kuroの覚え書き

96の個人的覚え書き

Raspberry Pi 3BにMX Linux

Raspberry Piの市場流通が減り、明らかに割高な価格で取引されてきたが、最近になってようやくちょっとまともな値段に戻ってきている。とはいえ現在主流のPi4ではもともと定価ベースでもそれなりに高額になってきており、単なるIoT制御基板としてはちょっとなあ、という感じになっている。
ということで未だにPi3Bを使い続けているのだが、こちらは4と並行して流通しているはずだが、まだ市場価格は落ち着いてきていない。
まあ、それはいいとして、Pi4が主流となっているせいか、公式OSであるRaspbianはなんだかどんどん肥大して、3BでGUIを動かすにはちょっと厳しくなってきているように思う。
3Bを使い続けている層はおそらくはデスクトップ環境とかには興味がなく、ただ組み込みLinux環境が動けばそれで十分、ということなんだろうか。わたしもPi3Bをデスクトップマシンとして常用する気はさらさらないのだが、実機で開発するときにはGUIも多少動いたほうがちょっと便利なきょくめんもあるよな、ということで純正Raspbianに見切りをつけて軽量なOSを探すこととした。
目についた候補はDietPiなんだが、アイコンがちょっとどうなの?というデザインで・・・(そこか!
で、ふと目に止まったMX Linuxを試してみることにした。
Pi Imagerには登録されていないので、まずはサイトからダウンロードしてくるところから。
MX-Linux - Browse /Community_Respins/Raspberry Pi at SourceForge.net
このMXRPi_22.03.08.imgをPi Imagerの「カスタムイメージを使う」、で選択して、インストールするだけ。
インストールに先立って歯車マークをクリックし、ホスト名とか、ユーザ、無線ネットワーク関係を前もって設定しておくと、インストールと同時にその設定もやってくれるのは便利だね。

さて、インストールが完了すると自動ログインでさっき作っておいたユーザでログインしてデスクトップが表示される。確かに動作は比較的キビキビした感じではある。ブラウザを開くとかそれなりに重い動作もあるけど、ターミナルを開いたり、設定を開いたりというくらいの動作ならサクサク動く。まあ基本ネットワークの設定とかsshの設定ができてしまえば、あとはリモートからsshとかVScodeとかでアクセスしてGUIは切ってしまってもいいんだけどね。

普通のRaspberry Pi Configもあるけど

MX Toolsというユーザー管理などができるツール

さらにツールバーにはsetting managerなんてのもあり、色々設定を操作できるがちょっとややこしい。

システム関連だと、タスクマネージャがあるのはちょっといいかも。

ちょっと気になったのはターミナルのフォントが幅広すぎて見にくいくらい、ロケールの変更に伴って使われている日本語フォントのせいかな。

ssh 鍵認証

ssh鍵認証でログインしようとしたら、

% ssh hogehoge
Unable to negotiate with xxx.xxx.xxx.xxx port 22: no matching host key type found. Their offer: ssh-rsa,ssh-dss
kex_exchange_identification: Connection closed by remote host
Connection closed by UNKNOWN port 65535

と出て、繋いでもらえなかった。

どうやらサーバ側はSHA-1RSA認証を使っていて、ローカル(クライアント)は廃止してしまっている、ということらしいので、
~/.ssh/configに

Host *
   HostKeyAlgorithms=+ssh-rsa
   PubkeyAcceptedAlgorithms=+ssh-rsa

この3行を追加したところ接続できるようになった。サーバ側もアップデートしたほうがセキュリティ上はいいだろうな。

ラズパイを無線ホストにする


ネット環境のない部屋にてラズパイによるデータ取得をする場合、データの回収にこまることがある。これまではそのためだけに無線ホスト(簡単には無線ルーター)をおいて、ラズパイをそこに無線または有線でつないで、別の無線端末(スマホとか)からホスト経由でsshとかウェブインターフェースで接続し、データ回収していた。ラズパイが無線ホストになってくれれば万事解決で話は早いんだけど、これまでラズパイのホスト化には成功していなかった。
今回久しぶりにトライしたところ、無事に構築できた。オマケとしてラズパイ自体をルーターとしてつかうことも可能となったので記録しておく。

やることは

  • dhcpcdを設定して無線LAN(wlan0)をstaticアドレスにする。
  • hostapdをインストールしてアクセスポイントにする。
  • dnsmasqをインストールしてDHCPサーバを建てる。
  • iptablesでポートフォワーディングすることでルーター化する。

最後の部分は今回の目的ではあくまでオマケだ。

設定としては無線ホストのアドレスを192.168.10.1とし、クライアントは192.168.10.11から192.168.10.50までにする。
DNSサーバはgoogleの8.8.8.8を利用。

使用したラズパイはRaspberry Pi 3B+
OSはRaspberry OS (64bitバージョン)Debian Bullseye

まずはdhcpcd
/etc/dhcpcd.confを編集

interface wlan0
static ip_address=192.168.10.1/24

次にhosted

$ sudo apt install hostapd 
$ sudo cp /usr/share/doc/hostapd/examples/hostapd.conf /etc/hostapd/hostapd.conf

/etc/hostapd/hostapd.confを編集

hw_mode=g
channel=6
wpa=2
auth_algs=1
wpa_key_mgmt=WPA-PSK
rsn_pairwise=CCMP
ssid=kurotest
wpa_passphrase=Hogehoge

かなかな長大なファイルだが、入力した&確認した&コメントを外したのは上記くらいだった。

/etc/default/hostapdを編集

DAEMON_CONF="/etc/hostapd/hostapd.conf"

hostapdを起動

$ sudo systemctl unmask hostapd
$ sudo systemctl restart hostapd 

DHCPサーバーとしてはisc-dhcp-serverをインストールして使っているページが多かったのだが、うちの環境ではうまく動かなかった。(起動に失敗する)代わりにdnsmasqを使う

$ sudo apt install -y dnsmasq

/etc/dnsmasq.d/wlan0.confを編集

interface = wlan0
dhcp-range = 192.168.10.11, 192.168.10.50, 255.255.255.0, 24h
dhcp-option = option:router, 192.168.10.1
dhcp-option = option:dns-server, 8.8.8.8
listen-address = 127.0.0.1
log-queries
log-dhcp
$ sudo systemctl restart dnsmasq

ここまででラズパイを無線LANアクセスポイントかつDHCPサーバとして使えるようになったので、他の端末からラズパイに無線で直接つながって、アドレスも自動で配布してもらってアクセスできるようになった。

以下はついでなのでルーターとして有線LANの側とも橋渡ししてもらえるようにしておく。有線側がネットワークにつながっていなくてもDHCPを割り振ってもらえるようにしている都合でブリッジではなくルーターモードだ。

まずは/etc/sysctl.confを編集

net.ipv4.ip_forward=1

ここのコメントを外す。
次に

$ sudo iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE

これでつながったはずなのだが、これでは起動するたびに同じコマンドを入れる必要があるため、

$ sudo sh -c "iptables-save > /etc/iptables.ipv4.nat"

として
/etc/rc.localの最後の行「exit 0」の前に

iptables-restore < /etc/iptables.ipv4.nat

を入れておく。

以上。

追記
iptablesの設定をrc.localに入れるとどうもhostapdがうまく機能しなくなる。
一旦は外しておく。
外に出ることが必要なときだけコマンドであとから設定してやることにする。あくまでルーター化はおまけなので。

PythonでGO解析

これまでGO解析はDAVIDを使ってきた。特に理由はないが、まあ老舗だし。しかしインターフェースがあんまり使いやすいとは言い難く、植物のデータベースもシロイヌナズナにしか対応していない。ということでAgriGOとか他のサービスを利用してもいいのだけれど、せっかくなのでローカル(もしくは自前サーバ)で使えるツールを構築してしまおう、ということにした。

PythonでGO解析をするツールとしてはGOATOOLSくらいしか見つからなかったし、結構使えそうなので、まずはこちらを試してみる。

github.com

インストールはpython moduleなので

$ python3 -m pip install goatools

とするだけ。
ただし、これだけではだめで、GO解析に必要なGOデータを記述したOBOファイルというものがいる

wget http://geneontology.org/ontology/go-basic.obo
wget http://www.geneontology.org/ontology/subsets/goslim_generic.obo

go-basic.oboがあればとりあえず良くて、goslim_generic.oboを使うと選択されるGOが抑えられるらしい。詳細は未調査。
このOBOファイルはデフォルトではスクリプトを実行するカレントディレクトリに置いておく必要があるが、オプションでファイルを指定することも可能そうだ。

スクリプトもインストールされるので

$ find_enrichment.py
usage: 
python find_enrichment.py study.file population.file gene-association.file

This program returns P-values for functional enrichment in a cluster of study
genes using Fisher's exact test, and corrected for multiple testing (including
Bonferroni, Holm, Sidak, and false discovery rate).

