user/pages/07.run/04.tips/docs.ja.md
452be89a
 ---
 title: ジョブ実行のヒント
 taxonomy:
     category:
         - docs
 external_links:
     process: true
     title: false
     no_follow: true
     target: _blank
     mode: active
 ---
 
 [toc]
 
 ## 環境変数{#env_val}
 ### 環境変数の設定と参照
 環境変数の設定にはexportコマンドを使用し、環境変数を参照する場合は変数名の先頭に「$」を付与して記述します。
 
 * 環境変数の設定
 ```nohighlight
 #書式 環境変数名=値; export 環境変数名
 LANG=en_US.UTF-8; export LANG
 ```
 
 * 環境変数の参照
 ```nohighlight
 echo $LANG
 ```
 
 ### ジョブ実行時に設定される環境変数
 |環境変数名|意味|
 | ---           |--- |
 |$SLURM_CPUS_ON_NODE|コア数/ノード|
f39696f5
 |$SLURM_DPC_CPUS|タスクごとの物理コア数|
 |$SLURM_CPUS_PER_TASK|タスクごとの論理コア数|
452be89a
 |$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|送信元ホスト|
 
 ## ジョブ投入時に使用できないオプション{#sbatch_ignore}
 
 以下のオプションは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 領域について
 
 本センターのスーパーコンピュータシステムでは、/tmpの領域を一時的なデータの書き込み先として利用できます。
 細かいファイルI/Oを伴うプログラムは、/tmpを利用したほうが高速に処理できるケースがあります。
 
 /tmpはジョブごとにプライベートな領域として用意しますので、他のジョブとファイルが
 混在しないように作りこんでありますので、ぜひご活用ください。
 
 なお、/tmp の領域は、ジョブの終了時に自動で削除されますので、/tmpに書き込んだファイルを
 残すためには、ジョブスクリプトに /homeや/LARGE0,/LARGE1 にファイルをコピーする
 記述を含めて頂く必要があります。あとから取り出すことはできませんので、ご注意ください。
 
 ### /tmpを使用する具体例
 
 * プログラムで指定が可能な場合は、ファイルの書き込み先を /tmp に指定する。
 * 繰り返し読み込むファイルをプログラム実行開始前に /tmp に配置する。
 * 相対PATHでファイルにアクセスするプログラムや入力ファイルを、/tmp に配置したうえで実行する。
 
 ### 利用可能な/tmpの容量
 
 各システムで利用可能な/tmpの容量は、
 `プロセス数 x プロセスあたりのコア数 x システム毎のコアあたりの容量(次表参照)`
 で求めることができます。
 
 |システム名 | コアあたりの容量 |
 |---------- | -----------------|
495abba5
 |システムA  |   2.4G           |
452be89a
 |システムB  |   8.9G           |
 |システムC  |   8.9G           |
 |システムG  |   15.6G          |
 |クラウド   |   94G            |
 <!--
 |システムA  |   2.4G           |
 |システムB  |   8.9G           |
 |システムC  |   8.9G           |
 |システムG  |   15.6G          |
 -->
 
 例えば、システムBで4プロセス(1プロセスあたり 8コア) のジョブを投入した場合は
 `4 x 8 x 8.9` から、**284.8GB** の割当が行われます。
 
 ## ジョブの実行順序を指定する{#dependency}
 すでに投入されたジョブの実行状況に合わせて、これから投入するジョブの実行開始のタイミングを制御することができます。
 具体的には、ジョブ投入オプション欄に以下の内容を追記することで、実現することができます。
 ```nohighlight
 #SBATCH -d <実行順序の指定コマンド>:<すでに投入済みのジョブID>
 ```
 
 例えば、ジョブスクリプトAの実行が正常に終了した場合に、ジョブスクリプトBを続けて実行したい場合は、
 以下の手順で実現することができます。
 
 1. ジョブスクリプトAをジョブに投入します。
 2. 1.で投入したジョブのジョブIDが「200」の場合、ジョブスクリプトBは以下のようになります。
 *
 ```nohighlight
 #!/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|指定したジョブが異常終了した場合にジョブを実行する。なお、指定したジョブが正常終了した場合は実行されずに終了します。|
 
 ## アレイジョブの実行{#arrayjob}
 アレイジョブ機能を用いることで、パラメータが異なる複数のジョブを1つのジョブスクリプトで実行することができます。
 具体的には、ジョブ投入オプション欄に以下の内容を追記することで、実現することができます。
 ```nohighlight
 #SBATCH -a <start_num>-<end_num>[option]
 ```
 
 例えば、./a.out に ジョブスクリプトと同一ディレクトリに配置した、1.data, 2.data, 3.data を渡して解析を行う
 ジョブを実行したい場合は、以下のようなジョブスクリプトを書くことによって、実現することができます。
 ```nohighlight
 #!/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台の計算ノードで複数のプログラムを同時に実行する方法{#multirun}
 
 1つのジョブの中で、複数のプログラムを同時に実行させることによって、計算資源を有効に利用することができます。
 複数のプログラムを1つのジョブとして同時に実行させるためには、シェルスクリプト中に複数の実行コマンドを記載し、そのシェルスクリプトを実行するようにします。
 
