Slurm を使ったジョブの投入
管理ノードへのログイン
$ ssh -l (ユーザ名) slurm.matsue-ct.ac.jp
キューの状態の確認
sugiyama@ncfs1:~$ sinfo PARTITION AVAIL TIMELIMIT NODES STATE NODELIST debug* up 1:00:00 1 idle ncsv3 v100 up infinite 1 idle ncsv3
slurm のコマンド
コマンド 説明・主な用途
srun インタラクティブ実行・ステップ実行
リソースを確保して即座にプログラムを実行する.
MPI並列実行時にも使用.
sbatch バッチジョブの投入
ジョブスクリプト(シェルスクリプト)をキューに投げ,
バックグラウンドで実行する.
squeue ジョブ待ち行列の確認
実行中(R)や待機中(PD)のジョブ一覧を表示する.-u <ユーザー名> で絞り込み
scancel ジョブの取り消し
scancel <ジョブID> で実行中または待機中のジョブを強制終了する
scantrol 詳細情報の表示・変更
scontrol show job <ID> で,そのジョブのさらに詳細な設定やログを確認できる
sacct 過去のジョブ履歴の確認
終了したジョブの実行時間や消費メモリ,終了ステータスなどを確認する
snfo パーティション・ノード状態の確認
ノードが使用可能(idle),使用中(alloc),ダウン(down)などの状態を表示する
scontrol show node ノードの詳細確認特定のノードに積まれているCPU数,
メモリ,GPU(GRES) の空き状況などを詳しく見る。
ジョブの実行時に付けるオプション
オプション 意味 -p, --partition 実行するパーティション(キュー)を指定する -n, --ntasks 合計タスク数(MPIプロセス数)を指定する -c, --cpus-per-task 1タスクあたりのCPUコア数(OpenMPスレッド用)を指定する --gres=gpu:N 使用するGPUの枚数(N枚)を指定する --mem 使用する合計メモリ量(例: --mem=10G)を指定する -t, --time 最大実行時間を指定する(例: 01:00:00)
並列実行の時は --ntasks と --cpus-per-task を設定する.
例: --ntasks=12 + --cpus-per-task=1 : CPU 12 コアで MPI 並列 --ntasks=1 + --cpus-per-task=12 : CPU 1 コアで,12 スレッドの OMP 並列 --ntasks=4 + --cpus-per-task=3 : CPU 4 コアで,3 スレッドの OMP 並列 = 計 12 並列
MPI 並列の時は以下のオプションも必要
--mpi=pmax : MPI 並列するときに必ず付ける
OpenMP 並列の場合は環境変数の設定が必要
export OMP_NUM_THREADS=$SLURM_CPUS_PER_TASK
GPU 利用時は --gres オプションを指定.使わない場合は 0 にすること.
--gres=gpu:0 : GPU 利用しない (デフォルト) --gres=gpu:1 : GPU 1 基利用
インタラクティブな実行
管理ノードから計算ノードにあたかも SSH でログインしたような操作感が得られる.
MPI 並列計算
mpirun のオプションとして --bind-to none を与える必要があることに注意.
sugiyama@ncfs1:~/CPU$ srun --ntasks=4 --pty bash
^^^^^
sugiyama@ncsv3:~/CPU$ mpirun --bind-to none c_mpi-hello
^^^^^
Hello World 3
Hello World 1
Hello World 0
Hello World 2
sugiyama@ncsv3:~/CPU$ mpirun --bind-to none -n 2 c_mpi-hello
^^^^^ ^^^^
Hello World 1
Hello World 0
sugiyama@ncsv3:~/CPU$ exit
sugiyama@ncfs1:~/CPU$
OMP 並列計算
OpenMP で並列計算する場合は,--cpus-per-task=2 でスレッド数を指定する. MPI を使わない場合は,計算ノードにおいて環境変数 OMP_NUM_THREADS に $SLURM_CPUS_PER_TASK を与えることを割愛できる.
sugiyama@ncfs1:~/CPU$ srun --cpus-per-task=2 --pty bash
^^^^^
sugiyama@ncsv3:~/CPU$ ./c_omp-hello
^^^^^
Hello World from 0 of 2
Hello World from 1 of 2
sugiyama@ncsv3:~/CPU$ nvidia-smi -L
^^^^^
GPU 0: Tesla V100S-PCIE-32GB (UUID: GPU-0ef0bd70-fd0b-7c80-7cdb-cc4ea2302287)
sugiyama@ncsv3:~/CPU$ exit
sugiyama@ncfs1:~/CPU$
MPI + OMP 並列計算
MPI と OMP の両方を使う場合は, 計算ノードにおいて環境変数 OMP_NUM_THREADS に $SLURM_CPUS_PER_TASK を与える必要がある.
sugiyama@ncfs1:~/CPU$ srun --ntasks=2 --cpus-per-task=2 --pty bash sugiyama@ncsv3:~/CPU$ export OMP_NUM_THREADS=$SLURM_CPUS_PER_TASK sugiyama@ncsv3:~/CPU$ mpirun --bind-to none -n 2 c_mpi-omp-hello Hello from thread 0 out of 2 from process 1 out of 2 on ncsv3 Hello from thread 1 out of 2 from process 1 out of 2 on ncsv3 Hello from thread 0 out of 2 from process 0 out of 2 on ncsv3 Hello from thread 1 out of 2 from process 0 out of 2 on ncsv3
Python venv 環境
sugiyama@ncfs1:~/check/python$ srun --gres=gpu:1 --pty bash sugiyama@ncsv3:~/check/python$ source ../venv/bin/activate (venv) sugiyama@ncsv3:~/check/python$ python test_tf.py
docker イメージ
sugiyama@ncfs1:~/check/python$ srun --gres=gpu:1 --ntasks=1 --pty bash sugiyama@ncsv3:~/check/python$ podman run --rm --device "nvidia.com/gpu=$CUDA_VISIBLE_DEVICES" docker.io/nvidia/cuda:12.0.1-base-ubuntu22.04 nvidia-smi -L GPU 0: Tesla V100S-PCIE-32GB (UUID: GPU-0ef0bd70-fd0b-7c80-7cdb-cc4ea2302287)
ジョブ投入方法
GPU
何もつけないとデフォルトの debug キューとして実行される
$ srun --gres=gpu:1 nvidia-smi -L GPU 0: Tesla V100S-PCIE-32GB (UUID: GPU-0ef0bd70-fd0b-7c80-7cdb-cc4ea2302287)
GPU を 2 基要求するとエラーになる (期待通り)
$ srun --gres=gpu:2 nvidia-smi srun: error: Unable to allocate resources: Invalid generic resource (gres) specification
--gres オプションをつけないと GPU は割り当てられない.
$ srun nvidia-smi -L No devices found.
CPU (MPI 並列)
デフォルトの debug キューで 4 並列で実行する.srun に --mpi=pmix オプションが必要
$ srun --mpi=pmix --ntasks=4 ./c_mpi-hello Hello World 3 Hello World 0 Hello World 1 Hello World 2
v100 キューを使うと,最大 32 並列まで OK.
$ srun --partition=v100 --mpi=pmix --ntasks=32 ./c_mpi-hello Hello World 0 Hello World 1 Hello World 2 Hello World 3 ...略...
--ntasks を指定しないと 1 並列で実行
$ srun --mpi=pmix ./c_mpi-hello Hello World 0
debug キューは 4 コアが上限なので,それを超えるとエラーになる (期待通り)
$ srun --mpi=pmix --ntasks=5 ./c_mpi-hello srun: error: Unable to allocate resources: Requested node configuration is not available
CPU (OMP 並列)
OMP だけしか使わない場合は環境変数 OMP_NUM_THREADS の設定を割愛することが可能.
$ srun --cpus-per-task=2 ./c_omp-hello Hello World from 0 of 2 Hello World from 1 of 2 $ srun --partition=v100 --cpus-per-task=10 ./c_omp-hello Hello World from 5 of 10 Hello World from 9 of 10 Hello World from 4 of 10 ...略...
CPU (MPI + OMP 並列)
環境変数を指定しないと,並列数がおかしくなることに注意.
$ srun --partition=v100 --mpi=pmix --ntasks=2 --cpus-per-task=4 \ bash -c "export OMP_NUM_THREADS=\$SLURM_CPUS_PER_TASK; ./c_mpi-omp-hello" Hello from thread 0 out of 4 from process 0 out of 2 on ncsv3 Hello from thread 2 out of 4 from process 0 out of 2 on ncsv3 Hello from thread 3 out of 4 from process 0 out of 2 on ncsv3 Hello from thread 1 out of 4 from process 0 out of 2 on ncsv3 Hello from thread 2 out of 4 from process 1 out of 2 on ncsv3 Hello from thread 0 out of 4 from process 1 out of 2 on ncsv3 Hello from thread 1 out of 4 from process 1 out of 2 on ncsv3 Hello from thread 3 out of 4 from process 1 out of 2 on ncsv3
上記の例で,export OMP_NUM_THREADS=$SLURM_CPUS_PER_TASK を指定しないと 16 並列となる. その原因は,「Slurmが確保したCPUコア数」と「OpenMPが自動認識したスレッド数」が食い違っているためである. OpenMP(libgomp等)は、環境変数 OMP_NUM_THREADS が指定されていない場合,「システムに見える全コア数」をスレッド数にしようとするためである.今回の例ではジョブに割り当てられた合計コア数(今回は 2タスク × 4コア = 8)が「システム全体」として見えてしまう.
Python venv 環境
bash -c で囲む形で,実行の手順をカンマ区切りで並べているだけ.
$ srun --gres=gpu:1 --ntasks=1 bash -c "source ../venv/bin/activate; python test_tf.py"
docker イメージ
podman を使って docker イメージを利用する場合は,bash -c でコマンドを囲む必要がある.
$ srun --gres=gpu:1 bash -c 'podman run --rm --device "nvidia.com/gpu=$CUDA_VISIBLE_DEVICES" docker.io/nvidia/cuda:12.0.1-base-ubuntu22.04 nvidia-smi -L' GPU 0: Tesla V100S-PCIE-32GB (UUID: GPU-0ef0bd70-fd0b-7c80-7cdb-cc4ea2302287)
覚書(1)
bash -c でコマンドを囲まないと環境変数 $CUDA_VISIBLE_DEVICES が取れない.
$ srun --gres=gpu:1 podman run --rm --device "nvidia.com/gpu=$CUDA_VISIBLE_DEVICES" docker.io/nvidia/cuda:12.0.1-base-ubuntu22.04 nvidia-smi -L Error: stat nvidia.com/gpu=: no such file or directory srun: error: ncsv3: task 0: Exited with exit code 125
覚書(2)
bash -c で囲まず,gpu=all にすると,全部の GPU が見えてしまう.このあたりに slurm と podman の連携がまだ完全ではないことが垣間見える.
$ srun --gres=gpu:1 podman run --rm --device "nvidia.com/gpu=all" docker.io/nvidia/cuda:12.0.1-base-ubuntu22.04 nvidia-smi -L GPU 0: Tesla V100S-PCIE-32GB (UUID: GPU-0ef0bd70-fd0b-7c80-7cdb-cc4ea2302287) GPU 1: Tesla V100S-PCIE-32GB (UUID: GPU-d19054e2-f863-3da6-c30b-f299bb053a27) GPU 2: Tesla V100S-PCIE-32GB (UUID: GPU-cf4c7b4a-6a73-1407-4d80-c5a8000eca26) GPU 3: Tesla V100S-PCIE-32GB (UUID: GPU-a478fcef-90a8-f595-6260-85b310526d6d)
ジョブスクリプトの例
CPU (MPI 並列)
c_mpi-hello.sh を以下のように作成する
#!/bin/sh #SBATCH --job-name=MyTest # ジョブ名 #SBATCH --output=%j_out.txt # 標準出力 (%j はジョブIDに置換) #SBATCH --error=%j_err.txt # 標準エラー出力 #SBATCH --partition=debug # パーティション名 (sinfoで確認したもの) #SBATCH --ntasks=2 # MPI 並列数 #SBATCH --cpus-per-task=1 # OMP 並列数 # 作業フォルダに移動 cd /work/$USER/CPU # コンパイル mpicc -o c_mpi-hello c_mpi-hello.c # 実行. --mpi=pmix オプション必須. srun --mpi=pmix ./c_mpi-hello
ジョブの投入
$ sbatch c_mpi-hello.sh
確認
$ cat 282_out.txt Hello World 0 Hello World 1 $ cat 282_err.txt
CPU (OMP 並列)
#!/bin/sh #SBATCH --job-name=MyTest # ジョブ名 #SBATCH --output=%j_out.txt # 標準出力 (%j はジョブIDに置換) #SBATCH --error=%j_err.txt # 標準エラー出力 #SBATCH --partition=debug # パーティション名 (sinfoで確認したもの) #SBATCH --ntasks=1 # MPI 並列数 #SBATCH --cpus-per-task=2 # OMP 並列数 # OpenMP の時は環境変数を設定する必要あり export OMP_NUM_THREADS=$SLURM_CPUS_PER_TASK # 作業フォルダに移動 cd /work/$USER/CPU # コンパイル gcc -fopenmp -o c_omp-hello c_omp-hello.c # 実行 ./c_omp-hello
CPU (MPI + OMP 並列)
#!/bin/sh #SBATCH --job-name=MyTest # ジョブ名 #SBATCH --output=%j_out.txt # 標準出力 (%j はジョブIDに置換) #SBATCH --error=%j_err.txt # 標準エラー出力 #SBATCH --partition=debug # パーティション名 (sinfoで確認したもの) #SBATCH --ntasks=2 # MPI 並列数 #SBATCH --cpus-per-task=2 # OMP 並列数 # OpenMP の時は環境変数を設定する必要あり export OMP_NUM_THREADS=$SLURM_CPUS_PER_TASK # 作業フォルダに移動 cd /work/$USER/CPU # コンパイル mpicc -fopenmp -o c_mpi-omp-hello c_mpi-omp-hello.c # 実行. --mpi=pmix オプション必須. srun --mpi=pmix ./c_mpi-omp-hello
Python venv
#!/bin/sh #SBATCH --job-name=MyTest # ジョブ名 #SBATCH --output=%j_out.txt # 標準出力 (%j はジョブIDに置換) #SBATCH --error=%j_err.txt # 標準エラー出力 #SBATCH --partition=debug # パーティション名 (sinfoで確認したもの) #SBATCH --gres=gpu:1 # GPUを1枚要求 # --- メール通知設定 --- #SBATCH --mail-type=END,FAIL # 通知するタイミング #SBATCH --mail-user=hoge@... # 送信先のアドレス # 作業フォルダに移動 cd /work/$USER/check/python # venv 環境 . ../venv/bin/activate # 実行 python test_tf.py
docker イメージ
#!/bin/bash #SBATCH --job-name=cuda_direct #SBATCH --output=%j_out.txt # 標準出力 (%j はジョブIDに置換) #SBATCH --error=%j_err.txt # 標準エラー出力 #SBATCH --partition=debug # パーティション名 (sinfoで確認したもの) #SBATCH --gres=gpu:1 # 作業フォルダに移動 cd /work/$USER/check/python # 1. 計算ノード側でSlurmが割り当てたGPUを決定 GPU_SPEC="nvidia.com/gpu=$CUDA_VISIBLE_DEVICES" # 2. Podman実行 # --rm: 終了後にコンテナを削除 # -v: ホストのディレクトリをコンテナへマウント # -w: 作業ディレクトリ podman run --rm \ --device "$GPU_SPEC" \ -v "$HOME:$HOME" \ -w "$PWD" \ docker.io/nvidia/cuda:12.0.1-base-ubuntu22.04 \ nvidia-smi