ジョブ投入
EIC計算機システムの構成
EIC計算機システムの計算サーバは,4CPUx4ノードのIntel Xeon Platinum 8468Hと2CPUx15ノードのAMD EPYC 9654からなるハイブリッドシステムです.Intel Xeon Platinum 8468HはCPUあたり48コア,AMD EPYC 9654はCPUあたり96コアを持ちます.
最初のジョブ
以下の簡単なFortranプログラム hello.f90 をジョブ管理システムを用いて実行してみます.
program hello
implicit none
write(*,*) "Hello EIC!"
call sleep(60)
end program helloこれは,標準出力に Hello miyabi!と出力し,60秒間待つだけのプログラムです. EICのFortranコンパイラftnを用いてコンパイルしましょう.
ftn hello.f90 -o hello.xhello.xは単一のCPUコアを用いた小さなプログラムですから,直接実行することもできますが,あえてこれをジョブにしてみます.
ジョブスクリプトの作成
ジョブは,必要となる計算資源やプログラムの実行文をまとめたジョブスクリプトを書き,それを投入することで実行します.投入されたジョブはすぐに実行されるとは限りません.コンピュータの混雑時にはジョブ管理システムによって計画的に実行されます.
先ほどのhello.xを実行するジョブスクリプトは以下のようなものです.
#!/bin/bash
#PBS -q B
#PBS -l select=1:ncpus=24
#PBS -j oe
#PBS -N hello
#PBS -m abe
#PBS -M your@email.address
module load PrgEnv-intel
module load cray-pals
module load cray-pmi
cd ${PBS_O_WORKDIR}
./hello.xただし,your@email.addressは自分のメールアドレスに変更してください.
スクリプト各行の意味は後ほど説明することとして,とりあえず実行してみましょう.
ジョブの投入と監視
ジョブを投入して実行させるには,qsubコマンドを使います.
$ qsub job.sh
62019.eic投入に成功すると,上記の例のように5桁の数字+.eicという文字列が表示されます.この数字が投入されたジョブに固有のジョブID番号です.
投入されたジョブの状態は qstat あるいは qstatus コマンドで確認できます.qstatusのほうがやや見やすいでしょう.
$ qstatus
JobID username status Queue hostname ncpus mpi/omp walltime cputime cputime/ usemem
walltime
----- -------- ------ ----- ------------- ----- ------- -------- ----------- -------- ------
(中略)
62019 jXXXXX R B eicp02 24 -/- 00:00:10 00:00:00 0.0status欄の記号は
R: 実行中Q: ジョブ受付済みで実行まで待機中H: ホールド(順番に実行するステップジョブの場合)
のようです1.
EIC計算機システムでは,自分以外のユーザーのジョブ実行状態もすべて表示されます.qstat/qstatusの表示から自分のJobIDがなくなったら実行終了です.ジョブの開始時と終了時にはメールも届いているはずです.
カレントディレクトリでlsしてみると,出力ファイル hello.oXXXXXが作られているはずです.ただしXXXXXはジョブID番号です.このなかにプログラムの出力が含まれています.
$ cat hello.oXXXXX
Hello EIC!出力ファイルは,ジョブの実行が始まってすぐに作成され,プログラムの進行とともに継ぎ足されていきます.もちろん,プログラムが何も画面に出力しないのであれば,ファイルは空のままです.
以上をまとめると,ジョブ管理システムにおけるプログラム実行は,以下のような手続きからなります.
- プログラムの作成とコンパイル
- ジョブスクリプトの作成
- ジョブの投入
- 実行待機と(必要があれば)監視
- ジョブの終了確認
- 出力結果ファイルの解析
ジョブスクリプトにおける指定
それでは,あらためてジョブスクリプトの書き方を説明していきます.ジョブスクリプトの先頭にある#PBS から始まる文が,ジョブ実行の設定です.以下に説明するジョブ投入コマンドのコマンドラインオプションとしても指定できるのですが,煩雑になるのでスクリプトで記述するほうがお勧めです.沢山ありますが,実はすべてが必須というわけではなく,使う可能性があるものをすべて列挙しています.意味は以下の表の通りです.
| オプション | 必須 | 意味 |
|---|---|---|
-q B |
YES | ジョブクラス |
-l select=1:ncpus=24 |
YES | 使用ノード・コア数 |
-j oe |
no | 標準出力と標準エラー出力を統合 |
-N hello |
no | ジョブの名前を指定 |
-m abe |
no | ジョブの開始終了時にメール送信 |
-M your@email.address |
no | メール送信先アドレス |
以下,順番に詳しく説明していきます.
ジョブクラス
前述のとおりEICはAMDとIntelのCPUを持ちますが,それぞれに対し,いくつまでコアを使えるかによって,以下のような7種類のジョブクラスが設定されています.
| Class | B | C | D | E | L | M | N |
|---|---|---|---|---|---|---|---|
| CPU | AMD | AMD | AMD | AMD | Intel | Intel | Intel |
| Memory (GB) | 192 | 384 | 768 | 1536 | 128 | 256 | 512 |
| Core | 24 | 48 | 96 | 192 | 24 | 48 | 96 |
| 同時実行数 | 8 | 8 | 8 | 8 | 8 | 4 | 4 |
クラスB〜EがAMDのCPU,L〜NがIntelのCPUを用いたノードです.AMD系とIntel系でそれぞれ専用のコンパイラも用意されています.ただし,AMDとIntelのCPUはバイナリ互換性があり,提供されているコンパイラの種類によらずどのクラスでも実行できます.少なくとも以下で紹介するOpenSWPCに関しては1種類の実行バイナリでどちらのCPUでも十分高速に動作するようです. したがって,ジョブクラスは必要とするコア数やメモリサイズで選んで良いでしょう.
使用ノード・コア数
この部分の指定はジョブクラスによって固定値があり,しかもOpenMPのみの並列化かMPIを使うか,あるいはそれらのハイブリッドかによっても記載方法が異なります. OpenSWPCを走らせる例を後述しますが,網羅的な記述は公式マニュアルをご覧ください.
ジョブの出力ファイル
コマンドライン端末から対話的に実行する場合とことなり,ジョブで実行されるプログラムには画面へのテキスト出力ができません.そのかわりに,標準出力と標準エラー出力(Fortranでは装置番号6番と0番,あるいはuse iso_fortran_envした状態で装置番号変数 output_unit と error_unit)を,それぞれファイルに出力します.つまり,1回のジョブ実行で2つのファイルが作成されます.そのファイル名は,標準出力が${jobname}.o${jobid},標準エラー出力が${jobname}.e${jobid}です.ただし${jobname}には -N オプションで名前を指定していればその名前が,そうでなければジョブスクリプトのファイル名が使われます.${jobid}はジョブID番号です.
たとえ標準出力や標準エラー出力がなくてもファイルが生成されるので,デバッグや試行錯誤をしていると出力ファイルが溜まっていきがちです.-j oeオプションを指定すると,標準エラー出力の内容も標準出力ファイルにまとめてくれます.この場合,作成されるファイルは${jobname}.o${jobid}だけです.
メール通知
オプション -m abe を指定しておくと,ジョブの異常終了時(a),開始時(b),終了時(e)にそれぞれ電子メールで通知してくれます.メールの宛先は-Mオプションで指定します.
ジョブ実行時のディレクトリ移動
上記のジョブスクリプト例には,
cd ${PBS_O_WORKDIR}という記載があります.この${PBS_O_WORKDIR}には,qsubコマンドによってジョブを投入したディレクトリ名が格納されています.通常はこのままで構いませんが,自分で絶対パスのディレクトリを直接記載してもよいでしょう.
Footnotes
公式マニュアルに記載がみつかりませんので,筆者の推測です.↩︎