About significance cutoff:
--alpha: test-wise alpha; for each GO term, what significance level to apply
        (most often you don't need to change this other than 0.05 or 0.01)
--pval: experiment-wise alpha; for the entire experiment, what significance
        level to apply after Bonferroni correction

       [-h] [--annofmt {gene2go,gaf,gpad,id2gos}] [--taxid TAXID] [--alpha ALPHA] [--pval PVAL] [--pval_field PVAL_FIELD]
       [--outfile OUTFILE] [--ns NS] [--id2sym ID2SYM] [--sections SECTIONS] [--outfile_detail OUTFILE_DETAIL] [--compare]
       [--ratio RATIO] [--prt_study_gos_only] [--indent] [--obo OBO] [--no_propagate_counts] [-r]
       [--relationships [RELATIONSHIPS ...]] [--method METHOD] [--pvalcalc {fisher_scipy_stats}] [--min_overlap MIN_OVERLAP]
       [--goslim GOSLIM] [--ev_inc EV_INC] [--ev_exc EV_EXC] [--ev_help] [--ev_help_short]
       filenames filenames filenames

positional arguments:
  filenames             data/study data/population data/association

optional arguments:
  -h, --help            show this help message and exit
  --annofmt {gene2go,gaf,gpad,id2gos}
                        Annotation file format. Not needed if type can be determined using filename (default: None)
  --taxid TAXID         When using NCBI's gene2go annotation file, specify desired taxid (default: 9606)
  --alpha ALPHA         Test-wise alpha for multiple testing (default: 0.05)
  --pval PVAL           Only print results with uncorrected p-value < PVAL. Print all results, significant and otherwise, by setting
                        --pval=1.0 (default: 0.05)
  --pval_field PVAL_FIELD
                        Only print results when PVAL_FIELD < PVAL. (default: None)
  --outfile OUTFILE     Write enrichment results into xlsx or tsv file (default: None)
  --ns NS               Limit GOEA to specified branch categories. BP=Biological Process; MF=Molecular Function; CC=Cellular
                        Component (default: BP,MF,CC)
  --id2sym ID2SYM       ASCII file containing one geneid and its symbol per line (default: None)
  --sections SECTIONS   Use sections file for printing grouped GOEA results. Example SECTIONS values:
                        goatools.test_data.sections.gjoneska_pfenning goatools/test_data/sections/gjoneska_pfenning.py
                        data/gjoneska_pfenning/sections_in.txt (default: None)
  --outfile_detail OUTFILE_DETAIL
                        Write enrichment results into a text file containing the following information: 1) GOEA GO terms, grouped
                        into sections 2) List of genes and ASCII art showing section membership 3) Detailed list of each gene and GO
                        terms w/their P-values (default: None)
  --compare             the population file as a comparison group. if this flag is specified, the population is used as the study
                        plus the `population/comparison` (default: False)
  --ratio RATIO         only show values where the difference between study and population ratios is greater than this. useful for
                        excluding GO categories with small differences, but containing large numbers of genes. should be a value
                        between 1 and 2. (default: None)
  --prt_study_gos_only  Print GO terms only if they are associated with study genes. This is useful if printng all GO results
                        regardless of their significance (--pval=1.0). (default: False)
  --indent              indent GO terms (default: False)
  --obo OBO             Specifies location and name of the obo file (default: go-basic.obo)
  --no_propagate_counts
                        Do not propagate counts to parent terms (default: False)
  -r, --relationship    Propagate counts up all relationships, (default: False)
  --relationships [RELATIONSHIPS ...]
                        Propagate counts up user-specified relationships, which include: part_of regulates negatively_regulates
                        positively_regulates (default: None)
  --method METHOD       Available methods: local( bonferroni sidak holm fdr ) statsmodels( sm_bonferroni sm_sidak holm_sidak sm_holm
                        simes_hochberg hommel fdr_bh fdr_by fdr_tsbh fdr_tsbky fdr_gbs ) (default: bonferroni,sidak,holm,fdr_bh)
  --pvalcalc {fisher_scipy_stats}
                        fisher_scipy_stats (default: fisher_scipy_stats)
  --min_overlap MIN_OVERLAP
                        Check that a minimum amount of study genes are in the population (default: 0.7)
  --goslim GOSLIM       The GO slim file is used when grouping GO terms. (default: goslim_generic.obo)
  --ev_inc EV_INC       Include specified evidence codes and groups separated by commas (default: None)
  --ev_exc EV_EXC       Exclude specified evidence codes and groups separated by commas (default: None)
  --ev_help             Print all Evidence codes, with descriptions (default: True)
  --ev_help_short       Print all Evidence codes (default: True)

このような感じ。
ちなみにスクリプト

/home/linuxbrew/.linuxbrew/bin/find_enrichment.py

ここに入っている。
オプションが色々あるが基本的には

$ find_enrichment.py ./data/at_gene_list.txt ./data/at_all_gene_list.txt ./data/at_go_association.txt  --outfile=at_go_enrichment.tsv

