slurm: Simple Linux Utility for Resource Management
Simple Linux Utility for Resource Management 本家様 slurm
ジョブスケジューラ。SunGridEngineをいろいろ調整していたのだが、、、、良く分からん。
結局TORQUEを作ってみたが、ノード指定があるのに躊躇う。必要なコア数とメモリー量だけでノードが決まる代物が欲しくて調べてみた。
Torque:
queue名称 + node(マシン数) + ppn(processors per node)
Slurm:
queue名称 + ntasks(MPI数)
計算ノード/queue設定slurm/slurm.conf
参照先https://wiki.fysik.dtu.dk/niflheim/SLURM
全体像 †
TORQUEと同じようにsamba AD or NIS, LDAP/NFS環境で/home,/Applが共有され、計算ノードはn1,n2,n3の3台で、ジョブを投入するサイトが1台。
ジョブを管理するslurm管理ノードが1台とする。
各ノードはsamba(or nis, ldap)に登録されてホスト情報は共有する. アカウント情報も共有します. 登録方法はsamba/Linux参加とか参照
各マシンの時計は chrony or ntp とかで同期されている

役目 | ホスト名 | IPアドレス | core数 | GPU | OS | cgroup | 備考 |
管理ノード | slurm | 192.168.0.69 | 1 | - | RockyLinux 8.6 | v1 | slurmctldが起動 |
計算ノード | n1 | 192.168.0.14 | 1 | A2000 | Ubuntu 20.04 | v1,v2(unified) | slurmdが起動 |
n2 | 192.168.0.15 | 2 | T600 | RockyLinux 9.1 | v2 |
n3 | 192.168.0.16 | 4 | - | ubuntu 22.04 | v2 |
s | 192.168.0.7 | 4 | GT710*2 | RockyLinux 9.1 | v2 |
ジョブ発行ノード | slurm-client | 192.168.0.20 | 1 | - | RockyLinux 9.1 | | srun,sbatchの 他TORQUEコマンドも使用可能 |
cgroup v1 or v2 は「mount -l | grep cgroup」で見分けられる
queue構成
queue名 | 対象ノード | 備考 |
workq | n1,n2 | |
gpu | n3 | GPUカード2枚 |
下拵え:共通アカウントの作成とmungeのインストール †
共通アカウントslurmとmungeを用意します。samba/ユーザ登録とかNIS#df5a057bとかLDAP/dataとかで
ユーザ名 | UID | GID | ホームディレクトリ | login shell | コマンド(nisの場合) | 備考 |
slurm | 5000 | 5000 | /var/lib/slurm | /sbin/nologin | groupadd -g 5000 slurm useradd -M -d /var/lib/slurm -s /sbin/nologin -u 5000 -g slurm slurm | |
munge | 5001 | 5001 | /var/lib/munge | /bin/bash | groupadd -g 5001 munge useradd -M -d /var/lib/munge -s /bin/bash -u 5001 -g munge munge | tmpfiles.dの関係でlocalにアカウント設置が必須みたい |
*mungeはyumでインストールした際にUID 1000以下でアカウントを作りますが、インストール前に1000以上でアカウントを作ります
そして全てのクラスターノード(slurm,n1,n2,n3,client)にmungeパッケージをインストールする。
[root@slurm ~]# id munge
uid=5001(munge) gid=5001(munge) groups=5001(munge)
[root@slurm ~]# dnf install munge
次に、munge.key(/etc/munge/munge.key)を作成して、mungeデーモンを起動させる
[root@slurm ~]# /usr/sbin/create-munge-key
Generating a pseudo-random key using /dev/urandom completed.
[root@slurm ~]# ls -l /etc/munge/
total 4
-r--------. 1 munge munge 1024 Dec 18 01:52 munge.key
[root@slurm ~]# systemctl enable munge.service --now
Created symlink /etc/systemd/system/multi-user.target.wants/munge.service → /usr/lib/systemd/system/munge.service.
[root@slurm ~]#
この作成したmunge.keyをクラスターに参加する全てのマシンに配布します
*n1,n2,n3,clientも同様にmungeパッケージのインストールも行う
例えば n1.sybyl.local(ubuntu20.04) マシンに対しては
[root@slurm ~]# ssh -l root n1 'apt update && apt install munge -y' *ubuntu20.04ですが、rootを許可してsshのroot接続も許可してます
[root@slurm ~]# scp /etc/munge/munge.key root@n1:/etc/munge/munge.key
[root@slurm ~]# ssh -l root n1 'chown munge. /etc/munge/munge.key'
*munge.keyファイルの所有者に留意する事
slurmサーバにAnsibleを入れて全参加ノードを仕立てさせた方がいいかも
slurmパッケージの構築とインストール †
クラスターが単一のOSであるなら別途パッケージを製作してslurmの起点を「/opt/slurm」に集約させ共有するのもいいかなと思うが、
クラスターの各ノードのOSがまちまちであるならOS提供のパッケージをそのまま利用した方がいいかな
パッケージを作成するなら slurm/rpmbuild ubuntuでソースから作るslurm/ubuntu
各ノードでインストールするパッケージ(RHEL系)
パッケージ名称(RHEL系) | Summary | 備考 | 管理ノード | 計算ノード | ジョブ投入ノード | Slurmdbdノード | 備考 |
slurm | Slurm Workload Manager | 基本キット | ○ | ○ | ○ | ○ | ubuntuでは「slurm-client」かな |
slurm-slurmctld | Slurm controller daemon | 管理デーモン slurmctld.service | ○ | - | - | - | ubuntuでは「slurmctld」 |
slurm-slurmd | Slurm compute node daemon | 計算ノードデーモン slurmd.service | - | ○ | - | - | ubuntuでは「slurmd」 |
slurm-pam_slurm | PAM module for restricting access to compute nodes via Slurm | pam_slurm.so pam_slurm_adopt.so | - | △ | - | - | |
slurm-torque | Torque/PBS wrappers for transitition from Torque/PBS to Slurm | ラッパープログラム qsub,qstatとか slurm-perlapiが必須 | - | - | △ | - | ubuntuでは「slurm-wlm-torque」 |
slurm-openlava | openlava/LSF wrappers for transitition from OpenLava/LSF to Slurm | ラッパープログラム slurm-perlapiが必須 | - | - | △ | - | |
slurm-slurmdbd | Slurm database daemon | systemctl対応 slurmdbd | - | - | - | ○ | ubuntuでは「slurmdbd」 |
slurm-sql | Slurm SQL support | - | - | - | - | ○ | |
ほかslurm-APIパッケージの「slurm-perlapi(libslurmdb-perl)」、開発環境向けの「slurm-devel(slurm-wlm-basic-plugins-dev)」、ツール類「slurm-contribs」がある.
恐らく複数台になると思うので ansible を作ってみた slurm/ansible
gpu対応slurm/gpu
確認 †
[illya@slurm-client ~]$ sinfo -N -l
Sun Dec 25 20:56:52 2022
NODELIST NODES PARTITION STATE CPUS S:C:T MEMORY TMP_DISK WEIGHT AVAIL_FE REASON
n1 1 workq* idle 1 1:1:1 16001 0 1 (null) none
n2 1 workq* idle 2 1:2:1 15732 0 1 (null) none
n3 1 workq* idle 4 1:4:1 16000 0 1 (null) none
[illya@slurm-client ~]$
各ノードは 1CPU ソケットで、1core、2core、4core構成です
STATEがdownとかなっていたら「scontrol update nodename=node_name state=idle」でidleに変更できる
実行テスト †
簡単なテストを行ってみます。
job queuing systemなのでバッチファイルを作ってジョブを流してみます. 使うコマンドは「sbatch」です
[illya@slurm-client ~]$ vi a.sh
#!/bin/bash
hostname
echo "sleeping..."
sleep 10
echo "done!"
[illya@slurm-client ~]$ sbatch a.sh <-- ジョブファイル「a.sh」を投入
Submitted batch job 41
[illya@slurm-client ~]$ squeue <-- 確認
JOBID PARTITION NAME USER ST TIME NODES NODELIST(REASON)
41 workq a.sh illya R 0:01 1 n1
(結果確認)
[illya@slurm-client ~]$ cat slurm-41.out
n1
sleeping...
done!
[illya@slurm-client ~]$
な感じで動いている. 実際には「a.sh」の中に「#SBATCH」で始まるディレクティブを加えますが、ここは簡単に.
次にインターラクティヴでジョブを投げたいと思います. slurmは「srun」コマンドで
[illya@slurm-client ~]$ srun --pty bash
illya@n1:~$
illya@n1:~$ sinfo
PARTITION AVAIL TIMELIMIT NODES STATE NODELIST
workq* up infinite 1 alloc n1
workq* up infinite 2 idle n[2-3]
illya@n1:~$ exit
(n3を指定して)
[illya@slurm-client ~]$ srun --nodelist=n3 --pty bash
illya@n3:~$ sinfo
PARTITION AVAIL TIMELIMIT NODES STATE NODELIST
workq* up infinite 1 mix n3 <-- mixなのでまだ余裕がある
workq* up infinite 2 idle n[1-2]
illya@n3:~$ exit
(4coreを使うと宣言)
[illya@slurm-client ~]$ srun --ntasks=4 --pty bash
illya@n3:~$ sinfo
PARTITION AVAIL TIMELIMIT NODES STATE NODELIST
workq* up infinite 1 alloc n3 <-- allocとなって全て払い下げられた.
workq* up infinite 2 idle n[1-2]
illya@n3:~$ exit
[illya@slurm-client ~]$
バッチジョブファイルを作ってみます。
http://www.ceci-hpc.be/slurm_tutorial.html
このサイトが非常に分かりやすかったです。
slurmでの[task]はプロセスと読み替えて、1つのジョブを2MPIプロセスで処理させるのなら-ntasks=2。1つのジョブを2スレッドで処理させるのなら--cpus-per-task=2と定義する。
[illya@client ~]$ vi a.sh
#SBATCH -J test_run # --job-name=test_run
#SBATCH -o output_%j.txt # --output=output_test_run.txt
#SBATCH -e errors_%j.txt # --error=errors_test_run.txt
#SBATCH -p batch # いわゆる使用するキュー名
#SBATCH -n 4 # --ntasks=4 このジョブで4プロセスを実行する
#SBATCH -c 2 # --cpus-per-task=2 1プロセス当たり2core使用する
mpirun mpirun.exe
[illya@client ~]$
[illya@client ~]$ sbatch a.sh #これで実行される
GPUを使ってみる †
[illya@slurm-client ~]$ sinfo -N -o "%N %G"
NODELIST GRES
n1 gpu:1(S:0)
n2 gpu:1(S:0)
n3 (null)
[illya@slurm-client ~]$
[illya@slurm-client ~]$ srun --gres=gpu:1 --pty nvidia-smi -L
GPU 0: NVIDIA RTX A2000 (UUID: GPU-23cc3ee7-31d3-a068-2f61-5aa00052d084)
[illya@slurm-client ~]$ srun --gres=gpu:1 -w n1 --pty bash
illya@n1:~$ nvidia-smi -L
GPU 0: NVIDIA RTX A2000 (UUID: GPU-23cc3ee7-31d3-a068-2f61-5aa00052d084)
illya@n1:~$ exit
exit
[illya@slurm-client ~]$ srun --gres=gpu:1 -w n2 --pty bash
[illya@n2 ~]$ nvidia-smi -L
GPU 0: NVIDIA T600 (UUID: GPU-01226552-df75-5989-c2f3-3550cdc3427d)
[illya@n2 ~]$ exit
exit
[illya@slurm-client ~]$
複数のGPUを持っているノードへのテスト
[illya@slurm-client ~]$ srun --gres=gpu:1 -w s --pty bash
[illya@s ~]$ nvidia-smi -L
GPU 0: NVIDIA GeForce GT 710 (UUID: GPU-f0753e20-06f7-695a-f325-b5b6342393ba)
[illya@s ~]$ exit
exit
[illya@slurm-client ~]$
[illya@slurm-client ~]$ srun --gres=gpu:2 -w s --pty bash
[illya@s ~]$ nvidia-smi -L
GPU 0: NVIDIA GeForce GT 710 (UUID: GPU-f0753e20-06f7-695a-f325-b5b6342393ba)
GPU 1: NVIDIA GeForce GT 710 (UUID: GPU-34c49ab7-b79d-e341-93e2-1659e9bd9e57)
[illya@s ~]$ exit
exit
[illya@slurm-client ~]$
と1枚指定したら1枚のみ。2枚指定したら2枚確保できた. そして2枚確保中に別のターミナルから再度GPUを確保するジョブを投げると待機状態になった.
めも †
[illya@slurm-client ~]$ srun --gres=gpu:1 --pty nvidia-smi -L
slurmstepd: error: no gpu utilization TRES! This should never happen
GPU 0: NVIDIA GeForce GT 710 (UUID: GPU-f0753e20-06f7-695a-f325-b5b6342393ba)
[illya@slurm-client ~]$
と「slurmstepd: error: no gpu utilization TRES! This should never happen」が表示されるのはslurm.confで
「JobAcctGatherType=jobacct_gather/cgroup」とかを「JobAcctGatherType=jobacct_gather/none」にする