ジョブ実行のヒント

環境変数の設定にはexportコマンドを使用し、環境変数を参照する場合は変数名の先頭に「$」を付与して記述します。

  • 環境変数の設定

    #書式 環境変数名=値; export 環境変数名
    LANG=en_US.UTF-8; export LANG
  • 環境変数の参照

    echo $LANG

環境変数名 意味
$SLURM_CPUS_ON_NODE コア数/ノード
$SLURM_DPC_CPUS タスクごとの物理コア数
$SLURM_CPUS_PER_TASK タスクごとの論理コア数
$SLURM_JOB_ID ジョブID (アレイジョブの場合は $SLURM_ARRAY_JOB_ID を使用してください)
$SLURM_ARRAY_JOB_ID アレイジョブ実行時の親となるジョブID
$SLURM_ARRAY_TASK_ID アレイジョブ実行時のタスクID
$SLURM_JOB_NAME ジョブ名
$SLURM_JOB_NODELIST ジョブに割り当てられたノード
$SLURM_JOB_NUM_NODES ジョブに割り当てられているノード数
$SLURM_LOCALID ノード内の実行中のノードのインデックス
$SLURM_NODEID ジョブに割り当てられたノードに対する相対的なインデックス
$SLURM_NTASKS ジョブのプロセス数
$SLURM_PROCID ジョブに対するタスクのインデックス
$SLURM_SUBMIT_DIR サブミットディレクトリ
$SLURM_SUBMIT_HOST 送信元ホスト

newgrpコマンドは、newgrp gr19999のように、グループ名をそのまま打つと、打った後の新しいグループの環境には環境変数LD_LIBRARY_PATHが引き継がれません。 一方、newgrp - gr19999のようにハイフンをつけることで、環境変数LD_LIBRARY_PATHとしてログイン時の初期値が再設定されますが、こちらでは環境変数DISPLAYが消えるため、X11ソフトウェアで接続している場合に問題が生じます。

そこで、newgrpを実行する前にロードしていたモジュールによって設定されていた環境変数を再設定するためのコマンドとして、reload_modulesコマンドを用意しております。

# newgrp を実行する前の LD_LIBRARY_PATH の状態
[b59999@laurel31 ~]$ echo $LD_LIBRARY_PATH
/opt/system/app/intel/2023.1/mpi/2021.9.0/libfabric/lib:...

# newgrp を実行した後の LD_LIBRARY_PATH の状態
[b59999@laurel31 ~]$ newgrp gr19999
[b59999@laurel31 ~]$ echo $LD_LIBRARY_PATH
(中身がクリアされてしまっている)

# reload_modules を実行することで、LD_LIBRARY_PATH が再設定される
[b59999@laurel31 ~]$ reload_modules
[b59999@laurel31 ~]$ echo $LD_LIBRARY_PATH
/opt/system/app/intel/2023.1/mpi/2021.9.0/libfabric/lib:...

以下のオプションはsbatchコマンドおよびジョブスクリプトの #SBATCH の指示文で指定できませんのでご注意ください。

オプション
--batch --clusters(-M) --constraint(-C) --contiguous --core-spec(-S)
--cores-per-socket --cpus-per-gpu --cpus-per-task(-c) --distribution(-m) --exclude(-x)
--exclusive --gpu-bind --gpus(-G) --gpus-per-node --gpus-per-socket
--gres --gres-flags --mem --mem-bind --mem-per-cpu
--mem-per-gpu --mincpus --nodefile(-F) --nodelist(-w) --nodes(-N)
--ntasks(-n) --ntasks-per-core --ntasks-per-gpu --ntasks-per-node --ntasks-per-socket
--overcommit(-O) --oversubscribe(-s) --qos(-q) --sockets-per-node --spread-job
--switches --thread-spec --threads-per-core --use-min-nodes
--get-user-env --gid --priority --reboot --uid

本センターのスーパーコンピュータシステムでは、/tmpの領域を一時的なデータの書き込み先として利用できます。 細かいファイルI/Oを伴うプログラムは、/tmpを利用したほうが高速に処理できるケースがあります。