がデフォルトセッティングで投げるフォーマットになる。
カレントディレクトリから一つ下がったdataディレクトリに入力する遺伝子のリストat_all_gene_list.txtと全遺伝子が一列に入っているat_all_gene_list.txtと遺伝子→GOの対応付けされたファイルat_go_association.txtを入れてある。
基本的に入力する遺伝子は全遺伝子リストに載っていないとだめで、全遺伝子リストに載っている遺伝子全部についてGOが対応付けされている必要があるらしい。
シロイヌナズナならまあ問題はないが情報の充実していない種ではすべての遺伝子にGOが割り振られているとは限らないので、まずはGOのついている遺伝子だけのリストを作成し、そのリストに載っている遺伝子だけを抽出して解析にかける必要がある。

import pandas as pd
df1 = pd.read_csv('/home/kuro/goatools/data/at_gene_list.txt', header=None)
df2 = pd.read_csv('/home/kuro/goatools/data/at_all_gene_list.txt', header=None)
df = pd.concat([df1,df2],axis=0)
df3 = df[df.duplicated()]
df3.to_csv('/home/kuro/goatools/data/at_gene_list1.txt', header=None, index=False)

このようなかんたんなPythonによる処理でGOのついている遺伝子だけを取り出してやる。

あとはhelpを見ながらオプションを色々いじってみる。p-valueを設定してリストするにしてもいろいろな統計方法のp-valueが選べるし、リストに表示する統計結果も増やしたり減らしたりできる。
デフォルトの統計方法はbonferroni,sidak,holm,fdr_bhの4つとなっており、まあデフォルトでほぼ問題はなさそうではある。
デフォルトではp_uncorrected<0.05となっているようで、ここをfdr_bhのp value <0.05にしてみたり、もっと数値を上げ下げしてみるといい場合があるだろう。

$ find_enrichment.py ./data/at_gene_list.txt ./data/at_all_gene_list.txt ./data/at_go_association.txt--pval=0.01 --method bonferroni,fdr_bh --pval_field fdr_bh --outfile=at_go_enrichment.tsv, at_go_enrichment.xlsx

みたいな感じだ。
ちなみに結果はtsv、xlsxをえらべ、両方を出力することも可能。結構柔軟だ。

Excelで値のペースト

Macexcelを使っていてよく使うのに一発でできるショートカットのないコマンドとして値のペーストがある。
数式を入れて計算した値だけを別のセルにコピーしたいとき、通常だとコマンド+Cでコピーしたあと、目的セルで右クリック→形式を選択してペースト→値というふうに選択しないとできない。もしくはコマンド+オプション+Vでメニューを出して、数値のラジオボタンをクリックしてOK、とやっぱり手間だし、3ボタンを押すのもかったるい。
そこでショートカットとして登録してしまおうというわけ。
メニューバーからツール→ショートカットキーのユーザー設定→分類からリボンにないコマンドを選択→値の貼り付けを選択。

現在のキー:に
Option+Control+V
Command+Option+V

というのが割り当てられているのだが、このキーコンビネーションでは先程あげたペーストメニューが出てくるだけでいきなり値だけペーストにはならない。
そこで
新しいショートカットキーを押してください:のところにカーソルをあわせ
Control+V
を入力する。
現在の割り当て:ペーストとなっているがペーストはMacユーザーなら迷わずCommand+Vなので気にしない。
Windowsユーザーと共有している場合は要注意)
あとは追加を押してOKで閉じる。

これでCommand+CしたあとControl+Vで値だけをペーストできるようになる。ひたすら単純作業をするときはすごく楽になること請け合い。

AlmaLinux8.7でopenMPI

私の用途としては大量のデータの処理、という方がメインなのでクラスタと言ってもノードをまたぐ並列処理よりもバッチシステムのほうがよく使う。しかしノードをまたぐような大規模解析も時々行うことがあって、これまではスパコンを使ってやっていた。せっかくなので新サーバではMPIも入れてみることにする。

大規模解析としてベイジアンネットワーク解析をするための環境を整える。
まずMPI環境としてopenMPI4.1.0を要求するようなので、それをインストールする。
dnfでも一応インストールできるっぽいが、ここはマニュアルでインストールすることにする。

まずはgccライブラリをインストール
これは全ノードでやる

$ sudo dnf groupinstall "Development Tools"
$ sudo dnf install gcc-gfortran

実はhomebrewでgccがインストールされていて、それがここでインストールするライブラリと競合してエラーを出すので一旦homebrewはアンインストールした。(実際今回のシステムではhomebrewでインストールしたプログラムは使っていない)

ヘッドノードにて

$ wget https://download.open-mpi.org/release/open-mpi/v4.1/openmpi-4.1.0.tar.bz2
$ tar xvf openmpi-4.1.0.tar.gz
$ cd openmpi-4.1.0
$ ./configure --prefix=/usr/local |& tee config.out
・・・・
$ make -j 8 |& tee make.out
・・・・
$ sudo make install |& tee install.out
・・・・
$ cd
$ nano .bashrc
##以下を追記する
##openmpi
MPIROOT=/usr/local/package/openmpi/4.1.0
export PATH=$PATH:$MPIROOT/bin
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$MPIROOT/lib

$ source .bashrc

## インストールの確認
$ which mpic++
/usr/local/package/openmpi/4.1.0/bin/mpic++
$ which mpirun
/usr/local/package/openmpi/4.1.0/bin/mpirun

テストプログラムhello.cpp

#include <iostream>
#include <mpi.h>
#include <stdio.h>

int main(int argc, char **argv)
{
  int rank, size;
  MPI_Init(&argc, &argv);
  // MPI::Init(argc, argv);

  MPI_Comm_rank(MPI_COMM_WORLD, &rank);
  MPI_Comm_size(MPI_COMM_WORLD, &size);
  // rank = MPI::COMM_WORLD.Get_rank();
  // size = MPI::COMM_WORLD.Get_size();

  std::cout << "rank = " << rank << std::endl;
  std::cout << "size = " << size << std::endl;

  MPI_Finalize();
  // MPI::Finalize();
}

ビルドして動かしてみる

$ mpic++ hello.cpp -o hello
$ mpirun -np 2 ./hello
rank = 0
size = 2
rank = 1
size = 2
  • ヘッドノードで公開鍵の設定

ノード間並列処理をするには公開鍵を登録してパスワード無しで計算ノードにアクセスできるようにして置かなければならない。

$ cd .ssh/
$ ssh-keygen #パスワードは空欄のままにする。ここでパスワードを入れると結局パスワードを入力しないとログインできない。
$ cat ~/.ssh/id_rsa.pub >> ~/.ssh/authorized_keys
$ echo "StrictHostKeyChecking no" >> ~/.ssh/config
$ chmod 600 ~/.ssh/id_rsa
$ chmod 600 ~/.ssh/authorized_keys
$ chmod 700 ~/.ssh/
$ chmod 600 ~/.ssh/config

## sshできるかテスト
$ ssh k2-inspur-a6

ノード間並列計算テストプログラムhello2.cpp

#include <stdio.h>
#include "mpi.h"
 
