HPCといえばSlurmだよね
ラズパイが腐るほどあるので、Slurmクラスタを作る。流れとしては、Slurmの全体像を理解してから、実際にSlurmをインストールして、クラスタを構築。んで、MPIジョブを投入できたら最高ですね。
参考文献
Slurmの全体像
クラスタを使って並列分散処理をしたいとき、どうするか?例えばMPIを使ってなにかを計算したいとき、どうするか?直接mpirunをすればいいよね?簡単だ。うん。ユーザがおれ一人で他の人がクラスタを使わない前提であれば直接実行していいよね。しかし、HPCシステムってのは基本的にはいろんな人に使われるんですよ。そんな時にいろんな人が同時にMPIのジョブを実行すると何が起こるか? まあ、これは予想だけど、基本的に1つのMPIプロセスに対して1つのコアが割り当てられるので、コア数を超えるプロセスが割り当てられそうなときは、mpirunの実行が失敗すると思うんですよ。
このようなリソース競合によるジョブの実行失敗などを防いだり、その他、リソースのマネジメントをするのがリソースマネジメントシステム(RMS)だよね。SlurmもRMSなわけだ。いろいろなRMSがあるわけで、その中でもSlurmの特徴が三つある。
- ある一定期間、ユーザが計算資源(ノード)を占有することを許す
- 各ノードに対して、ジョブのスタート、実行、監視を可能にする
- 待ち行列内のpending jobに対して、恣意的な実行を可能にする
slurmのアーキテクチャ
各ノードでslurmdデーモンが動いている。そして、マネジメントノード(マスターノード)ではslurmctldデーモンが動いている。ユーザはクライアントアプリを使って、slurmctldにアクセスし、ジョブのサブミットや、状態の確認ができる。
Slurmのインストール
参考文献
前提
- ノード間でuidが同じユーザが作られていること これは、最初にラズパイの設定をするときにユーザ名を一律に決めておくことで解決できる。
- ノード間でシステムの時刻が一致している事 これは、raspi-configのロケール設定でAsia/Tokyoを選ぶことで解決できる
マスターノードのあるディレクトリをnfsとして外部にエクスポートしておくといろいろとらく
マスターノード、スレーブノードのホスト名を決めておく
/etc/hosts
マスターノードの設定
リポジトリからのインストール
sudo apt install slurm-wlm -y
Slurmの設定
設定ファイルの場所は
/etc/slurm/slurm.conf
この場所に、デフォルトの設定ファイルを持ってくる
cp /usr/share/doc/slurm-client/examples/slurm.conf.simple.gz .
gzip -d slurm.conf.simple.gz
mv slurm.conf.simple slurm.conf
設定ファイル(slurm.conf)の内容は厳密にかかないとだめ
SlurmctldHost=node01(<ip addr of node01>)
# e.g.: node01(192.168.1.14)
# actual : zeta(172.20.2.1)
SelectType=select/cons_res
SelectTypeParameters=CR_Core
...
...
ClusterName=glmdev
...
...
NodeName=zeta NodeAddr=172.20.2.1 CPUs=4 Sockets=1 CoresPerSocket=4 State=UNKNOWN
NodeName=slave1 NodeAddr=172.20.2.3 CPUs=4 Sockets=1 CoresPerSocket=4
State=UNKNOWN
NodeName=slave2 NodeAddr=172.20.2.4 CPUs=4 Sockets=1 CoresPerSocket=4
State=UNKNOWN
NodeName=slave3 NodeAddr=172.20.2.5 CPUs=4 Sockets=1 CoresPerSocket=4
State=UNKNOWN
NodeName=slave4 NodeAddr=172.20.2.6 CPUs=4 Sockets=1 CoresPerSocket=4
State=UNKNOWN
PartitionName=mycluster Nodes=slave[1-4] Default=YES MaxTime=INFINITE
State=UP
cgroup関係の設定ファイルをつくる
/etc/slurm/cgroup.confに
CgroupMountpoint="/sys/fs/cgroup"
CgroupAutomount=yes
CgroupReleaseAgentDir="/etc/slurm-llnl/cgroup"
AllowedDevicesFile="/etc/slurm-llnl/cgroup_allowed_devices_file.conf"
ConstrainCores=no
TaskAffinity=no
ConstrainRAMSpace=yes
ConstrainSwapSpace=no
ConstrainDevices=no
AllowedRamSpace=100
AllowedSwapSpace=0
MaxRAMPercent=100
MaxSwapPercent=100
MinRAMSpace=30
そして、 /etc/slurm/cgroup_allowed_devices_file.conf に
/dev/null
/dev/urandom
/dev/zero
/dev/sda*
/dev/cpu/*/*
/dev/pts/*
/clusterfs*
munge関係の設定
slurmはノード間の通信にmungeっていうソフトを使う。その辺の設定をしてください。割愛します。
スレーブノードの設定
必要なソフトのインストール
sudo apt install slurmd slurm-client -y
マスターノードの設定ファイル(slurm.conf)、mungeの鍵ファイル(/etc/munge/munge.key)をスレーブノードに配る
場所はオリジナルと同じ場所で。
sudo cp /cluster_common/munge.key /etc/munge/munge.key
sudo cp /cluster_common/slurm.conf /etc/slurm/slurm.conf
sudo cp /cluster_common/cgroup* /etc/slurm
mungeサーバの起動
sudo systemctl enable munge
sudo systemctl start munge
mungeを使った認証
ssh pi@node01 munge -n | unmunge
slurmdの起動
sudo systemctl enable slurmd
sudo systemctl start slurmd
その他、注意点
- マスターノードではslurmctldが稼働する
- スレーブノードではslurmdが稼働
- どちらのデーモンも/etc/slurm/slurm.confを使う
- slurmctldは6817ポートでslurmdと通信をするので開けておく 以下のコマンドでプロセスがどのポートを使っているのかを確認
sudo lsof -i TCP
エラーが発生時の対処方法
1. journalctlでログを見る
2. 直接ログファイルを見に行く
コントロールコマンドの基本
NQSVと同じ感じだね。qsub,qstat,など、やったよね。
- sinfo
ノードの状態を得る
srun ジョブのサブミットに使われる
sstat ジョブの実行状況とリソースの割り当て状況
scancel 実行中のジョブのキャンセル、停止
その他にもいろいろあるので、適宜調べてください。
その他、起こったエラーと対処法
ノードのステートがdrainのままで変わらない
sinfoでノードの状態を見ると、次のようになる。
mycluster* up infinite 2 drain slave[3-4]
mycluster* up infinite 2 idle slave[1-2]
sinfo -R でdrainもしくはdropの原因を知ることが可能
REASON USER TIMESTAMP NODELIST
Low socket*core*thre slurm 2023-01-17T08:50:28 slave[3-4]
これは、slurm.confの各ノードの資源量パラメータを設定する箇所が間違っているのが原因だとおもう。直して、
scontrol update nodename=YOURNODEHERE state=resume
でノードの状態をアップデートできる。が
scontrol update nodename=slave2 state=resume
をすると、
slurm_update error: Invalid user id
が出てくる。これはもしや、mungeでの認証うまくいていない?
いや、調べてみた結果、sudoで実行すればいいっぽい。んで、stateはresumeではなく、idleに変更するっぽい。次のコマンドで実行できた。
sudo scontrol update NodeName=slave4 state=idle
んで、だ。次の問題は
srun --nodes=2 hostname
が実行できないこと。
その前に、 squeueで ジョブキューがみられる。
JOBID PARTITION NAME USER ST TIME NODES NODELIST(REASON)
17 mycluster bash ray R 47:57 1 slave1
んで、 scancel jobid でジョブを削除できる。 これをやると、 sinfoでmixだったノードのステートがidleにもどった。 ちなみに、sinfoでmix担っている奴は、稼働中って意味なのかな?わからん。
でもやっぱりだめなんですよね、srunが利かない。
うん、やっとsrunでマルチノードでできるようになった。まだ完ぺきではないんだけど。 なぜかわからないんだけど、特定のノードから出ないとsrunが効かないんだよね。 どういうことか? zeta,slave1,slave2からsrunをすると、なぜかわからないが、実行されない。
しかし、slave3-11のノード上だとsrunで何を起動してもうまくいくのよ。なぜや?なんか、最初に素ラームの設定をしたのがうまくいかない3ノードなんだよね。これ何か関係しているのではないか? なぞです。忘れる前にいろいろと書いておこう。
なんか役に立ちそうなメモ
- ノードを指定して実行
srun --nodelist=slave1 hostname
- ジョブキューの中身の見方
squeue
ジョブidとかが見られる。
- downやdrainになっているノードの復活方法
scontrol update NodeName=slave1 state=idle
- ジョブの削除方法
scancel job_id
- ジョブの投入方法
sbatch script.sh
なんと、sbatchはどこからでも提出できるっぽんだよね。 zetaでも、slave[1-11]でも。ダメなのは、srunだけだね。あとは完ぺき。
2/3追記
srunは、ufwを無効化したらどこからでも実行できるようになりました。完璧ですよ!
- ジョブの詳細情報確認方法
scontrol show job
あとは、MPIのジョブを投入するだけです~!
何をインストールすればインですかね?PMIxって何なんですかね?わからんです。
MPI関係のpackageインストールコマンド
sudo apt install openmpi-bin libopenmpi-dev openmpi-doc
スクリプトにかいた要求ノード数でmpiを実行できるようになります。以下にジョブスクリプトの例をのせておきます。
#!/bin/bash
#SBATCH -p mycluster
#SBATCH -n 16
#SBATCH -J test_openmpi
#SBATCH -o stdout.%J.log
#SBATCH -e stderr.%J.log
cd /cluster_common/mpi_file
time mpirun -np ${SLURM_NTASKS} ./pi_calc < input.txt
echo ${SLURM_NTASKS}
RETCODE=$?
exit ${RETCODE}
今後やりたい事
- slurmのプラグインをいじって、独自のスケジューリングポリシーでジョブスケジューリングを実行したいよね。
- それくらいですかね?