/tmpはジョブごとにプライベートな領域として用意しますので、他のジョブとファイルが 混在しないように作りこんでありますので、ぜひご活用ください。

なお、/tmp の領域は、ジョブの終了時に自動で削除されますので、/tmpに書き込んだファイルを 残すためには、ジョブスクリプトに /homeや/LARGE0,/LARGE1 にファイルをコピーする 記述を含めて頂く必要があります。あとから取り出すことはできませんので、ご注意ください。

  • プログラムで指定が可能な場合は、ファイルの書き込み先を /tmp に指定する。
  • 繰り返し読み込むファイルをプログラム実行開始前に /tmp に配置する。
  • 相対PATHでファイルにアクセスするプログラムや入力ファイルを、/tmp に配置したうえで実行する。

各システムで利用可能な/tmpの容量は、 プロセス数 x プロセスあたりのコア数 x システム毎のコアあたりの容量(次表参照) で求めることができます。

システム名 コアあたりの容量
システムA 2.4G
システムB 8.9G
システムC 8.9G
システムG 15.6G
クラウド 94G

例えば、システムBで4プロセス(1プロセスあたり 8コア) のジョブを投入した場合は 4 x 8 x 8.9 から、284.8GB の割当が行われます。

すでに投入されたジョブの実行状況に合わせて、これから投入するジョブの実行開始のタイミングを制御することができます。 具体的には、ジョブ投入オプション欄に以下の内容を追記することで、実現することができます。

#SBATCH -d <実行順序の指定コマンド>:<すでに投入済みのジョブID>

例えば、ジョブスクリプトAの実行が正常に終了した場合に、ジョブスクリプトBを続けて実行したい場合は、 以下の手順で実現することができます。

  1. ジョブスクリプトAをジョブに投入します。

  2. 1.で投入したジョブのジョブIDが「200」の場合、ジョブスクリプトBは以下のようになります。 *

    #!/bin/bash
    #============ SBATCH Directives =======
    #SBATCH -p gr19999b
    #SBATCH -t 2:0:0
    #SBATCH --rsc p=4:t=8:c=8:m=8G
    #SBATCH -d afterok:200
    #SBATCH -o %x.%j.out
    #============ Shell Script ============
    srun ./a.out
  3. ジョブスクリプトBをジョブに投入します。

なお、実行順序の指定は以下の4つから選ぶことができます。

実行順序の指定コマンド 意味
after 指定したジョブの開始後にジョブを実行する。
afterany 指定したジョブの終了後にジョブを実行する。
afterok 指定したジョブが正常終了した場合にジョブを実行する。なお、指定したジョブが異常終了した場合は実行されずに終了します。
afternotok 指定したジョブが異常終了した場合にジョブを実行する。なお、指定したジョブが正常終了した場合は実行されずに終了します。

アレイジョブ機能を用いることで、パラメータが異なる複数のジョブを1つのジョブスクリプトで実行することができます。 具体的には、ジョブ投入オプション欄に以下の内容を追記することで、実現することができます。

#SBATCH -a <start_num>-<end_num>[option]

例えば、./a.out に ジョブスクリプトと同一ディレクトリに配置した、1.data, 2.data, 3.data を渡して解析を行う ジョブを実行したい場合は、以下のようなジョブスクリプトを書くことによって、実現することができます。

#!/bin/bash
#============ SBATCH Directives =======
#SBATCH -p gr19999b
#SBATCH -t 2:0:0
#SBATCH --rsc p=4:t=8:c=8:m=8G
#SBATCH -a 1-3
#SBATCH -o %x.%A_%a.out
## %xはジョブ名、%AはアレイジョブID、%aはアレイタスクIDに置換されます。
#============ Shell Script ============
srun ./a.out ${SLURM_ARRAY_TASK_ID}.data

なお、[option] には以下オプションを設定することができます。

[option]に記載する内容 実行内容
:[0-9] 指定した数値毎に実行する。例えば 「1-5:2」とした場合は、1,3,5が実行される。
%[0-9] 指定した数値が同時実行数の最大値として設定される。例えば「%2」とした場合は、同時実行数の最大値は「2」となる。