int main( int argc, char *argv[] )
{
    int     rank, size, len;
    char    name[MPI_MAX_PROCESSOR_NAME];
 
    MPI_Init( &argc, &argv );
    MPI_Comm_rank( MPI_COMM_WORLD, &rank );
    MPI_Comm_size( MPI_COMM_WORLD, &size );
    MPI_Get_processor_name( name, &len );
    name[len] = '\0';
 
    printf( "Hello world: rank %d of %d running on %s\n", rank, size, name );
 
    MPI_Finalize();
    return 0;
}
$ nano hostfile
## HyperthreadingはMPIでは効率が逆に低下するのでslotsには物理コア数以下を記載する。
k1-inspur-a6 slots=1
k2-inspur-a6 slots=1
k3-inspur-a6 slots=1

$ mpic++ hello2.cpp -o hello2
$ sudo systemctl stop firewalld #ファイアウォールは止めなければならない
$ mpirun --hostfile hostfile -n 3 ./hello2 
Hello world: rank 0 of 3 running on k1-inspur-a6.klab.kuro.jp
Hello world: rank 2 of 3 running on k3-inspur-a6.klab.kuro.jp
Hello world: rank 1 of 3 running on k2-inspur-a6.klab.kuro.jp

AlmaLinux8.7でサーバクラスタを構築する

さて、サーバ間でユーザとディレクトリを共有できるようになったので、次にジョブスケジューラを導入してサーバクラスタとしたい。
これまでCentOS7ではTORQUEを使ってきたのだが、どうも8系以降ではインストールができないらしい。有料のSGEという選択肢もあるが、今どきのスパコンでもTOP500でシェアを伸ばしているらしいSlurmを使うことにする。しかし日本語の情報はあまりないようだ。本家配布サイトのドキュメントは充実しているが、充実しすぎて難しい。とっつきにくい。

ヘッドノード:k1-inspur-a6
計算ノード:k2-inspur-a6, k3-inspur-a6

  • 共通ユーザーの準備とmunge keyの準備
[root@k1-inspur-a6 ~]# groupadd -g 5000 slurm
# useradd -M -d /var/lib/slurm -s /sbin/nologin -u 5000 -g slurm slurm
# groupadd -g 5001 munge
# useradd -M -d /var/lib/munge -s /bin/bash -u 5001 -g munge munge
# id munge
uid=5001(munge) gid=5001(munge) groups=5001(munge)
# id slurm
uid=5000(slurm) gid=5000(slurm) groups=5000(slurm)

# mkdir -p /var/lib/slurm
# mkdir -p /var/lib/slurm/spool
# mkdir -p /var/log/slurm
# chown -R slurm:slurm /var/lib/slurm
# chown -R slurm:slurm /var/log/slurm

# ssh -l root k2-inspur-a6 'mkdir -p /var/lib/slurm'
# ssh -l root k2-inspur-a6 'mkdir -p /var/lib/slurm/spool'
# ssh -l root k2-inspur-a6 'mkdir -p /var/log/slurm'
# ssh -l root k2-inspur-a6 'chown -R slurm:slurm /var/lib/slurm'
# ssh -l root k2-inspur-a6 'chown -R slurm:slurm /var/log/slurm'

#同じ操作をk3-inspur-a6でも行う

# mungeのインストール
# dnf install munge
・・・・
================================================================================
 パッケージ         Arch           バージョン           リポジトリー      サイズ
================================================================================
インストール:
 munge              x86_64         0.5.13-2.el8         appstream         121 k
依存関係のインストール:
 munge-libs         x86_64         0.5.13-2.el8         appstream          29 k
・・・・
## munge keyの生成
# /usr/sbin/create-munge-key 
Generating a pseudo-random key using /dev/urandom completed.

# systemctl enable --now munge.service
Created symlink /etc/systemd/system/multi-user.target.wants/munge.service → /usr/lib/systemd/system/munge.service.

## mungeを計算ノードにもインストール
# ssh -l root k2-inspur-a6 'dnf install munge -y'
・・・・
## munge keyを計算ノードにコピー
# scp /etc/munge/munge.key root@k2-inspur-a6:/etc/munge/munge.key
# ssh -l root k2-inspur-a6 'chown munge. /etc/munge/munge.key'

## 計算ノードでmungeを起動
# ssh -l root k2-inspur-a6 'systemctl enable --now munge'

Created symlink /etc/systemd/system/multi-user.target.wants/munge.service → /usr/lib/systemd/system/munge.service.

## 同じ操作をk3-inspur-a6でも行う
  • Slurmのインストール

PowerToolsリポジトリを有効化する必要がある。

# dnf config-manager --set-enabled powertools
# dnf repolist --all | grep PowerTools
powertools                     AlmaLinux 8 - PowerTools                   有効化
powertools-debuginfo           AlmaLinux 8 - PowerTools debuginfo         無効化
powertools-source              AlmaLinux 8 - PowerTools Source            無効化

## パッケージslurmはすべてのノードに必要
# dnf -y install slurm
・・・・
================================================================================
 パッケージ                   Arch     バージョン            リポジトリー サイズ
================================================================================
インストール:
 slurm                        x86_64   20.11.9-1.el8         epel         1.8 M
依存関係のインストール:
 Lmod                         x86_64   8.7.19-1.el8          epel         263 k
 freeipmi                     x86_64   1.6.8-1.el8           baseos       2.1 M
 hdf5                         x86_64   1.10.5-4.el8          epel         2.1 M
 hwloc-libs                   x86_64   2.2.0-3.el8           baseos       2.0 M
 infiniband-diags             x86_64   41.0-1.el8            baseos       322 k
 libaec                       x86_64   1.0.2-3.el8           powertools    39 k
 libgfortran                  x86_64   8.5.0-16.el8_7.alma   baseos       643 k
 libibumad                    x86_64   41.0-1.el8            baseos        32 k
 libjwt                       x86_64   1.12.1-7.el8          epel          28 k
 libquadmath                  x86_64   8.5.0-16.el8_7.alma   baseos       171 k
 lua-filesystem               x86_64   1.6.3-7.el8           powertools    35 k
 lua-posix                    x86_64   33.3.1-9.el8          powertools   176 k
 lua-term                     x86_64   0.07-9.el8            epel          16 k
 mariadb-connector-c          x86_64   3.1.11-2.el8_3        appstream    199 k
 mariadb-connector-c-config   noarch   3.1.11-2.el8_3        appstream     14 k
 munge                        x86_64   0.5.13-2.el8          appstream    121 k
 munge-libs                   x86_64   0.5.13-2.el8          appstream     29 k
 pmix                         x86_64   2.2.5-1.el8           appstream    739 k
 slurm-libs                   x86_64   20.11.9-1.el8         epel         1.0 M
 tcl                          x86_64   1:8.6.8-2.el8         baseos       1.1 M
・・・・
# ssh -l root k2-inspur-a6 'dnf install slurm -y'
# ssh -l root k3-inspur-a6 'dnf install slurm -y'

## 管理ノードにはslurm-slurmctldが必要
# dnf install slurm-slurmctld
・・・・
================================================================================
 パッケージ             Arch          バージョン              Repo        サイズ
================================================================================
インストール:
 slurm-slurmctld        x86_64        20.11.9-1.el8           epel        453 k
・・・・

