逐次プログラムの実行

本節では,C言語でプログラムを作成し,スーパーコンピュータでコンパイル・ジョブ実行を行うユースケースについて説明します.
スーパーコンピュータへのログインについては,システムへの接続方法 をご覧ください.

本節では,サンプルプログラム (sample.c) を作成ならびにコンパイルする手順について説明します.

ここでは,emacsを用いてサンプルプログラムを作成します.emacsの他にシステムに標準インストールされているエディタとしては, vi(vim) などがあります.

下記のコマンドでemacsが起動し,空のファイル「sample.c」を開きます.

emacs sample.c

下記のプログラムを手入力するか,コピー&ペーストしてください.
ターミナルへのペーストはマウスの右クリックやホイールクリックに割り当てられていることが多いです.

#include <stdio.h>
#include <unistd.h>

int main(void){
   printf("hello\n\n");
   sleep(120);
   return 0;
}

入力が完了したら,「Ctrl+x Ctrl+s」を押し,保存します. 「Ctrl+x」は,「キーボードのCtrlキーを押しながらxキーを押す」という意味です.
保存が完了した場合は,画面の下部に下記のようなメッセージが表示されます.

Wrote /home/b/b59999/sample.c

emacsを終了するには,「Ctrl+x Ctrl+c」を押します.
作成したファイルの確認は,ターミナルでls -lと打ち,下記のようにsample.cといったファイル名が表示されていれば問題ありません.

-rw-r----- 1 b59999 b59999           75 Dec 18 10:42 sample.c

下記のコマンドを入力してコンパイルします. コンパイルのコマンド名はシステムによって異なります.

システム コマンド
A cc sample.c
BまたはC icc sample.c

コンパイルされたプログラムは「a.out」という名前になります.
ターミナルでls -lと打ち,下記のようにa.outというファイル名が表示されていれば問題ありません.

-rw-r----- 1 b59999 b59999        9817 Dec 18 10:42 a.out

次に,前節で作成したプログラムを実行する手順について説明します.
ログインノードは多くのユーザで共有して使用する計算機ですので, プログラムは 下記の方法を用いて 計算ノードで実行する必要 があります.

プログラムを計算ノードに投入(実行依頼)する単位をジョブと呼びます. ジョブ投入の方法として,会話型処理とバッチ処理の2種類の方法がありますが, ここではバッチ処理を使ったジョブ投入の方法を紹介します.

バッチ処理を用いて,ジョブ投入をする場合はジョブスクリプトと呼ばれるスクリプトで 実行処理について記述する必要があります.
ここでは,ジョブスクリプトの作成,実行,実行確認までを説明します.

ジョブスクリプトは,原則的にシェルスクリプトと同じ形式です.ジョブスクリプトはPBSのジョブ投入オプションを記述したオプション領域と, 実行するプログラムを記述したユーザプログラム領域(シェルスクリプト部)から構成されます.
ユーザプログラム領域にはプログラム本体の実行処理に加えて,前後で実行する処理をシェルスクリプトと同じ形式で記載頂くことが可能となっています.

下記のコマンドでemacsを起動し,sample.shファイルを開きます.

emacs sample.sh

emacsが起動したら,下記のジョブスクリプトを手入力するか,コピー&ペーストしてください.
※ジョブスクリプトは,システムAとシステムB/Cによってユーザプログラム領域の書き方が異なります.ジョブ投入するシステムのものをご利用ください.

#!/bin/bash
#============ PBS Options ============
#QSUB -q gr19999b
#QSUB -ug gr19999
#QSUB -A p=1:c=1:t=1:m=1355M
#QSUB -W 10:00
#============ Shell Script ============
aprun -n $QSUB_PROCS -d $QSUB_THREADS -N $QSUB_PPN ./a.out

※注) システムAでバッチ処理を行う場合は, aprunコマンドが必須 となります.詳細は こちら をご覧ください.

#!/bin/bash
#============ PBS Options ============
#QSUB -q gr19999b
#QSUB -ug gr19999
#QSUB -A p=1:c=1:t=1:m=3413M
#QSUB -W 10:00
#============ Shell Script ============
./a.out

次に,ご自身の利用可能なシステムやキューに応じて,ジョブスクリプトを修正します.

#QSUB -qに続けてキューを指定します.キュー名は,サービスコースごとに以下の値となります.

サービスコース キュー名
エントリ eb
パーソナル pa (システムA)
pb (システムB)
pc (システムC)
グループ,機関・部局定額,HPCI,JHPCN 申込者に通知されたキュー名

グループコースキュー(gr19999b)を指定する場合は下記の通り記載します.

#QSUB -q gr19999b

これはグループコースまたは機関・部局定額,HPCI,JHPCNの利用者に必要です.エントリ,パーソナルの方はこの行ごと削除して頂いて構いません.

#QSUB -ugに続けてグループ名を指定します.グループコースはグループ名(キュー名から最後の英字を取ったもの)と同じです.機関定額,HPCI,JHPCNの方は,キュー名と異なる場合がありますので,指定されたグループ名に従ってください.

システムBのグループコースキューgr19999bに投入する場合は下記の通り記載します.

#QSUB -ug gr19999

#QSUB -Aに続けてジョブ割当リソース量を指定することができます. 指定することが可能な引数は以下の4つで,指定しない場合はデフォルト値が自動的にセットされます.