1つのジョブの中で、複数のプログラムを同時に実行させることによって、計算資源を有効に利用することができます。 複数のプログラムを1つのジョブとして同時に実行させるためには、シェルスクリプト中に複数の実行コマンドを記載し、そのシェルスクリプトを実行するようにします。

※本手法の対象は、逐次プログラムもしくはOpenMPや自動並列化機能でスレッド並列化したプログラムです。
※複数のMPIプログラムを1つのジョブとして同時に実行する場合は、複数のプログラムを同時に実行する方法(MPMD)を ご参照下さい。

各スクリプトの例を以下に記します。

sbatchコマンドで実行するジョブスクリプト(逐次)

※下記のスクリプトは、プログラムを4つ同時に実行する場合のサンプルです

#!/bin/bash
#============ SBATCH Directives =======
#SBATCH -p gr19999b
#SBATCH --rsc p=4:t=1:c=1:m=3G
#SBATCH -o %x.%j.out
#============ Shell Script ============
srun ./multiprocess.sh
  • キューを -p オプションで指定します。
  • 使用するリソースを --rsc オプションで下記の通り指定します。
    • 引数pには使用するプロセス数。
      • 同時に実行したいプログラム数を指定してください。ここでは4となります。
    • 引数cには利用するプロセス(プログラム)あたりに使用するコア数。
      • プログラムはシングルスレッド実行ですので、1を指定します。
    • 引数tには利用するプロセス(プログラム)あたりに使用するスレッド数。
      • プログラムはシングルスレッド実行ですので、1を指定します。
    • 引数mには利用するメモリプロセス(プログラム)辺りの容量。
  • srunコマンドに続けて実行するシェルスクリプトのパスを記載します。

ジョブスクリプト中で実行するシェルスクリプト(逐次)

#!/bin/bash
case $SLURM_PROCID in
    0) ./a1.out ;;
    1) ./a2.out ;;
    2) ./a3.out ;;
    3) ./a4.out ;;

esac
  • リソースを確保すると、それぞれのプロセスごとにランク番号が付与されます。
  • プロセスが実行されると、環境変数 SLURM_PROCID から割り当てられたランク番号を読み出すことが可能となります。
  • ランク番号を用いて処理分岐を行うシェルスクリプトを作成することで、実行するプログラムをプロセスごとに分けることが可能となります。 これによって、複数のプログラムを1つのジョブとして同時に実行する事が可能となります。

sbatchコマンドで実行するジョブスクリプト(OpenMP)

※下記のスクリプトは、4スレッド実行のプログラムを8つ同時に実行する場合のサンプルです

#!/bin/bash
#============ SBATCH Directives =======
#SBATCH -p gr19999b
#SBATCH -t 2:0:0
#SBATCH --rsc p=8:t=4:c=4:m=3G
#SBATCH -o %x.%j.out
#============ Shell Script ============
srun ./multiprocess.sh
  • キューを -p オプションで指定します。
  • 使用するリソースを --rsc オプションで下記の通り指定します。
    • 引数pには使用するプロセス数。
      • 同時に実行したいプログラム数を指定してください。ここでは8となります。
    • 引数cには利用するプロセス(プログラム)あたりに使用するコア数。
      • プログラムは4スレッド実行ですので、4を指定します。
    • 引数tには利用するプロセス(プログラム)あたりに使用するスレッド数。
      • プログラムは4スレッド実行ですので、4を指定します。
    • 引数mには利用するメモリのプロセス(プログラム)辺りの容量。
  • srunコマンドに続けて実行するシェルスクリプトのパスを記載します。

ジョブスクリプト中で実行するシェルスクリプト(OpenMP)

#!/bin/bash
case $SLURM_PROCID in
    0)  ./aaa.out ;;
    1)  ./bbb.out ;;
    2)  ./ccc.out ;;
    3)  ./ddd.out ;;
    4)  ./eee.out ;;
    5)  ./fff.out ;;
    6)  ./ggg.out ;;
    7)  ./hhh.out ;;

