はじめてのSlurmジョブ投入

# ジョブ投入概要

知人より知見をまとめてほしいとの、要望をいただきました。
ユーザとしてこれくらい知っておけば、大丈夫という程度の、Slurm情報をここにまとめます。

## 3つのジョブ投入方法

ジョブの投入方法は主に以下の3つがあります。

- `sbatch` : バッチジョブで使用します。
- `srun` : インタラクティブジョブで使用します。また、`sbatch`でジョブ投入するとき、マシンファイルを作成のためにも利用可能です。
- `salloc` : ノードのみを確保し、その後、複数回にわたり srun コマンドを実行する場合などに使います。

基本的には通常のバッチジョブは `sbatch` を利用し、インタラクティブジョブは `srun` を利用してください。sallloc の具体的な使い方は、「`salloc` で計算ノードを確保する」 を参照してください。

# 0. 事前準備

## パーティション名(キュー名)の確認

`sinfo -s` コマンドを実行します。

```terminal
$ sinfo -s
PARTITION    AVAIL  TIMELIMIT   NODES(A/I/O/T)  NODELIST
test1*          up   infinite        93/3/0/96  worker[01-96]
test2           up   infinite          0/6/2/8  worker-lmem[01-08]
sambanova*      up   infinite          0/2/0/2  host[1-2]
```

- test1とtest2のパーティション(キュー)があることが分かります。
- test1の横に * はデフォルトパーティションであることを示しています。パーティション(キュー)を指定しない場合、これが自動的に使用されます。

## ノード利用状況の確認方法

`NODES (A/I/O/T)` によりノードの利用状況を確認します。意味は下記のようになります。

| 記号 | 意味      | 説明                                               | 
| ---- | --------- | -------------------------------------------------- | 
| A    | Allocated | 使用中のノード数                                   | 
| I    | Idle      | 空きノード数                                       | 
| O    | Other     | 故障等でスケジュール管理から除外されているノード数 | 
| T    | Total     | トータルのノード数                                 | 

# 1. sbatchによるジョブ投入

Slurmのバッチジョブの投入コマンドである sbatch を用いてジョブ投入/確認までの一連の流れを最初に確認します。

複雑なsbatchによるジョブ投入は以下をご参照ください

https://qiita.com/daikumatan/items/63d4873686178a69f474

## 1.1 ノード仕様の確認

利用したいノードが何コアあるかなど、その仕様を確認したい場合は、以下のように確認できます。

```terminal
$ scontrol show nodes host1
NodeName=host1 Arch=x86_64 CoresPerSocket=1 
   CPUAlloc=0 CPUTot=128 CPULoad=0.29
   AvailableFeatures=(null)
   ActiveFeatures=(null)
   Gres=rdu:8,rdu_mem:1T,rdu_tile:64
   NodeAddr=host1 NodeHostName=host1 Version=20.02.5
   OS=Linux 5.4.0-147-generic #164-Ubuntu SMP Tue Mar 21 14:23:17 UTC 2023 
   RealMemory=1 AllocMem=0 FreeMem=294638 Sockets=128 Boards=1
   State=IDLE ThreadsPerCore=1 TmpDisk=0 Weight=1 Owner=N/A MCS_label=N/A
   Partitions=sambanova 
   BootTime=2024-03-15T08:30:50 SlurmdStartTime=2024-03-15T16:23:12
   CfgTRES=cpu=128,mem=1M,billing=128
   AllocTRES=
   CapWatts=n/a
   CurrentWatts=0 AveWatts=0
   ExtSensorsJoules=n/s ExtSensorsWatts=0 ExtSensorsTemp=n/s
```

## 1.2 ジョブの投入

### 1.2.1 ランスクリプトの作成

以下のファイルを `run.sh` という名前で作成してください。

`#SBATCH --partition <パーティション名(キュー名)>` でパーティション名(キュー名)を指定します。 test2 を環境に応じて適当な名前に変更してください。

クラスターのキュー名を確認する方法は、「パーティション名(キュー名)の確認とノード利用状況の確認」 をご参照ください。

```bash
#!/bin/bash
#SBATCH --partition sambanova
#SBATCH --job-name sample
#SBATCH --ntasks=4

echo "---- machinefile ----"
srun -n ${SLURM_NTASKS} hostname | sort > my_hosts

echo "---- Slurm Environment Variables ----"
cat <<ETX
JOB_ID="${SLURM_JOB_ID}"
JOB_NAME="${SLURM_JOB_NAME}"
PARTITION_NAME="${SLURM_JOB_PARTITION}"
NODE_LIST="${SLURM_JOB_NODELIST}"
NTASKS="${SLURM_NTASKS}"
ETX

echo "---- Start Your Application ----"
sleep 10
# if MPI Job,
# mpirun -n ${SLURM_NTASKS} -machinefile my_hosts hello_mpi
```


:::note info
Slurmによるマシンファイルの作成方法は、一般的に generate_pbs_nodefile と srun による方法がありますが、ここでは後者の方法を採用しました。
:::


### 1.2.2 ジョブの投入

```bash
$ sbatch run.sh
Submitted batch job 1304
```

sbatchコマンドの詳細については、付録の 「sbatch コマンドによるジョブの投入」 をご参照ください。

## 1.3. 投入したジョブステータス確認