## 計算ノードにはslurm-slurmdが必要
# dnf install slurm-slurmd
・・・・================================================================================
 パッケージ           Arch           バージョン              リポジトリー サイズ
================================================================================
インストール:
 slurm-slurmd         x86_64         20.11.9-1.el8           epel         196 k
・・・・

# ssh -l root k2-inspur-a6 'dnf install slurm-slurmd -y'
# ssh -l root k3-inspur-a6 'dnf install slurm-slurmd -y'

## 計算ノードにはslurm-pam_slurmも入れたほうがいい?
# dnf install slurm-pam_slurm
・・・・
================================================================================
 パッケージ             Arch          バージョン              Repo        サイズ
================================================================================
インストール:
 slurm-pam_slurm        x86_64        20.11.9-1.el8           epel         30 k
・・・・

# ssh -l root k2-inspur-a6 'dnf install slurm-pam_slurm -y'
# ssh -l root k3-inspur-a6 'dnf install slurm-pam_slurm -y'

## ジョブ投入ノードにはslurm-torque、slurm-openlavaを入れたほうがいい?
# dnf install slurm-torque
・・・・================================================================================
 パッケージ            Arch           バージョン             リポジトリー サイズ
================================================================================
インストール:
 slurm-torque          x86_64         20.11.9-1.el8          epel          67 k
依存関係のインストール:
 slurm-perlapi         x86_64         20.11.9-1.el8          epel         184 k
・・・・

# dnf install slurm-openlava
・・・・================================================================================
 パッケージ             Arch           バージョン            リポジトリー サイズ
================================================================================
インストール:
 slurm-openlava         x86_64         20.11.9-1.el8         epel          30 k
・・・・
  • 設定
# nano /etc/slurm/slurm.conf

#
# See the slurm.conf man page for more information.
#
ControlMachine=k1-inspur-a6
ControlAddr=10.0.1.90
#BackupController=
#BackupAddr=
#
AuthType=auth/munge
#CheckpointType=checkpoint/none
CryptoType=crypto/munge
#DisableRootJobs=NO
#EnforcePartLimits=NO
#Epilog=
#EpilogSlurmctld=
#FirstJobId=1
#MaxJobId=999999
#GresTypes=
#GroupUpdateForce=0
#GroupUpdateTime=600
#JobCheckpointDir=/var/slurm/checkpoint
#JobCredentialPrivateKey=
#JobCredentialPublicCertificate=
#JobFileAppend=0
#JobRequeue=1
#JobSubmitPlugins=
#KillOnBadExit=0
#LaunchType=launch/slurm
#Licenses=foo*4,bar
#MailProg=/bin/true
#MaxJobCount=5000
#MaxStepCount=40000
#MaxTasksPerNode=128
MpiDefault=pmix
#MpiParams=ports=#-#
#PluginDir=
#PlugStackConfig=
#PrivateData=jobs
ProctrackType=proctrack/cgroup
#Prolog=
#PrologFlags=
#PrologSlurmctld=
#PropagatePrioProcess=0
#PropagateResourceLimits=
#PropagateResourceLimitsExcept=
#RebootProgram=
ReturnToService=1
#SallocDefaultCommand=
SlurmctldPidFile=/var/run/slurm/slurmctld.pid
SlurmctldPort=6817
SlurmdPidFile=/var/run/slurm/slurmd.pid
SlurmdPort=6818
SlurmdSpoolDir=/var/spool/slurm/d
SlurmUser=root
#SlurmdUser=root
#SrunEpilog=
#SrunProlog=
StateSaveLocation=/var/spool/slurm/ctld
SwitchType=switch/none
#TaskEpilog=
TaskPlugin=task/none
#TaskPluginParam=
#TaskProlog=
#TopologyPlugin=topology/tree
#TmpFS=/tmp
#TrackWCKey=no
#TreeWidth=
#UnkillableStepProgram=
#UsePAM=0
#
#
# TIMERS
#BatchStartTimeout=10
#CompleteWait=0
#EpilogMsgTime=2000
#GetEnvTimeout=2
#HealthCheckInterval=0
#HealthCheckProgram=
InactiveLimit=0
KillWait=30
#MessageTimeout=10
#ResvOverRun=0
MinJobAge=300
#OverTimeLimit=0
SlurmctldTimeout=120
SlurmdTimeout=300
#UnkillableStepTimeout=60
#VSizeFactor=0
Waittime=0
#
#
# SCHEDULING
#DefMemPerCPU=0
#FastSchedule=1
#MaxMemPerCPU=0
#SchedulerTimeSlice=30
SchedulerType=sched/backfill
SelectType=select/cons_tres
SelectTypeParameters=CR_Core
#
#
# JOB PRIORITY
#PriorityFlags=
#PriorityType=priority/basic
#PriorityDecayHalfLife=
#PriorityCalcPeriod=
#PriorityFavorSmall=
#PriorityMaxAge=
#PriorityUsageResetPeriod=
#PriorityWeightAge=
#PriorityWeightFairshare=
#PriorityWeightJobSize=
#PriorityWeightPartition=
#PriorityWeightQOS=
#
#
# LOGGING AND ACCOUNTING
#AccountingStorageEnforce=0
#AccountingStorageHost=
#AccountingStorageLoc=
#AccountingStoragePass=
#AccountingStoragePort=
AccountingStorageType=accounting_storage/none
#AccountingStorageUser=
AccountingStoreJobComment=YES
ClusterName=cluster
#DebugFlags=
#JobCompHost=
#JobCompLoc=
#JobCompPass=
#JobCompPort=
JobCompType=jobcomp/none
#JobCompUser=
#JobContainerType=job_container/none
JobAcctGatherFrequency=30
JobAcctGatherType=jobacct_gather/cgroup
SlurmctldDebug=3
SlurmctldLogFile=/var/log/slurmctld.log
SlurmdDebug=3
SlurmdLogFile=/var/log/slurmd.log
#SlurmSchedLogFile=
#SlurmSchedLogLevel=
#
#
# POWER SAVE SUPPORT FOR IDLE NODES (optional)
#SuspendProgram=
#ResumeProgram=
#SuspendTimeout=
#ResumeTimeout=
#ResumeRate=
#SuspendExcNodes=
#SuspendExcParts=
#SuspendRate=
#SuspendTime=
#
#
# COMPUTE NODES
NodeName=k1-inspur-a6 CPUs=48 Sockets=1 CoresPerSocket=24 ThreadsPerCore=2 State=UNKNOWN
NodeName=k2-inspur-a6 CPUs=48 Sockets=1 CoresPerSocket=24 ThreadsPerCore=2 State=UNKNOWN
NodeName=k3-inspur-a6 CPUs=48 Sockets=1 CoresPerSocket=24 ThreadsPerCore=2 State=UNKNOWN
PartitionName=work Nodes=ALL OverSubscribe=FORCE Default=YES MaxTime=INFINITE State=UP

# scp /etc/slurm/slurm.conf k2-inspur-a6:/etc/slurm/
# scp /etc/slurm/slurm.conf k3-inspur-a6:/etc/slurm/
  • 起動

管理ノード(兼計算ノード)