-Aの引数 説明 デフォルト値
p=procs ジョブ実行時の割当プロセス数 1
t=threads ジョブ実行時のプロセスあたりの割当スレッド数.環境変数 OMP_NUM_THREADS を自動で設定 1
c=cores ジョブ実行時のプロセスあたりの割当CPUコア数.基本的に t と同じ値を設定 1
m=memory ジョブ実行時のプロセスあたりの割当メモリ量(単位:M,G,T) 1355M(システムA), 3413M(システムB), 42666M(システムC)

今回は,逐次プログラム(非並列プログラム)を題材として取り扱っていますので,1プロセスに 1コア,1スレッド,メモリ1355Mを 割り当てて実行する場合の例を以下に記載します.並列計算をする場合は MPIプログラムの実行 をご覧ください.

#QSUB -A p=1:c=1:t=1:m=1355M

#QSUB -Wに続けてジョブ実行時間の上限値を指定することができます. ジョブ実行時間上限値のデフォルト値ならびに,指定できる最大値は以下のとおりです

サービスコース デフォルト値 上限値
エントリ 1:00 (1時間) 1:00 (1時間)
パーソナル 1:00 (1時間) 168:00 (168時間)
グループ,機関・部局定額,HPCI,JHPCN 1:00 (1時間) 336:00 (336時間)

ジョブ実行時間の上限値を 10時間とする場合は下記の通り記載します.

#QSUB -W 10:00

システムAでは,ジョブスクリプトが実行されるノード(ゲートウェイノード)とプログラムが実行されるノード(計算ノード)が分かれています. プログラムを計算ノード上で動作させるためには,逐次プログラム,MPIプログラムに関わらず,ジョブスクリプトのプログラムを実行する箇所に 必ず aprun コマンドを使用する必要があります.

aprunコマンドの引数のうち,代表的なものを以下に示します.オプションの詳細については,コマンドのマニュアル(man aprun)を参照してください.

オプション 機能 デフォルト値 備考
-n procs 起動するプロセス数を指定する 1 $QSUB_PROCS を指定することで,#QSUB -A オプションの p に指定した数値が挿入される
-d cores プロセスあたり確保するCPUコア数を指定する 1 $QSUB_THREADS を指定することで,#QSUB -A オプションの t に指定した数値が挿入される
-N procs_per_node ノードあたりのプロセス数を指定する 1 $QSUB_PPN を指定することで,自動的に最適な1ノードあたりのプロセス数が挿入される

以下のコマンドでジョブを投入します.

qsub sample.sh

上記コマンドが正常に受け付けられた場合は 下記のようにJOBIDが表示されます.

$ qsub sample.sh
1255581.jb

qsコマンドで,ジョブの状態が確認できます.

出力結果の一例:

 QUEUE     USER     JOBID      STATUS  PROC THRD CORE    MEM ELAPSE( limit)
 gr19999b  b59999   1255581    RUN        1    1    1    1355M  00:00( 10:00)

STATUSがRUNになっていれば,プログラムが計算ノードで実行されています.
ジョブが終了すると,プログラムの標準出力は,「B121811.o1255581」といった,拡張子が「o+数字」のファイルに出力されます.数字の部分は JOBID になっています.

lsコマンドで,標準出力ファイルを探し,開いてみましょう.ジョブが正常に実行されていれば,下記のように「hello」という出力と共に,ジョブサマリが出ているはずです.

[b59999@laurel3 b]$ ls
B121811.o1255581    B121811.e1255581

[b59999@laurel3 b]$ cat B121811.o1255581
hello

================================================================================

                Resource Usage on 2017-12-18 11:50:04.791317:

JobId: 1255581.jb
        Job_Name = B1255581
        queue = gr19999b
        Resource_List.Aoption = gr19999:p=1:t=1:c=1:m=1355:c_dash=1
        Resource_List.select = 1:ncpus=2:mpiprocs=1:mem=1355mb:jobfilter=long
        qtime = 2017-12-18 11:49:58
        stime = 2017-12-18 11:50:04
        resource_used.cpupercent = 0
        resource_used.cput = 00:00:00
        resources_used.mem = 0b
        resources_used.ncpus = 2
        resources_used.vmem = 0b
        resources_used.walltime = 00:00:02

================================================================================

なお,拡張子が「e+数字」のファイルは,標準エラー出力となります.

以上のチュートリアルでは,ホームディレクトリで単一プロセスでのサンプルプログラムの実行を行いました.

本格的な計算には, MPIやOpenMPによる複数プロセス・複数スレッドの並列実行が必要です.そのためには,ジョブスクリプトで今回取り上げなかった#QSUB -Aオプションが必要です.また,ジョブの標準実行時間は1時間ですので,長時間の計算を行うには#QSUB -Wオプションが必要です.
詳細は下記ページから,システムに応じた項目をご覧ください.

また,エントリコース以外の方は,ディスク領域としてホーム(容量100GB)以外に大容量ディスクがご利用いただけます. 詳細は下記ページをご覧ください.

コンパイラや計算ライブラリについても,複数種類の商用ツールを用意しております. 利用方法は下記ページをご覧ください.

ジョブスクリプトは実行種別に合わせたサンプルスクリプトを用意しています. 詳細は下記ページをご覧ください.

以上で,自作アプリケーションのコンパイル,実行 の説明は終了となります.


Copyright © Academic Center for Computing and Media Studies, Kyoto University, All Rights Reserved.