```terminal
$ squeue
             JOBID PARTITION     NAME     USER ST       TIME  NODES NODELIST(REASON) 
                38 sambanova   sample daisuke.  R       0:02      1 host1 
```

## 1.4. 投入したジョブをキャンセルする場合

squeueの結果からJOBIDを確認し、ジョブをキャンセルします

```bash
scancel 38
```

確認後はもう一度 `squeue` を実行しジョブがキャンセルされたことを確認しましょう

```bash
squeue
```

## 1.5. 過去に実行したジョブのステータス確認

すでに終了したジョブを確認するには sacct コマンドが便利です。 sacctの詳細は 「sacctコマンドの使い方」 をご参照ください。

```terminal
$ sacct --starttime 2020-10-22 \
    --format JobID%5,JobName%16,Partition,NCPU%5,ReqCPUS,Start,End,Elapsed%8,State -X

JobID          JobName  Partition NCPUS  ReqCPUS               Start                 End  Elapsed      State
----- ---------------- ---------- ----- -------- ------------------- ------------------- -------- ----------
 1302           sample      test1     8        1 2020-10-22T14:33:25 2020-10-22T14:52:17 00:18:52 CANCELLED+
 1303          handson      test2    16        4 2020-10-22T14:51:45 2020-10-22T14:51:45 00:00:00  COMPLETED
 1304          handson      test2    16        4 2020-10-22T14:54:35 2020-10-22T14:54:51 00:00:16  COMPLETED
```

# 2. srunによるインタラクティブジョブの実行

次に、Interactive Jobを実行してみます。

## 2.1. インタラクティブジョブの開始

インタラクティブジョブ下記コマンドにて開始します。各種オプションの意味は以下の通りです。

- `-p test2`: test2のPartition(キュ-)を使います。流体であれば `-p test1` を使用してください。
- `-N2`: 2ノードを確保します。
- `-n8`: アプリケーションとしてはノードあたり4コアずつ、トータル8コアを使います。
- `--time`: 24:00:00: 24時間,2ノードを確保します。

`--pty bash`: シェルはbashとなります。cshを使い方は、`--pty csh` に変更してください。

```terminal
[login ~]$ srun -N2 -n8 --job-name "InteractiveJob" --time 24:00:00 --pty bash -i
[worker01 ~]$
```

この例では、`login`は、ログインノード名、`worker01`は割り当てられたコンピュートノード名を示します。 上記コマンドの実行でプロンプト名が計算ノードにかわったことがわかります。つまり計算ノードを直接操作することができます。 使用する環境/ジョブの状況によってこれらの名前は変わります。計算ノード名のリストは `sinfo -s` を実行し確認することができます。


:::note info
インタラクティブジョブのため、 `-N2` だけでも良いですが、MPIジョブの場合、-n8 も加えることで、正しくマシンファイルが生成されるメリットがあります。 つまり、並列アプリを実行するときに、マシンファイルを自分で作成する手間がなくなります。またコア数に関するSlurmの環境変数も正しく使用することができます。
:::

念のため `hostname` コマンドでターミナルのホストが計算ノードに変わっていることを確認します。

```terminal
[worker01 ~]$ hostname
worker01
```
またノードが2ノード確保されていることを確認します。

```terminal
[worker01 ~]$ squeue
     JOBID PARTITION     NAME     USER ST       TIME  NODES NODELIST(REASON)
      2026     test2 Interact xd-daisu  R       1:22      2 worker-lmem[01-02]
```

## 2.2. インタラクティブジョブによるMPIアプリケーションの実行

アプリケーションを実行します。 テストとして、まずは指定したすべてのコアに対して、`hostname` を表示してみます。

```terminal
[worker01 ~]$ srun hostname
worker-lmem02
worker-lmem02
worker-lmem02
worker-lmem02
worker-lmem01
worker-lmem01
worker-lmem01
worker-lmem01
```

マシンファイルを作成し確認します。

```terminal
[worker01 ~]$ srun hostname > my_hosts && cat my_hosts
worker-lmem01
worker-lmem01
worker-lmem01
worker-lmem01
worker-lmem02
worker-lmem02
worker-lmem02
worker-lmem02
```

今回は、アプリケーションとして、Intel MPIを使用しているため、Intel MPI環境を現在のシェルに読み込みます。

```terminal
[worker01 ~]$ source /opt/intel/bin/iccvars.sh -arch intel64 -platform linux
```

`${SLURM_NTASKS}` は、上記で `srun -N2 -n8` ... を実行した際の `-n8` に相当します。

```terminal
[worker01 ~]$ mpirun -n ${SLURM_NTASKS} -machinefile my_hosts <your mpi application>
```

## 2.3. インタラクティブジョブの終了

exit してインタラクティブジョブを終了します。プロントがホスト名に戻っていることを確認してください。

```terminal
[worker01 ~]$ exit
exit
[login ~]$
```

squeue でジョブが終了していることを確認します

```terminal
[login ~]$ squeue
     JOBID PARTITION     NAME     USER ST       TIME  NODES NODELIST(REASON)
```

# 3. sallocで計算ノードを確保する

- salloc でノードのみを確保
- その後、srunでインタラクティブジョブを実行し一度作業を終了しセッションを切る
- srunは終了しても、sallocによるSlurmジョブは終了せずノード確保は維持されるため、再度srunでインタラクティブジョブを実行する