esac
  • リソースを確保すると、それぞれのプロセスごとにランク番号が付与されます。
  • プロセスが実行されると、環境変数 SLURM_PROCID から割り当てられたランク番号を読み出すことが可能となります。
  • ランク番号を用いて処理分岐を行うシェルスクリプトを作成することで、実行するプログラムをプロセスごとに分けることが可能となります。 これによって、複数のプログラムを1つのジョブとして同時に実行する事が可能となります。

ジョブスクリプトで「#SBATCH --rsc t=4」 を指定したことで、ジョブスケジューラによって1プロセスあたり4スレッド使用する設定が自動的に行われます。 そのため、上記シェルスクリプトでは各プログラムを4スレッドで実行されます。

プロセスごとにスレッド数を変化させたい場合は、下記のように OMP_NUM_THREADS={使用したいスレッド数} をプロセスごとに定義します。

#!/bin/bash
case $SLURM_PROCID in
    0) export OMP_NUM_THREADS=1; ./aaa.out ;;
    1) export OMP_NUM_THREADS=2; ./bbb.out ;;
    2) export OMP_NUM_THREADS=2; ./ccc.out ;;
    3) export OMP_NUM_THREADS=3; ./ddd.out ;;
    4) export OMP_NUM_THREADS=3; ./eee.out ;;
    5) export OMP_NUM_THREADS=4; ./fff.out ;;
    6) export OMP_NUM_THREADS=4; ./ggg.out ;;
    7) export OMP_NUM_THREADS=4; ./hhh.out ;;

esac

sbatchコマンドで実行するジョブスクリプト(MPI)

※下記のスクリプトは、4プロセスを必要とするMPIプログラム(1プロセスあたり4コア、4スレッド)を 3つ同時に実行する場合のサンプルです。

#!/bin/bash
#============ SBATCH Directives =======
#SBATCH -p gr19999b
#SBATCH -t 2:0:0
#SBATCH --rsc p=12:t=4:c=4:m=3G
#SBATCH -o %x.%j.out
#============ Shell Script ============
srun --multi-prog ./multiprocess.conf
  • キューを -p オプションで指定します。
  • 使用するリソースを --rsc オプションで下記の通り指定します。
    • 引数pには使用するプロセス数。
      • 同時に実行したいプロセス数の合計(4プロセスを使用するMPIプログラムを3つ同時に実行したい場合は、4×3から12を指定)
    • 引数cには利用するプロセス(プログラム)あたりに使用するコア数。
      • プログラムは4スレッド実行ですので、4を指定します。
    • 引数tには利用するプロセス(プログラム)あたりに使用するスレッド数。
      • プログラムは4スレッド実行ですので、4を指定します。
    • 引数mには利用するメモリのプロセス(プログラム)辺りの容量。
  • srunコマンドには以下のオプションを指定します。
    • --multi-prog には以下で作成するMPIプログラムの実行に関する内容を記述した設定ファイル(multiprocess.conf)へのパスを記載。

設定ファイル(multiprocess.conf)

## 4プロセスを使用してMPIプログラムを実行
0-3  ./aaa.out 
4-7  ./bbb.out
8-11 ./ccc.out
  • 1列目には、MPIプログラムが使用するプロセスIDのレンジを記載して下さい。(プロセスIDは、0始まりであることに注意)
  • 2列目には、1列目で指定したプロセスIDで実行するMPIプログラムのパス(絶対パス、相対パスの何れにも対応)を記載して下さい。

なお、使用するプロセス数はMPIプログラムごとに変更することができます。 例えば、a1.outというプログラムでは4プロセスを使用し、a2.outというプログラムでは8プロセスを使用したいと いった場合は、以下のような設定ファイルを作成することで実現することが可能です。 ただし、1プロセスあたりのコア数、スレッド数、メモリ量については、--rscオプションで指定した値が自動的に 設定されるため、MPIプログラムごとにカスタマイズをすることはできません。

## 4プロセスを使用してMPIプログラムを実行
0-3  ./aaa.out
## 8プロセスを使用してMPIプログラムを実行
4-11 ./bbb.out