6fe23678
 ※本手法の対象は、逐次プログラムもしくはOpenMPや自動並列化機能でスレッド並列化したプログラムです。<br>
 ※複数のMPIプログラムを1つのジョブとして同時に実行する場合は、[複数のプログラムを同時に実行する方法(MPMD)](#mpmd)を
 ご参照下さい。
452be89a
 
 各スクリプトの例を以下に記します。
 
 #### 逐次実行(1プログラムあたり1スレッド)
 
 ** sbatchコマンドで実行するジョブスクリプト(逐次) **
 
 ※下記のスクリプトは、プログラムを4つ同時に実行する場合のサンプルです
 
 ```nohighlight
 #!/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コマンドに続けて実行する**シェルスクリプト**のパスを記載します。
 
 ** ジョブスクリプト中で実行するシェルスクリプト(逐次) **
 
 ```nohighlight
 #!/bin/bash
 case $SLURM_PROCID in
     0) ./a1.out ;;
     1) ./a2.out ;;
     2) ./a3.out ;;
     3) ./a4.out ;;
 
 esac
 ```
 
 * リソースを確保すると、それぞれのプロセスごとにランク番号が付与されます。
 * プロセスが実行されると、環境変数 SLURM_PROCID から割り当てられたランク番号を読み出すことが可能となります。
 * ランク番号を用いて処理分岐を行うシェルスクリプトを作成することで、実行するプログラムをプロセスごとに分けることが可能となります。
 これによって、複数のプログラムを1つのジョブとして同時に実行する事が可能となります。
 
 #### OpenMP実行
 
 ** sbatchコマンドで実行するジョブスクリプト(OpenMP) **
 
 ※下記のスクリプトは、4スレッド実行のプログラムを8つ同時に実行する場合のサンプルです
 
 ```nohighlight
 #!/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) **
 
 ```nohighlight
 #!/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={使用したいスレッド数} ** をプロセスごとに定義します。
 
 ```nohighlight
 #!/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
 ```
6fe23678
 
 ## 複数のプログラムを同時に実行する方法(MPMD){#mpmd}
 
 ** sbatchコマンドで実行するジョブスクリプト(MPI) **
 
 ※下記のスクリプトは、4プロセスを必要とするMPIプログラム(1プロセスあたり4コア、4スレッド)を
 3つ同時に実行する場合のサンプルです。
 
 ```nohighlight
 #!/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コマンドには以下のオプションを指定します。
 <!--
     * -n には同時に実行したいプロセス数の合計を記載。$SLURM_DPC_NPROCSという環境変数を記載することで --rscオプションで指定したプロセス数を読み出すことができますので、基本的には変更不要。
     * -c には利用するプロセス(プログラム)あたりに使用するコア数を記載。$SLURM_DPC_CPUSという環境変数を記載することで --rscオプションで指定したコア数を読み出すことができますので、基本的には変更不要。
 -->
     * --multi-prog には以下で作成するMPIプログラムの実行に関する内容を記述した設定ファイル(multiprocess.conf)へのパスを記載。
 
 
 ** 設定ファイル(multiprocess.conf) **
 
 ```nohighlight
 ## 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プログラムごとにカスタマイズをすることはできません。
 
 ```nohighlight
 ## 4プロセスを使用してMPIプログラムを実行
 0-3  ./aaa.out
 ## 8プロセスを使用してMPIプログラムを実行
 4-11 ./bbb.out
 ```