# systemctl start slurmd slurmctld
# systemctl status slurmd
● slurmd.service - Slurm node daemon
   Loaded: loaded (/usr/lib/systemd/system/slurmd.service; disabled; vendor pre>
   Active: active (running) since Sun 2023-03-05 23:36:49 JST; 3s ago
 Main PID: 98292 (slurmd)
    Tasks: 1
   Memory: 1.4M
   CGroup: /system.slice/slurmd.service
           └─98292 /usr/sbin/slurmd -D

 3月 05 22:36:49 k1-inspur-a6.kuro.jp systemd[1]: Started Slurm node d>
lines 1-10/10 (END)

# systemctl status slurmctld
● slurmctld.service - Slurm controller daemon
   Loaded: loaded (/usr/lib/systemd/system/slurmctld.service; disabled; vendor >
   Active: active (running) since Sun 2023-03-05 22:38:23 JST; 55min ago
 Main PID: 96873 (slurmctld)
    Tasks: 7
   Memory: 3.8M
   CGroup: /system.slice/slurmctld.service
           └─96873 /usr/sbin/slurmctld -D

 3月 05 22:38:23 k1-inspur-a6.kuro.jp systemd[1]: Started Slurm contro>
lines 1-10/10 (END)

# firewall-cmd --add-port=6817-6818/tcp --zone=public --permanent
# firewall-cmd --reload

計算ノード

# systemctl start slurmd
# firewall-cmd --add-port=6818/tcp --zone=public --permanent
# firewall-cmd --reload

管理ノードで確認

# sinfo
PARTITION AVAIL  TIMELIMIT  NODES  STATE NODELIST
work*        up   infinite      3   idle k1-inspur-a6,k2-inspur-a6,k3-inspur-a6
# sinfo -N -l
Mon Mar 06 00:23:42 2023
NODELIST       NODES PARTITION       STATE CPUS    S:C:T MEMORY TMP_DISK WEIGHT AVAIL_FE REASON              
k1-inspur-a6      1     work*        idle 48     1:24:2      1        0      1   (null) none                
k2-inspur-a6      1     work*        idle 48     1:24:2      1        0      1   (null) none                
k3-inspur-a6      1     work*        idle 48     1:24:2      1        0      1   (null) none

ノードの構成を確認

$ scontrol show node
NodeName=k1-inspur-a6 Arch=x86_64 CoresPerSocket=24 
   CPUAlloc=0 CPUTot=48 CPULoad=0.03
   AvailableFeatures=(null)
   ActiveFeatures=(null)
   Gres=(null)
   NodeAddr=k1-inspur-a6 NodeHostName=k1-inspur-a6 Version=20.11.9
   OS=Linux 4.18.0-425.13.1.el8_7.x86_64 #1 SMP Tue Feb 21 04:20:52 EST 2023 
   RealMemory=1 AllocMem=0 FreeMem=254216 Sockets=1 Boards=1
   State=IDLE ThreadsPerCore=2 TmpDisk=0 Weight=1 Owner=N/A MCS_label=N/A
   Partitions=work 
   BootTime=2023-03-01T17:38:17 SlurmdStartTime=2023-03-06T00:18:23
   CfgTRES=cpu=48,mem=1M,billing=48
   AllocTRES=
   CapWatts=n/a
   CurrentWatts=0 AveWatts=0
   ExtSensorsJoules=n/s ExtSensorsWatts=0 ExtSensorsTemp=n/s
   Comment=(null)

NodeName=k2-inspur-a6 Arch=x86_64 CoresPerSocket=24 
   CPUAlloc=0 CPUTot=48 CPULoad=0.01
   AvailableFeatures=(null)
   ActiveFeatures=(null)
   Gres=(null)
   NodeAddr=k2-inspur-a6 NodeHostName=k2-inspur-a6 Version=20.11.9
   OS=Linux 4.18.0-425.13.1.el8_7.x86_64 #1 SMP Tue Feb 21 04:20:52 EST 2023 
   RealMemory=1 AllocMem=0 FreeMem=255960 Sockets=1 Boards=1
   State=IDLE ThreadsPerCore=2 TmpDisk=0 Weight=1 Owner=N/A MCS_label=N/A
   Partitions=work 
   BootTime=2023-03-01T12:21:56 SlurmdStartTime=2023-03-06T00:18:01
   CfgTRES=cpu=48,mem=1M,billing=48
   AllocTRES=
   CapWatts=n/a
   CurrentWatts=0 AveWatts=0
   ExtSensorsJoules=n/s ExtSensorsWatts=0 ExtSensorsTemp=n/s
   Comment=(null)

NodeName=k3-inspur-a6 Arch=x86_64 CoresPerSocket=24 
   CPUAlloc=0 CPUTot=48 CPULoad=0.00
   AvailableFeatures=(null)
   ActiveFeatures=(null)
   Gres=(null)
   NodeAddr=k3-inspur-a6 NodeHostName=k3-inspur-a6 Version=20.11.9
   OS=Linux 4.18.0-425.13.1.el8_7.x86_64 #1 SMP Tue Feb 21 04:20:52 EST 2023 
   RealMemory=1 AllocMem=0 FreeMem=255896 Sockets=1 Boards=1
   State=IDLE ThreadsPerCore=2 TmpDisk=0 Weight=1 Owner=N/A MCS_label=N/A
   Partitions=work 
   BootTime=2023-03-01T18:01:07 SlurmdStartTime=2023-03-06T00:17:26
   CfgTRES=cpu=48,mem=1M,billing=48
   AllocTRES=
   CapWatts=n/a
   CurrentWatts=0 AveWatts=0
   ExtSensorsJoules=n/s ExtSensorsWatts=0 ExtSensorsTemp=n/s
   Comment=(null)

Slurmによるバッチファイルの実行方法はSGE/torqueと若干違っている。
まず投入コマンドがqsubではなくsbatchである。

$sbatch -a 0-9:1 test_batch.sh

のような書式が基本スタイルでqsubで-tで与えていたタスクIDが-aとなっている。(:1を2にしたら2ID番号ごとに飛び飛びに実行される)

#!/bin/sh
#SBATCH -c 8 #1タスクで使用するCPU
#SBATCH -J test230331 #ジョブにつけた名前
#SBATCH -o %x_%j.log #標準出力をファイルに書き出し。-eをつけないとエラーログも同じファイルに書き出す
#SBATCH -a 518  #タスクIDは中に書いておくことも可能

バッチファイルの頭にこのような感じで記述をしておくのはqsubと似たような感じ。
%xはジョブ名、%jはジョブID、%AはアレイジョブID、%aはアレイタスクIDに置換。
ジョブ名を設定していないとスクリプト名がそのまま使われる。


一度に投入できるタスクはデフォルトでは

$ scontrol show config | grep MaxArraySize
MaxArraySize            = 1001

となっており1001-1=1000タスクとなっている。/etc/slurm/slurm.confで書き換えることも可能だ。

ジョブの実行状況を確認するコマンドはqstatに対しsqueueとなっている。

アレイジョブ内で利用できる環境変数
SLURM_ARRAY_JOB_ID   アレイジョブのID
SLURM_ARRAY_TASK_ID   アレイジョブのタスクID
SLURM_ARRAY_TASK_COUNT   アレイジョブのタスク数
SLURM_ARRAY_TASK_MIN   アレイジョブの最初のタスクID
SLURM_ARRAY_TASK_MAX   アレイジョブの最後のタスクID
などなので特にタスクIDを使ってファイルを参照するとかに使用できる。

line=${SLURM_ARRAY_TASK_ID}

など。

AlmaLinux8.7に移行

新しいサーバマシンが導入されたため、環境をセットアップする。
これまでサーバはCentOS7を並列クラスタ、データベース用に使用し、AlphaFold2用GPUサーバに限ってUbuntu20.04をインストールしていた。
CentOS7のサポート期限が来年ということで、5年はあまり環境をいじらず使いたいので、バージョンを上げたいのだが、CentOS8はすでにサポートを切られてしまった。
そもそもCentOSの存在意義が変わってしまったので、いっそ他のディストリビューションに移行しようと思う。
候補としてUbuntuも考えたが、あんまり安定志向でないし、yumからaptに移るのもなんだかなあ、というわけでやめた。
RHELにすりゃいいっちゃあいいが、サブスクで使うならそもそもハードウェアもAWSでいいんじゃん、ってなわけで却下。
となるとRPM系でいくならOpenSUSE、Rocky Linux、AlmaLinux辺りだろう。で、今回AlmaLinuxを採用することにした。
バージョンはすでに9系まで行っているが、安定志向なので、あえての8系にとどめておくことにする。

  • サーバの構成

INSPUR NF3280A6 (AMD EPYC 7413 24C/48T)
memory: 256G
storage: 64TB RAID5

INSPUR NF3180A6 (AMD EPYC 7413 24C/48T)
memory: 256G
storage: 480 G SSD

INSPUR NF3180A6 (AMD EPYC 7413 24C/48T)
memory: 256G
storage: 480 G SSD

NF3280A6をヘッドノード兼用とした3ノードクラスタ。ネットワークは10Gイーサネットで構築。

  • OSのインストール

インストールは普通にDVDに焼いたインストーラで実施。(AlmaLinux 8.7)
ヘッドノードはサーバー版(GUI)をインストール。計算ノードは最小インストールを選択。
インストーラーはCentOS7のときと何ら変わっていないので間違いようがない。
RAIDの構成は別途必要。

klab.kuro.jp(仮)

  • ネットワーク構成
IPv4         hostname
10.0.1.90    k1-inspur-a6
10.0.1.89    k2-inspur-a6
10.0.1.88    k3-inspur-a6
  • NFSサーバ・NISサーバをインストール

ヘッドノードはHDDでRAIDを組んでおり、ファイルサーバも兼ねてもらう。
NISはRHEL8系では非推奨だが、ジョブスケジューラを使ったクラスタを構築する上で、設定が容易なので、当面はこれを使用することにする。
一般ユーザもこのヘッドノードサーバのみに作成する。

## SELINUXを無効化しておく
# nano /etc/selinux/config
# This file controls the state of SELinux on the system.
# SELINUX= can take one of these three values:
#     enforcing - SELinux security policy is enforced.
#     permissive - SELinux prints warnings instead of enforcing.
#     disabled - No SELinux policy is loaded.
## 下行を変更
SELINUX=disabled
# SELINUXTYPE= can take one of these two values:
#     targeted - Targeted processes are protected,
#     minimum - Modification of targeted policy. Only selected processes are protected.
#     mls - Multi Level Security protection.
SELINUXTYPE=targeted

## 再起動して変更を有効にする
# reboot

# NFS サーバーの設定
# dnf -y install nfs-utils rpcbind
# nano /etc/idmapd.conf

## 5行目:コメント解除して自ドメイン名に変更
Domain = klab.kuro.jp

## NFS 共有に設定
# nano /etc/exports

/usr/local 10.0.1.0/24(rw,no_root_squash)
/home 10.0.1.0/24(rw,no_root_squash)

# systemctl enable --now rpcbind nfs-server 

## FirewalldにNFSサービスを許可
# firewall-cmd --add-service=nfs --permanent
# firewall-cmd --reload

## Ypserv をインストールして NIS サーバーを設定
# dnf -y install ypserv
# ypdomainname klab.kuro.jp
# nano /etc/sysconfig/network

NISDOMAIN=klab.kuro.jp
YPSERV_ARGS="-p 944"
YPXFRD_ARGS="-p 945"    #NIS関連サービスのポートを固定

## アクセス許可する NIS クライアントの範囲を指定
# nano /var/yp/securenets

255.0.0.0       127.0.0.0
255.255.255.0   10.0.1.0

## NIS ドメインに属するホストを登録 (サーバー/クライアント)
# nano /etc/hosts

127.0.0.1   localhost localhost.localdomain localhost4 localhost4.localdomain4
::1         localhost localhost.localdomain localhost6 localhost6.localdomain6

10.0.1.90 k1-inspur-a6.klab.kuro.jp k1-inspur-a6
10.0.1.89 k2-inspur-a6.klab.kuro.jp k2-inspur-a6
10.0.1.88 k3-inspur-a6.klab.kuro.jp k3-inspur-a6

# systemctl enable --now rpcbind ypserv ypxfrd yppasswdd nis-domainname

## NIS データベース更新
# /usr/lib64/yp/ypinit -m

At this point, we have to construct a list of the hosts which will run NIS
servers.  k1-inspur-a6. klab.kuro.jp is in the list of NIS server hosts.  Please continue to add
the names for the other hosts, one per line.  When you are done with the
list, type a <control D>.
        next host to add:  k1-inspur-a6.klab.kuro.jp
        next host to add:  # Ctrl + D キーを入力
The current list of NIS servers looks like this:

k1-inspur-a6. klab.kuro.jp

Is this correct?  [y/n: y]  y
We need a few minutes to build the databases...
Building /var/yp/srv.world/ypservers...
Running /var/yp/Makefile...
gmake[1]: Entering directory '/var/yp/klab.kuro.jp'
Updating passwd.byname...
Updating passwd.byuid...
Updating group.byname...
Updating group.bygid...
Updating hosts.byname...
Updating hosts.byaddr...
Updating rpc.byname...
Updating rpc.bynumber...
Updating services.byname...
Updating services.byservicename...
Updating netid.byname...
Updating protocols.bynumber...
Updating protocols.byname...
Updating mail.aliases...
gmake[1]: Leaving directory '/var/yp/klab.kuro.jp'

k1-inspur-a6. klab.kuro.jp has been set up as a NIS master server.

Now you can run ypinit -s k1-inspur-a6.klab.kuro.jp on all slave server.

## [/etc/hosts] へ登録した新規ホストをNISデータベースへ反映する
# cd /var/yp
# make 

## Firewalldに許可設定
# nano /etc/sysconfig/yppasswdd
## 該当行に追記
YPPASSWDD_ARGS="--port 950"

# systemctl restart rpcbind ypserv ypxfrd yppasswdd
# firewall-cmd --add-service=rpc-bind --permanent 
# firewall-cmd --add-port={944-951/tcp,944-951/udp} --permanent 
# firewall-cmd --reload 

計算ノードにNFSNISクライアントをインストールする

## NFSクライアントをインストール・設定
# dnf -y install nfs-utils

# nano /etc/idmapd.conf
## 5行目:コメント解除して自ドメイン名に変更
Domain = klab.kuro.jp

## 起動時にマウントするように設定
# nano /etc/fstab

/dev/mapper/almalinux-root /                       xfs     defaults        0 0
UUID=****************** /boot                   xfs     defaults        0 0
UUID=*************         /boot/efi               vfat    umask=0077,shortname=winnt 0 2
/dev/mapper/almalinux-home /home                   xfs     defaults        0 0
/dev/mapper/almalinux-swap none                    swap    defaults        0 0
## 以下に追記
k1-inspur-a6:/usr/local        /usr/local	nfs     defaults        0 0
k1-inspur-a6:/home             /home           nfs     defaults        0 0

## マウントポイントへのアクセス時に、動的に NFS 共有をマウントする
# dnf -y install autofs

# nano /etc/auto.master
## 最終行に追記
 /-    /etc/auto.mount

# nano /etc/auto.mount
## 新規作成 : [マウントポイント] [オプション] [ロケーション]
 /home -fstype=nfs,rw k1-inspur-a6:/home

## NISクライアントのインストールと設定
# dnf -y install ypbind rpcbind oddjob-mkhomedir
# ypdomainname klab.kuro.jp
# nano /etc/sysconfig/network

NISDOMAIN= klab.kuro.jp

# nano /etc/yp.conf
## 最終行に追記
# [domain (NIS ドメイン) server (NIS サーバー)]
domain klab.kuro.jp server k1-inspur-a6. klab.kuro.jp

# authselect select nis --force 
Backup stored at /var/lib/authselect/backups/2019-10-17-01-18-26.zBmEkS
Profile "nis" was selected.
The following nsswitch maps are overwritten by the profile:
- aliases
- automount
- ethers
- group
- hosts
- initgroups
- netgroup
- networks
- passwd
- protocols
- publickey
- rpc
- services
- shadow

Make sure that NIS service is configured and enabled. See NIS documentation for more information.

# systemctl enable --now rpcbind ypbind nis-domainname oddjobd 
# exit
  • Slurmのインストール

NF3280A6 (k1-inspur-a6)を管理ノード、ジョブ投入ノード兼計算ノードとし、
NF3180A6 (k2-inspur-a6、k3-inspur-a6)を計算ノードとする。

続く。

Raspberry Pi PicoでI2C OLED

ようやくI2Cで接続して通信できるようになったPicoだが、OLED (SSD1306)に表示するのにはなかなか成功していなかった。
Adafruit_SSD1306.hをつかってみたり、ACROBOTIC_SSD1306.hを使ってみたりしたが、いずれもコンパイルでエラーとなって表示できなかった。
最終的にはU8g2ライブラリを使って表示に成功した。

テストコードは

#include <Wire.h>
#include <U8g2lib.h>
U8G2_SSD1306_128X64_NONAME_F_HW_I2C u8g2(U8G2_R0, /* reset=*/U8X8_PIN_NONE);

void setup() {
  Serial.begin(115200);
  Wire.setSDA(16);
  Wire.setSCL(17);
  Wire.begin();

  u8g2.begin();  // OLED初期化
  u8g2.setContrast(1);

  u8g2.clearBuffer();
  u8g2.setFont(u8g2_font_crox1hb_tf);
  u8g2.drawStr(0, 17, "Hello world");
  u8g2.sendBuffer();

}

void loop() {
  // put your main code here, to run repeatedly:

}

参考にしたページは
aloseed.com

Raspberry Pi Picoを使う 〜I2C RTC編〜

買ってはみたもののイマイチ使いこなせてないRaspberry Pi Picoをどうにか使いこなしたい。micropythonでやるのが王道なんだろうけどマイコンはすっかりArduinoに馴染んでいるためArduino IDEでどうにかしたいところ。

まずは
Raspberry Pi Pico (RP2040) のArduino IDEでの使い方 | STEAM Tokyo
こちらを参考にしてIDEにRP2040デバイス用のArduinoコア、arduino-picoをインストールする。

手始めにファイル>スケッチ例>rp2040からLEDのFadeをロードしてみる。

int led = LED_BUILTIN; // the PWM pin the LED is attached to
int brightness = 0;    // how bright the LED is
int fadeAmount = 5;    // how many points to fade the LED by

// the setup routine runs once when you press reset:
void setup() {
  // declare pin to be an output:
  pinMode(led, OUTPUT);
}

// the loop routine runs over and over again forever:
void loop() {
  // set the brightness
  analogWrite(led, brightness);

  // change the brightness for next time through the loop:
  brightness = brightness + fadeAmount;

  // reverse the direction of the fading at the ends of the fade:
  if (brightness <= 0 || brightness >= 255) {
    fadeAmount = -fadeAmount;
  }
  // wait for 30 milliseconds to see the dimming effect
  delay(30);
}

これはなんの問題もなく動くね。

次にI2Cの制御としてDS3231のRTCをつないでみる。

ファイル>スケッチ例>DS3232>rtcTimeTempを試す。

元の内容は

// Arduino DS3232RTC Library
// https://github.com/JChristensen/DS3232RTC
// Copyright (C) 2019 by Jack Christensen and licensed under
// GNU GPL v3.0, https://www.gnu.org/licenses/gpl.html
//
// Example sketch to display time and temperature.
//
// Jack Christensen 24Sep2019

#include <DS3232RTC.h>      // https://github.com/JChristensen/DS3232RTC
DS3232RTC myRTC;

void setup()
{
    Serial.begin(115200);
    myRTC.begin();
}

void loop()
{
    display();
    delay(10000);
}

// display time, date, temperature
void display()
{
    char buf[40];
    time_t t = myRTC.get();
    float celsius = myRTC.temperature() / 4.0;
    float fahrenheit = celsius * 9.0 / 5.0 + 32.0;
    sprintf(buf, "%.2d:%.2d:%.2d %.2d%s%d ",
        hour(t), minute(t), second(t), day(t), monthShortStr(month(t)), year(t));
    Serial.print(buf);
    Serial.print(celsius);
    Serial.print("C ");
    Serial.print(fahrenheit);
    Serial.println("F");
}

なのだが、これに

#include <Wire.h>

を頭に付け足し、
シリアル通信の前に

void setup()
{
    Wire.setSDA(16);
    Wire.setSCL(17);
    Wire.begin();

    Serial.begin(115200);
    myRTC.begin();
}

とI2Cのためのピンを設定しておく。この場合、21ピン(GP16)をSDA、22ピン(GP17)をSCLに設定している。

これでエラーなくシリアルコンソールに時間、温度を表示できた。RTCへの時間あわせをしていないので、00:00:10からスタートした。時刻設定のコードも必要だが、まずはI2Cが使えたということで良しとしよう。