MPIプログラムの実行

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

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

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

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

emacs sample_mpi.c

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

#include <stdio.h>
#include "mpi.h"

int main(int argc, char* argv[]) {
    int process_id;

    MPI_Init(&argc, &argv);
    MPI_Comm_rank(MPI_COMM_WORLD, &process_id);

    printf("Hello world! Process ID is %2d \n", process_id);

    MPI_Finalize();
}

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

Wrote /home/b/b59999/sample_mpi.c

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

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

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

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

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

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

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

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

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

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

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

emacs sample_mpi.sh

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

#!/bin/bash
#============ PBS Options ============
#QSUB -q gr19999b
#QSUB -ug gr19999
#QSUB -A p=2: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=2:c=1:t=1:m=3413M
#QSUB -W 10:00
#============ Shell Script ============
mpiexec.hydra ./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)

MPIプログラムを実行する場合には、pのパラメーターにより起動するプロセス数を定義してください.
以下の例では,2プロセスを起動し,プロセス当たり1コア,1スレッド,メモリ1355Mを割り当てる設定です. もし,MPIとOpenMPを組み合わせたハイブリッド並列を実行する場合は,t及びcのパラメータを実行したい並列数に合わせて増やしてください.

#QSUB -A p=2: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ノードあたりのプロセス数が挿入される

システムB,C でMPIプログラムを実行するには, mpiexec.hydra を使用してください(Intel MPIの場合).

mpiexec.hydra は PBSと連携するため,-A オプションの p で指定した値のプロセスを自動で起動します.

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

qsub sample_mpi.sh

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

[b59999@laurel3 b]$ qsub sample_mpi.sh
2703360.jb

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

出力結果の一例:

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

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

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

[b59999@laurel3 b]$ ls
B012817.o2703360    B012817.e2703360

[b59999@laurel3 b]$ cat B012817.o2703360
Hello world! Process ID is  0
Hello world! Process ID is  1
================================================================================

        Resource Usage on 2019-01-28 17:41:31.843331:

JobId: 2703360.jb
    Job_Name = B012817
    queue = gr10001b
    Resource_List.Aoption = gr10001:p=2:t=1:c=1:m=1355:c_dash=5
    Resource_List.select = 1:ncpus=20:mpiprocs=2:mem=2710mb:ompthreads=1:jobfilter=long
    qtime = 2019-01-28 17:40:57
    stime = 2019-01-28 17:41:22
    resources_used.walltime = 00:00:12
    resources_used.cput = 00:00:00
    resources_used.cpupercent = 0
    resources_used.ncpus = 20
    resources_used.mem = 0bkb

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

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

以上のチュートリアルでは,MPI対応の並列プログラムを作成し実行しました.
この他にも,プログラムを実行するにあたって設定可能なオプションや実行方法を紹介しております.必要に応じて下記ページからシステムに応じた項目をご覧ください.

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

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

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


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