2014年3月12日
大島 聡史 (東京大学情報基盤センター)
ohshima@cc.u-tokyo.ac.jp

第34回お試しアカウント付き並列プログラミング講習会（2014/03/12）

1 ファイルシステム
 バッチジョブの操作(上級編)◦ ステージング◦ ジョブの詳細な情報の把握◦ コマンドラインオプションの利用◦ ステップジョブ

 makeの利用
 makeの応用◦ makeを使った並列処理◦ GXP/GXP makeの利用

第34回お試しアカウント付き並列プログラミング講習会（2014/03/12）

2

 Oakleaf-FXにログインして効率的に作業を行えるようになることを目指し、ファイルシステムやジョブの操作について学ぶ 大規模なプログラムを作成する際に必須となる、分割

コンパイルの方法について学ぶ makeを使用した並列処理の方法について学ぶ

第34回お試しアカウント付き並列プログラミング講習会（2014/03/12）

3

第34回お試しアカウント付き並列プログラミング講習会（2014/03/12）

4 Oakleaf-FXで利用可能なファイルシステムは以下のとおりである
PATH

種類

共有/非共有/home/ログイン名

FEFS

共有

備考

共有ファイルシステム/group[1-3]/グループ名/ログイン名(*)

FEFS

共有

/mppx[bc]/ログイン名(*)

FEFS

共有

外部ファイルシステム（一時利用）

/work

FEFS

-

ローカルファイルシステム（ステージング用）

/tmp

NFS

非共有

(*) 負荷分散のため、グループ、ユーザ毎に/group[1-3], /mppx[bc] のいずれかを使用
第34回お試しアカウント付き並列プログラミング講習会（2014/03/12）

5 他のノードから直接アクセスできない記憶域◦ Oakleaf-FXでは、計算ノードとインタラクティブノードにはローカルディスクはない

ディスクと直接接続

第34回お試しアカウント付き並列プログラミング講習会（2014/03/12）

6

 ネットワーク経由で複数クライアントからアクセス可能 動的な負荷分散機能がない(サーバは1台)
 Oakleaf-FXにおける設定◦ OS起動等のために、1ラック(96ノード)ごとに1台使用◦ /tmp (NFS領域) には書き込みを行わないことを推奨

ネットワーク経由で接続

第34回お試しアカウント付き並列プログラミング講習会（2014/03/12）

NFSサーバ7◦ 複数のファイルサーバにデータおよびメタデータを分散配置
 1ファイルのデータを複数台のサーバに分散可能
 フェイルオーバーにより、サーバ故障に対応可能
メタデータ
サーバ

オブジェクト格
納サーバ

オブジェクト格
納サーバ
第34回お試しアカウント付き並列プログラミング講習会（2014/03/12）

8 複数のファイルサーバにデータを分散可能◦ 多くのクライアントからアクセスする場合に効率がよい
 構成がNFSより複雑◦ NFSに比べると1クライアントからのアクセス性能は低い場合がある◦ ただし、1ファイルのデータを複数のサーバに分散させれば、1クライアントからのアクセス性能を上げることができる(lfssetstripeなど)

第34回お試しアカウント付き並列プログラミング講習会（2014/03/12）

9 FEFS(Fujitsu Exabyte File System)◦ Lustre ファイルシステムをベースに富士通が開発
 Lustre との高い互換性◦ 数万規模のクライアントによるファイル利用を想定
 最大ファイルサイズ、最大ファイル数等の拡張
 Lustre◦ 大規模ファイル入出力、メタデータ操作の両方で高性能なファイルシステム◦ データの分散方法をファイルごとに指定可能(後述)

第34回お試しアカウント付き並列プログラミング講習会（2014/03/12）

10 共有ファイルシステムは、個人、またはグループに対して利用可能容量の制限(quota)がある
 残り容量の確認コマンド (show_quota)$ show_quota
Disk quotas for user t00004
Directory
used(MB)/home/t00004
194,229/group/gc26/t00004
0/group/gv52/t00004
101,520/group/gv56/t00004
0/mppxb/t00004
202

limit(MB)204,800-

nfiles338,682
90,915
221,398
034,153

Disk quotas for group gc26 gv52 gv56
Directory
used(MB)/group/gc26
8,732,088/group/gv52
131,701/group/gv56
1,481,982

limit(MB)57,344,000
8,192,000
8,192,000

nfiles971,278
273,851
233,079

第34回お試しアカウント付き並列プログラミング講習会（2014/03/12）

11

 それぞれのファイルシステムでファイル展開コマンドを実行せよ◦ 実行時間にどのような差があるか？
 各ファイルシステムに割り当てられたquota値を確か

めよ

第34回お試しアカウント付き並列プログラミング講習会（2014/03/12）

12 /home/t00001/public に、この講習会で使用したプログラム、課題の解答などのファイルを置きました。
ご利用ください。

第34回お試しアカウント付き並列プログラミング講習会（2014/03/12）

13 ./create_tar.sh ファイル数◦ 指定された数のファイルが格納されたtar.gzファイルを作成
 ジョブスクリプト extract_test.sh（pjsubで実行する）◦ extract関数（extract ディレクトリ）
 指定したディレクトリにファイルを展開し、所要時間を表示
 PJM_O_LOGNAMEという環境変数に、ユーザ名が格納されている -I "test.tar.gz …"はステージングのための指定(後述) ファイルシステムのquotaを確認するには、

show_quotaコマンドを使用する

第34回お試しアカウント付き並列プログラミング講習会（2014/03/12）

14◦ 複数のOST (Object Storage Target: 仮想的なディスク) で構成◦ 各OSTは1つのRAIDグループに対応 共有: RAID6 (9D+2P) x 480、ローカル: RAID5 (4D+1P) x
600、外部: RAID6 (8D+2P) x 236◦ メタデータの格納先 (MDT: Metadata Target)はRAID1
メタデータ
サーバ

オブジェクト格
納サーバ

第34回お試しアカウント付き並列プログラミング講習会（2014/03/12）

15 データ配置の指定◦ ファイルのデータをひとつのOSTに配置するか、複数のOSTに分散して配置するかはユーザが指定できる◦ デフォルトではひとつのOSTに配置◦ lfs getstripe / lfs setstripeコマンドで参照・変更可能

ひとつのOSTに配置

OST1

OST2

OST3

第34回お試しアカウント付き並列プログラミング講習会（2014/03/12）

複数のOSTに配置

OST1

OST2

OST3

16

 lfs setstripe -s size -c count ファイル名◦ size 毎にcount 個のOSTに渡ってデータを分散配置する設定にした空のファイルを作成する(lustre_stripeディレクトリに、ここで使用したスクリプトがあります)$ dd if=/dev/zero of=/mppxc/t00004/4G.dat bs=1M count=4096
4096+0 records in
4096+0 records out
4294967296 bytes (4.3 GB) copied, 35.6352 s, 121 MB/s
OST数が1の場合の書き込み性能$ rm /mppxc/t00004/4G.dat$ lfs setstripe -s 1M -c 50 /mppxc/t00004/4G.dat
ストライプ設定の変更(50個のOSTにデータを分散)$ dd if=/dev/zero of=/mppxc/t00004/4G.dat bs=1M count=4096
4096+0 records in
4096+0 records out
4294967296 bytes (4.3 GB) copied, 17.6508 s, 243 MB/s
OST数が50の場合の書き込み性能
第34回お試しアカウント付き並列プログラミング講習会（2014/03/12）

17

1.

ステージング2.

ジョブの詳細な情報の把握

3.

コマンドラインオプションの利用

4.

ステップジョブ

第34回お試しアカウント付き並列プログラミング講習会（2014/03/12）

18

ジョブ投入ステージイン実行

ステージアウト 共有ファイルシステムとローカルファイルシステムの間で、ジョブの入力ファイル、出力ファイルを転送する手法
 ジョブが利用するファイルシステムをローカルファ
イルシステムにすることで、入出力の競合を減らすことが可能◦ 多くのI/O処理を行う大規模なプログラムにて大きな効果を発揮する ステージイン◦ 入力ファイルなどをローカルファイルシステムに転送 ステージアウト終了◦ 出力結果などを共有ファイルシステムに転送

第34回お試しアカウント付き並列プログラミング講習会（2014/03/12）

19



ステージングを利用する場合、ジョブの実行時ディレクトリは投入時ディレクトリとは異なるディレクトリになる
ジョブ実行時ディレクトリ$PJM_O_WORKDIR$PJM_JOBDIR

非ステージングジョブ

A

A

A

ステージングジョブ(共有モデル)B

A

B

ステージングジョブ(非共有モデル)B/rankA

B

A: ジョブ投入時ディレクトリ
 B: /work/jobname.jobid 非ステージングジョブでは、/work/jobname.jobidというディレクトリは作成されない

第34回お試しアカウント付き並列プログラミング講習会（2014/03/12）

20

 共有モデル◦ ジョブ内の並列プロセスが同じファイルに対して入出力◦ ジョブ内で同一ファイルを共有

Process 0/

Process 1
work

job.sh.12345
Process n
第34回お試しアカウント付き並列プログラミング講習会（2014/03/12）

21

 非共有モデル/◦ 入出力の競合を避けるため、ジョブ内の並列プロセスが異なるディレクトリで実行

work

job.sh.12345

Process 0

 ジョブスクリプトに以下を追加することで、非共有モデルでの実行が可能#PJM--mpi use-rankdir
第34回お試しアカウント付き並列プログラミング講習会（2014/03/12）

0Process 1
1nProcess n
22

 #PJM-I“srcfile dstfile” ← 「“」「”」も必要◦ srcfileをdstfileに名前変更してステージイン
 #PJM-I"srcfile1 srcfile2 … dstdir/"◦ srcfile*をdstdirディレクトリに(存在しなければ作成して)ステー
ジイン◦ 最後の「/」も必須
 #PJM-D"srcdir dstdir"◦ srcdir以下のファイルをdstdirディレクトリに(存在しなければ作成して) ステージイン
 srcfile,srcdirを相対パス指定したときはジョブ投入ディ

レクトリが起点になる

第34回お試しアカウント付き並列プログラミング講習会（2014/03/12）

23

 #PJM-O"srcfile dstfile"◦ srcfileをdstfileに名前変更してステージアウト
 #PJM-O"srcfile1 srcfile2 … dstdir/"◦ srcfile*をdstdirディレクトリに(存在しなければ作成して)ステー
ジアウト◦ 最後の「/」も必須
 #PJM-E"srcdir dstdir"◦ srcdir以下のファイルをdstdirディレクトリに(存在しなければ作成して) ステージアウト
 dstfile,dstdirを相対パス指定したときはジョブ投入ディ

レクトリが起点になる

第34回お試しアカウント付き並列プログラミング講習会（2014/03/12）24

 以下の表記を使用して、ステージングのファイル名にジョブID等を含めることが可能 %j◦ ジョブID %n◦ ジョブ名 %r◦ ランク番号(非共有モデル利用時)◦ %03rの様な指定も可能(rank=1の時、001等)

第34回お試しアカウント付き並列プログラミング講習会（2014/03/12）

25

 pjstgchk◦ ステージング書式の文法チェック
 pjcat [-e | -o] -f◦ 標準出力・エラー出力の表示◦ -fはtail -fと同様の動作(継続して表示) pjlist [-a] [-l] [-R] JOBID [rank]◦ ジョブ実行時ディレクトリのファイルリストの表示 pjget [-f] [-p] [-r] JOBID [rank:] src dst◦ ジョブ実行時ディレクトリ上のファイルをコピー◦ -fは既存ファイルを削除してからコピー、-p,-rはcpコマンドと同様

第34回お試しアカウント付き並列プログラミング講習会（2014/03/12）

26

 MPIプログラムを実行し、ログをジョブIDがついたディレクトリに保存
#PJM--mpi use-rankdir#PJM-I "a.out input.dat ./"#PJM-O "stderr.%r logs_%j/"#PJM-O "stdout.%r logs_%j/"mpiexec --stdout-proc stdout ¥--stderr-proc stderr ./a.out input.dat

第34回お試しアカウント付き並列プログラミング講習会（2014/03/12）27

 MPIランクごとに異なるファイル名のデータをステージ

イン#PJM--mpi use-rankdir#PJM-I "program ./"#PJM-I "rank=0 master.dat ./"#PJM-I "rank=1- worker_%r.dat ./”mpiexec ./program …
 ランク番号は範囲で指定することができる• 書式：rank=N1-N2• N1省略時：0• N2省略時：MPIプロセス数-1
第34回お試しアカウント付き並列プログラミング講習会（2014/03/12）28

 pjstat-s ジョブID◦ ジョブの、より詳しい状態を確認するコマンド◦ ジョブIDを指定しない場合は実行前・実行中の、自分のすべてのジョブが対象
 pjstat-X ジョブID◦ 実行中のジョブのノード割り当て、ランク割り当てを確認する
コマンド pjstatには他にも様々なオプションがある。これら以外のオプションはman pjstatやオンラインドキュメントを参照のこと。
第34回お試しアカウント付き並列プログラミング講習会（2014/03/12）

29

Oakleaf-FX scheduled stop time: 2012/06/29(Fri) 09:00:00(Remain: 2days 17:26:40)
JOB IDJOB NAMEJOB TYPEJOB MODELRETRY NUM
SUB JOB NUM
USER
PROJECTRESOURCE UNITRESOURCE GROUP
APRIORITYPRIORITYSHELLCOMMENTLAST STATESTATEPRM DATE...
MAIL ADDRESSSTEP DEPENDENCY EXP
STEP EXITING WAIT MODE
FILE MASKSTANDARD OUT FILE
STANDARD ERR FILE
INFORMATION FILEPJSUB DIRECTORY
FILE SYSTEM NAMEAPPLICATION NAMEACCEPT DATEQUEUED DATEEXIT DATELAST HOLD USER

: 288534: STDIN: INTERACT: NM: 0: : t00004: gt00: oakleaf-fx: interactive_n1
: 127
: 63
: /bin/bash
:
: RNA
: RUN
: 2012/06/26 15:33:07: t00004@oakleaf-fx-6:: 2: 0022: : : : /home/t00004/private/:: :submitted on oakleaf-fx-6: 2012/06/26 15:33:05: 2012/06/26 15:33:06: :第34回お試しアカウント付き並列プログラミング講習会（2014/03/12）

HOLD NUM
HOLD TIMEJOB START DATEJOB END DATEJOB DELETE DATE (REQUIRE)JOB DELETE DATESTAGE IN START DATESTAGE IN END DATESTAGE IN SIZESTAGE OUT START DATESTAGE OUT END DATESTAGE OUT SIZENODE NUM (REQUIRE)CPU NUM (REQUIRE)
ELAPSE TIME (LIMIT)MEMORY SIZE (LIMIT)DISK SIZE (LIMIT)...
NODE NUM (ALLOC)MEMORY SIZE (ALLOC)
CPU NUM (ALLOC)
ELAPSE TIME (USE)NODE NUM (UNUSED)NODE NUM (USE)NODE ID (USE)TOFU COORDINATE (USE)MAX MEMORY SIZE (USE)CPU NUM (USE)USER CPU TIME (USE)SYSTEM CPU TIME (USE)CPU TIME (TOTAL)DISK SIZEI/O SIZE
FILE I/O SIZEEXEC INST NUM
EXEC SIMD NUM
TOKEN

: 0
: 00:00:00 (0): 2012/06/26 15:33:07<: : : : : : 0.0 MB (0): : : 0.0 MB (0): 1: 8: 02:00:00 (7200) <DEFAULT>: 28672.0 MiB (30064771072): 240000.0 MB (240000000000): 1:1x1x1: 28672.0 MiB (30064771072): 16: 00:00:12 (12): 0
: 1
: 0x030F0006: (8,4,0): 0.0 MiB (0): 0: 0 ms: 0 ms: 0 ms: 0.0 MB (0): 0.0 MB (0): 0.0 MB (0)
: 0
: 0
30
: -

 同一ノードには同一のNODEIDが表示される◦ 2ノード、8プロセス（1ノードあたり4プロセス）の場合の例$ pjstat -X

JOBID
288538RANK NODEID
0 0x010A0006
1 0x010A0006
2 0x010A0006
3 0x010A0006
4 0x02020006
5 0x02020006
6 0x02020006
7 0x02020006

第34回お試しアカウント付き並列プログラミング講習会（2014/03/12）31

 pjsub-L node=2,rscgrp=tutorial スクリ

プト名◦ スクリプト内の記述に関わらずtutorialリソースグループの2ノードを使用して実行◦ ジョブスクリプトに書いたものより、コマンドライン引数で指定したオプションのほうが優先される◦ 投入したスクリプトに記述された設定と実際のオプションが異なる場合がある◦ pjstatコマンドを使って確認すれば正しい情報が得られる

第34回お試しアカウント付き並列プログラミング講習会（2014/03/12）32

-L rscgrp=tutorial,node=1 コマンドを実行し、標準入力に env|sort; sleep 30を入力してCtrl-Dキーで終了

 pjsub

 pjstat-sで詳細情報を確認せよ
 ジョブ終了後、STDIN.o??????に出力された内容を確認せよ◦ どのような環境変数が設定されているか◦ env を mpiexec env に変更すると、どのような環境変数が設定されるか

第34回お試しアカウント付き並列プログラミング講習会（2014/03/12）33

 標準入力から与えたジョブスクリプトのジョブ名は

STDINになる (-Nオプションで変更可能)
 ジョブ内では、PJM_で始まる環境変数が設定される◦ PJM_O_で始まる環境変数には、pjsubした環境の情報が格納される
 更に、MPIプロセス内では、FLIB_またはOMPI_で始まる環境変数が設定される

第34回お試しアカウント付き並列プログラミング講習会（2014/03/12）

34

 実行されたジョブのノード数を NODES 環境変数に、

総プロセス数を PROCS 環境変数に設定するにはどうすればよいか?
◦ ヒント
 MPIプログラムを実行すれば上記の情報はわかる eval `echo x=1` を実行すると、シェル変数 x に 1 が設定される

第34回お試しアカウント付き並列プログラミング講習会（2014/03/12）35 環境変数の説明◦ FLIB_NUM_PROCESS_ON_NODE
 ノードあたりのMPIプロセス数(の最大値)◦ OMPI_UNIVERSE_SIZE 上記の値とノード数の積◦ OMPI_MCA_orte_ess_num_procs
 MPIプロセス数
 バッチジョブ内とインタラクティブジョブ内では、

mpiexec実行時のリダイレクトやバッククォートの動作が異なるので注意すること

第34回お試しアカウント付き並列プログラミング講習会（2014/03/12）36

 複数のジョブの間で実行の順序関係や依存関係を指定可能
 ステップジョブは複数サブジョブから構成され、各サブジョブは同時に実行されることはない
pjsub --step --sparam "sn=1" step1.sh[INFO]PJM 0000 pjsub Job 12345_1 submitted.
$ pjsub --step --sparam "jid=12345, sn=2, sd=ec!=0:after:1" step2.sh[INFO]PJM 0000 pjsub Job 12345_2 submitted.
$ pjsub --step --sparam "jid=12345, sn=3, sd=ec!=0:all" step3.sh[INFO]PJM 0000 pjsub Job 12345_3 submitted.
$ pjsub --step --sparam "jid=12345, sn=4, sd=ec==0:one:1" step4.sh[INFO]PJM 0000 pjsub Job 12345_4 submitted.

第34回お試しアカウント付き並列プログラミング講習会（2014/03/12）

37

 step2

step1◦ 依存するサブジョブ1の終了コードが0以外の場合(ec!=0)、自分と自分に依存するサブジョブすべてを(after)削除

step2
step3
step4

 step3◦ 依存するサブジョブ2(省略時は直前のサブジョブ)の終了コードが0以外の場合(ec!=0) 、依存関係にかかわらず後続のサブジョブすべてを削除(all) step4◦ 依存するサブジョブ1の終了コードが0の場合(ec==0)、自分を削除(one)pjstat –Eで、サブジョブを展開して表示可能
終了したジョブの場合は、pjstat -H –E

第34回お試しアカウント付き並列プログラミング講習会（2014/03/12）

38

第34回お試しアカウント付き並列プログラミング講習会（2014/03/12）

39

 プログラムの分割コンパイル等を支援するツール（ソフトウェア） 変更があったファイルのみを再コンパイルする、等の指定が可能
 大規模なプログラムを書くときに便利 本質的にはワークフロー言語の実行エンジン
 コンパイルに限らず、処理の依存関係を記述して、依存関係に従ってコマンドを実行できる
 Oakleaf-FXだけではなく、一般的なLinux環境の多くで利用可能
 この講習会では GNU make (version 3.81)を使用する

第34回お試しアカウント付き並列プログラミング講習会（2014/03/12）40

 hello.c#include <stdio.h>
int main(int argc, char** argv) {printf("Hello, world!¥n");return 0;}

 Makefile
hello: hello.c
gcc -o hello hello.c◦ スペースではなくタブを入れる 実行$ make hello
gcc -o hello hello.c

第34回お試しアカウント付き並列プログラミング講習会（2014/03/12）

もう一度makeを実行するとどうなるか？
$ make hello
make: `hello' is up to date.
※コマンド(gcc)は実行されない
41

 ルールは、ターゲット、依存するファイル、コマンドで記述される
ターゲット: 依存するファイル …
コマンド…
 makeの実行◦ make ターゲット◦ ターゲットを省略した場合は、Makefileの最初のターゲットが指定されたものとして実行される
 Makefileを1行目から順番に見ていって最初に出現したターゲッ
ト、という意味

第34回お試しアカウント付き並列プログラミング講習会（2014/03/12）42 以下のいずれかが満たされるとコマンドを実行◦ ターゲットが存在しない◦ (ターゲットのタイムスタンプ )< (依存するいずれかのファイルのタイムスタンプ)
 依存するファイル X が存在しない場合、make

Xを先

に実行
 コマンドを実行した後の終了ステータスが 0 以外の場合は続きの処理を実行しない

第34回お試しアカウント付き並列プログラミング講習会（2014/03/12）

43

 hello.c#include <stdio.h>void hello(void) {printf("Hello, world!¥n");} main.cvoid hello(void);
int main(int argc, char** argv) {hello();
return 0;}
 Makefile
hello: hello.o main.ogcc -o hello hello.o main.o
hello.o: hello.c
gcc -c hello.c
main.o: main.c
gcc -c main.c
第34回お試しアカウント付き並列プログラミング講習会（2014/03/12）

 実行$ makegcc -c hello.c
gcc -c main.c
gcc -o hello hello.o main.o hello.cを書き換え
例: world! を world!! に書き換え makeを再実行$ makegcc -c hello.c
gcc -o hello hello.o main.o44 2回目のmakeで起きていたこと◦ main.oのコンパイルは、main.cに変更がなかったため行われなかった
 Makefileに依存関係を適切に記述することで、変更があった部分だけを再コンパイルすることができる

第34回お試しアカウント付き並列プログラミング講習会（2014/03/12）

45

module1.o: module1.c common.hgcc -o module1.o module1.c -cmodule2.o: module2.c common.hgcc -o module2.o module2.c -cmodule3.o: module3.c common.hgcc -o module3.o module3.c -ca.out: module1.o module2.o module3.o
gcc -o a.out module1.o module2.o module3.o

module1.o以下の場合に何が起きるか考えよ・module1.cが変更された場合
・module2.oが削除された場合

module2.oa.out

common.hmodule1.c
module2.c
module3.o
module3.c
第34回お試しアカウント付き並列プログラミング講習会（2014/03/12）46

 Makefileの指定$ make -f test.mk 長い行
hello: hello.o main.ogcc -g -Wall -O3 ¥-o hello hello.o main.o PHONYターゲット.PHONY: clean
clean:(cleanというファイルがあっても実行する)
rm –f hello hello.o main.o ディレクトリを移動してmake$ make –C hello2 target(cd hello2; make targetと同様
実行後は元のディレクトリに戻る)
第34回お試しアカウント付き並列プログラミング講習会（2014/03/12）47

 コマンドの前のタブを、スペースにした場合、どのようなエラーが出力されるかX があるときとない時で、make X の動作に違いがあることを確認せよ

 .PHONY:

第34回お試しアカウント付き並列プログラミング講習会（2014/03/12）48

 誤ってタブを、スペースにした場合、“missing

separator” というメッセージが表示される◦ 環境設定などにより異なる場合もある◦ より親切な警告メッセージが表示される場合もある

第34回お試しアカウント付き並列プログラミング講習会（2014/03/12）49

 変数、関数の使用・特別なルールの書き方 Makefileのより簡潔な記述
 より柔軟な出力やエラー制御

第34回お試しアカウント付き並列プログラミング講習会（2014/03/12）50 代入方法OBJECTS=main.o hello.o 参照方法
hello: $(OBJECTS)${OBJECTS}でもよい$OBJECTSとすると、$(O)BJECTSと同じことになる 変数代入時における変数の参照（展開）CFLAGS=$(INCLUDES) -O -g
INCLUDES=-Idir1 -Idir2
CFLAGSは -Idir1 -Idir2 -O -gに展開される

第34回お試しアカウント付き並列プログラミング講習会（2014/03/12）

51

 実行しようとするコマンドを表示しない

test1:@echo Test message
 コマンド終了時ステータスを無視する（実行結果に問題があっても次のコマンドを実行する）
test2:-rm file1 file2 file3

第34回お試しアカウント付き並列プログラミング講習会（2014/03/12）52

 コマンドの条件分岐

hello: $(OBJECTS)
ifeq ($(CC),gcc)$(CC) -o hello $(OBJECTS) $(LIBS_FOR_GCC)
else$(CC) -o hello $(OBJECTS) $(LIBS_FOR_OTHERCC)
endif 変数代入の条件分岐

ifeq ($(CC),gcc)
LIBS=$(LIBS_FOR_GCC)
else
LIBS=$(LIBS_FOR_OTHERCC)
endif※変数代入には行頭のタブは不要 利用可能なディレクティブ◦ ifeq, ifneq, ifdef, ifndef

第34回お試しアカウント付き並列プログラミング講習会（2014/03/12）53

 変数と似た参照方法で利用可能

VALUE=$(subst xx,yy,aaxxbb)

VALUEにaayybbが代入される

CONTENTS=$(shell cat data.txt) CONTENTSにはdata.txtの中身が代入される
SECOND=$(word 2, This is a pen) SECOND=isと同じ

CDR=$(wordlist 2,$(words $(LIST)), $(LIST))CDRには$LISTの2番目以降の単語のリストが代入される
 他の関数の例◦ dir, notdir: シェルのdirname, basenameに似た動作◦ suffix, basename: 拡張子とそれ以外の部分に分ける
 シェルのbasenameとは違う◦ wildcard: ワイルドカードを展開

第34回お試しアカウント付き並列プログラミング講習会（2014/03/12）

54

 ターゲット名や依存ファイル名などに展開される特殊な変数がある$@$<$?
$+

ターゲット名最初の依存ファイルターゲットより新しい依存ファイル
すべての依存ファイル

hello: hello.o main.ogcc -o hello ¥hello.o main.o
hello.o: hello.c
gcc -c hello.c
main.o: main.c
gcc -c main.c
第34回お試しアカウント付き並列プログラミング講習会（2014/03/12）

CC=gccOBJECTS=hello.o main.o
hello: $(OBJECTS)$(CC) -o $@ $+hello.o: hello.c$(CC) -c $<main.o: main.c$(CC) -c $<55

 指定したパターンにマッチしたらコマンドを実行する%.o : %.c$(CC) -c $(CFLAGS) $(CPPFLAGS) $< -o $@◦ ***.o は ***.c に依存する
hello: hello.o main.ogcc -o hello hello.o main.o
hello.o: hello.c
gcc -c hello.c
main.o: main.c
gcc -c main.c

第34回お試しアカウント付き並列プログラミング講習会（2014/03/12）

CC=gccOBJECTS=hello.o main.o
hello: $(OBJECTS)$(CC) -o $@ $+%.o: %.c$(CC) -c $<56

DATE1 = $(shell date)
DATE2 := $(shell date)
DATE3 = `date`
 DATE1◦ 参照されるたびにdateが実行される（毎回再評価する）◦ 実行されるタイミングは最初(アクションが実行される前) DATE2◦ (参照されなくても)1度だけdateが実行される（右辺が変わっていなければ再評価しない）◦ 実行されるタイミングは最初(アクションが実行される前) DATE3◦ 最初は`date`という文字列が展開されるだけ◦ dateが実行されるのは各アクションが実行されるとき
第34回お試しアカウント付き並列プログラミング講習会（2014/03/12）57

 以下のルールDATE1をDATE2,DATE3に変更して実行せよ。2つechoの出力に違いはあるか？
test:echo $(DATE1)
sleep 1echo $(DATE1)
 DATE1,DATE2は、一見すると出力が同じであるが、どうすれば動作の違いを説明できるか？
 DATE4 := `date`◦ はどれと同じ動作になるか

第34回お試しアカウント付き並列プログラミング講習会（2014/03/12）58

 dateコマンドだけでは明確な違いがわかりにくいため、

以下のようにして情報を取得◦ より細かい単位で表示 (+%N でナノ秒単位の表示)◦ date実行時にログを出力する◦ 実行開始時刻を付加する、時刻表示前にsleepする
 lab5/2◦ date1, date2: 「最初」に時刻を変数に代入している、実行す
るコマンドを表示する時点で展開されている◦ date3, date4: 実行時に代入◦ date2: 二度目の実行時に再度実行「しない」◦ date3 = date4

第34回お試しアカウント付き並列プログラミング講習会（2014/03/12）59

 wildcard関数を使用して以下の処理を行うMakefile

を記述せよ◦ 入力データの中から、2009年8月と9月のデータだけを処理する
 入出力データの仕様◦ 入力ファイル名に日付が含まれている(YYYYMMDD.in)◦ 出力データは拡張子を.inから.outに変え、内容をコピーする

第34回お試しアカウント付き並列プログラミング講習会（2014/03/12）60 test:*.outから、%.out: %.inというルールが適用される
 *.out: *.in のアクションとして、cp *.in が実行される◦ sh(bash)の場合、*.inは存在する複数のファイルに展開され、*.outは存在しないため、展開はされず、*.outのままとなる◦ 結果として、複数のファイルを ‘*.out’というディレクトリにコピーするコマンドとなり、失敗する
 Wildcard関数を使用した例(test3)では、正しい

OUTFILELISTが生成されるため、入力ファイルの数と同数のcpコマンドが実行され、正しい結果が得られる

第34回お試しアカウント付き並列プログラミング講習会（2014/03/12）

61

第34回お試しアカウント付き並列プログラミング講習会（2014/03/12）62 makeは本質的にはワークフロー言語とその実行エンジン◦ コンパイル以外にもいろいろなことができる
 makeを使う上での便利な点◦ 実行するコマンドの依存関係を簡単に記述可能◦ 簡単な並列化
 依存関係の解析はmakeが自動的に行ってくれる◦ 耐故障性 途中で失敗しても、makeし直せば続きから実行してくれる

第34回お試しアカウント付き並列プログラミング講習会（2014/03/12）

63

 make-j による並列化◦ 同時実行可能なコマンドを見つけて並列に実行◦ 依存関係の解析は make が自動的に行ってくれる

all: a b
a: a.c$(CC) a.c -o ab: b.c$(CC) b.c -o b

第34回お試しアカウント付き並列プログラミング講習会（2014/03/12）

同時
実行
可能

64

GNU
make

-j で指定した数まで同時に実行する

第34回お試しアカウント付き並列プログラミング講習会（2014/03/12）

sh

コマンド

sh

コマンド

sh

コマンド

sh

コマンド

sh

コマンド

sh

コマンド

65

 make-j 最大並列度◦ 最大並列度で指定した数まで同時にコマンドを実行する◦ 最大並列度の最大値は 4096 (RHEL6における制約)
 それ以上を指定すると 1 を指定したものとみなされる◦ 省略した場合、可能な限り同時にコマンドを実行する(∞)
 make-j が正常に動作しない場合◦ Makefileの書き方の問題
 暗黙の依存関係
 同名の一時ファイル◦ リソース不足

 使用メモリやプロセス数が多すぎる 最大並列度を適切に設定する必要がある

第34回お試しアカウント付き並列プログラミング講習会（2014/03/12）

66

 逐次 make の実行順序に依存した Makefile の記述

をしてはいけない 左のターゲットから順番に処理されることに依存した
Makefileの例
all: 1.out 2.out
1.out:
sleep 1; echo Hello > 1.out
2.out: 1.out
cat 1.out > 2.out
 本来は依存関係を明示する必要がある(wrong_makefiles/wrong1.mak に、ここで使用した Makefile があります)
第34回お試しアカウント付き並列プログラミング講習会（2014/03/12）

67

 逐次 make 実行順序に依存する Makefile の別な例

 同名の一時ファイルを使用すると、並列実行時に競合する◦ 実行できたとしても正しい結果が得られない可能性がある
all: a b
a: a.c.gz
gzip -dc < a.c.gz > tmp.c$(CC) tmp.c -o a
tmp.cが競合

b: b.c.gz
gzip -dc < b.c.gz > tmp.c$(CC) tmp.c -o b

→異なる名前にすれば良い(wrong_makefiles/wrong2.mak に、ここで使用した Makefile があります)
第34回お試しアカウント付き並列プログラミング講習会（2014/03/12）

68 Makefile

FILE_IDS := $(shell seq 1 10)
FILES:= $(FILE_IDS:%=%.dat)

all: $(FILES)%.dat:
sleep 5touch $@◦ 変数や%を使わない場合どのようなMakefileになるか◦ make と make -j の実行時間を比較せよ

第34回お試しアカウント付き並列プログラミング講習会（2014/03/12）69 test.mkに特殊変数展開前、test2.mkに展開後のファ

イルを用意した time make -j 数値とすれば並列度を変更して計測できる
 様々な並列度で試してみていただきたい

第34回お試しアカウント付き並列プログラミング講習会（2014/03/12）70 Oakleaf-FX の場合、1 ノードで使える CPU コア数は16 まで
 多数のノードを使用すれば、よりたくさんの処理を行うことが可能 makeは複数ノードを使った処理に対応していない
 GXP make を使用すると複数ノードで並列make を実行可能◦ GXP make は並列シェル GXP と一緒に配布されているソフ
トウェア◦ Make の処理を、マスターワーカー型の並列処理として複数ノードで実行可能◦ 各ノードでファイルが共有されていることが前提
第34回お試しアカウント付き並列プログラミング講習会（2014/03/12）

71 並列分散環境を簡単に扱うための、並列版シェル◦ 多数のノードのインタラクティブな利用◦ 並列ワークフローの実行 (GXP make) 詳しい情報

http://www.logos.t.u-tokyo.ac.jp/gxp
http://sourceforge.net/projects/gxp
 ダウンロード方法$ cvs -d ¥:pserver:anonymous@gxp.cvs.sourceforge.net:/cvsroot/gxp ¥co gxp3※cvsで入手したものにパスを通せばすぐに使えます Oakleaf-FX 上のインストール先/home/t00001/public/gxp3
第34回お試しアカウント付き並列プログラミング講習会（2014/03/12）

72

 各計算ノードでデーモンプロセス(GXPD)を起動◦ ノード集合と、GXPD の起動方法を指定 (use) SSH, PBS, GridEngine 等が利用可能。拡張も可能◦ ノード集合を指定して、GXPD を起動 (explore) e(execute) コマンドでユーザプロセスを起動◦ 全部または一部のノードを指定可能
SH

use
exploreexecute

RSH

RSH
SSH

第34回お試しアカウント付き並列プログラミング講習会（2014/03/12）

TORQUE

RSH
RSH
73

#PJM-L node=4#PJM--mpi proc=4
NODES=ノード数

ノード数を取得
gxpc --root_target_name headgxpc rsh YYY XXX %target% %cmd%
gxpc use YYY head node
gxpc explore node[[1--$NODES]]

各ノードでGXPDを起動

gxpc cd `pwd`
gxpc e 'echo $GXPC_EXEC_IDX `hostname`'

gxpc quit

head

node1

コマンドの実行XXX は、各ノードでプロセスを起動するためのrsh-likeなコマンド
第34回お試しアカウント付き並列プログラミング講習会（2014/03/12）

node2 node374 Oakleaf-FX では、プロセス起動に rsh 等を使用できないため、MPI プロセス経由で起動する

gxpc --root_target_name headgxpc rsh mpi_redirect redirect_client %target% %cmd%
gxpc use mpi_redirect head node←redirect_serverをバッ
クグラウンドで起動
NODES=`redirect_client getsize`←ノード数を取得
mpiexec redirect_server &gxpc explore node[[1--$NODES]]
gxpc cd `pwd`
gxpc e 'echo $GXPC_EXEC_IDX `hostname`'
gxpc quit
redirect_client shutdown
wait
第34回お試しアカウント付き並列プログラミング講習会（2014/03/12）←redirect_serverを終了
75

 用意された、初期化からExploreするところまでを実行するスクリプト、終了処理を実行するスクリプトを使用すれば、より簡単に記述可能#PJM -L node=4. /home/t00001/public/fx10_gxp/gxp_init.sh

gxpc cd `pwd`
gxpc e 'echo $GXPC_EXEC_IDX `hostname`'. /home/t00001/public/fx10_gxp/gxp_finalize.sh

第34回お試しアカウント付き並列プログラミング講習会（2014/03/12）76

 makeで実行される各コマンドをGXP経由で実行◦ -jオプションと組み合わせて、ノードにまたがってmakeを並列実行することができる◦ 各ノードでファイルが共有されている必要がある
 gxpc make …

◦ … には、GNU makeに渡すことができるすべてのオプションを渡すことができる Oakleaf-FXでのGXP makeの実行◦ CPU数の自動取得に失敗するため、作業ディレクトリ上に以下の内容でgxp_js.confというファイルを作成
cpu 16

第34回お試しアカウント付き並列プログラミング講習会（2014/03/12）

77

GNU
make

GXP
make

mksh

gxpc

コマンド

mksh

gxpc

コマンド

gxpc

コマンド

mksh

gxpc

コマンド

mksh

gxpc

コマンド

mksh

gxpc

コマンド

xmake
スケ
ジューラ

mksh

直接コマンドを実行せずスケ
ジューラに登録するだけ

どのノードでコマンドを実行するか決める

第34回お試しアカウント付き並列プログラミング講習会（2014/03/12）

指定されたノードでコマンドを実行する
78

#PJM-L node=4#PJM--mpi proc=4. /home/t00001/public/fx10_gxp/gxp_init.sh

GXPDの起動gxpc cd `pwd`
gxpc make -j 64

並列makeの実行. /home/t00001/public/fx10_gxp/gxp_finalize.sh

GXPDの終了

第34回お試しアカウント付き並列プログラミング講習会（2014/03/12）

79 以下に述べる並列処理を実行せよ

 処理の内容◦ 複数の入力ファイルがある(in/inpXX-Y.dat)◦ 入力ファイルごとに、その内容に従って「処理」を行い、1つの出力ファイルを生成する(out/outXX-Y.dat)
 入力ファイルの内容により、処理時間は異なる◦ それぞれのタスクは独立で、並列実行可能 以下のそれぞれの場合を実際に試して、実行時間の違いの理由を考えよ◦ 処理するファイルをプロセスごとに固定する場合(MPI)◦ マスターワーカー型の負荷分散を行う場合(GXP make)第34回お試しアカウント付き並列プログラミング講習会（2014/03/12）

80 サンプルプログラムの説明◦ nolb.cがMPI版
 make nolbでコンパイル可能
 pjsub.shがジョブスクリプト◦ GXP make版のジョブスクリプトはpjsub_gxp.sh◦ make infiles で入力ファイルを作成◦ ./shuffle.sh で入力ファイルの内容をシャッフル

第34回お試しアカウント付き並列プログラミング講習会（2014/03/12）

81動的な負荷分散の効果で、短時間で処理が完了

300

経過時間(秒)250
200
no shuffle
shuffle

150
100
50
0
MPI
負荷分散 なし

第34回お試しアカウント付き並列プログラミング講習会（2014/03/12）

GXP Make
負荷分散 あり
82

(

0

50

100

150

)

200

250

300

0
10
20
30
40
50
60
第34回お試しアカウント付き並列プログラミング講習会（2014/03/12）

83

(

0

50

100

150

)

200

250

300

0
10
20
30
40
50
60
第34回お試しアカウント付き並列プログラミング講習会（2014/03/12）

84

(

0

50

100

150

)

200

250

300

0
10
20
30
40
50
60
第34回お試しアカウント付き並列プログラミング講習会（2014/03/12）85 容易にパラメタ並列処理を記述可能◦ GXPが提供する、パラメタ並列用のMakefileをincludeする 使用方法◦ parameters, target, output, cmd 変数を定義する◦ output, cmdは、:=ではなく=で値を定義する
 これをテンプレートとして何度も展開される◦ $(GXP_MAKE_PP)をinclude文で読み込む
 (GXPインストール先)/gxpmake/gxp_make_pp_inc.mk

第34回お試しアカウント付き並列プログラミング講習会（2014/03/12）

86 例1: (2 * 3 * 4=24個のタスクを並列実行)◦ 以下のMakefileを書いて、gxpc make -j baz を実行する
parameters:=a b c
a:=1 2b:=3 4 5
c:=6 7 8 9target:=baz
output=hoge.$(a).$(b).$(c)cmd=expr $(a) + $(b) + $(c) > hoge.$(a).$(b).$(c)include $(GXP_MAKE_PP) 例2: (課題8の処理)◦ 複数のパラメタ並列処理の組み合わせも可能

第34回お試しアカウント付き並列プログラミング講習会（2014/03/12）87 MapReduceモデル◦ Googleが提案する、大規模データの並列処理に特化したプ
ログラミングモデル◦ 1レコードに対する処理を書くと、処理系が大規模データに並列適用◦ 入力データは、レコードの集合◦ プログラムは、以下の2つの処理を定義
 Map: レコード→(key, value)の集合
 Reduce: (key, value)の集合→出力
 異なるレコードに対するmap処理と、異なるkeyに対するreduce
処理が並列実行可能

第34回お試しアカウント付き並列プログラミング講習会（2014/03/12）

88

 GXP make上に構築されたMapReduce処理系◦ パラメタ並列と同様に、GXP が提供する Makefile を
include するだけで利用可能◦ GXP が動く環境ならどこでも動く カスタマイズが容易◦ Makefile と、mapper, reducer などのいくつかの小さなスク
リプトを書くだけ

第34回お試しアカウント付き並列プログラミング講習会（2014/03/12）

89 include $(GXP_MAKE_MAPRED)の前に、以下の変数を設定する◦ input=入力ファイル名◦ output=出力ファイル名◦ mapper=mapperコマンド(ex_word_count_mapper)◦ reducer=reducerコマンド(ex_count_reducer)◦ n_mappers=map ワーカ数(3)◦ n_reducers=reduce ワーカ数(2)◦ int_dir=中間ファイル用ディレクトリ名
 省略時は$(output)_int_dir◦ keep_intermediates=yの時、中間ファイルを消さない◦ small_step=yの時、細かいステップでの実行

第34回お試しアカウント付き並列プログラミング講習会（2014/03/12）90 例(word count)◦ Mapper: レコード→(単語1, 1),(単語2, 1),…
◦ Reducer: それぞれのkeyについてvalueの和を出力◦ 以下のMakefileを書いて、gxpc make -j bar を実行する
input:=foo
output:=bar
mapper:=ex_word_count_mapper
reducer:=ex_count_reducer
n_mappers:=5
n_reducers:=3
include $(GXP_MAKE_MAPRED) 複数のMapReduceやパラメタ並列処理を組み合わせることも可能

第34回お試しアカウント付き並列プログラミング講習会（2014/03/12）

91 ファイルシステムやジョブ管理システム◦ Oakleaf-FXに固有の情報を活用することで、より効率的なシステムの利用が可能
 make, Makefile◦ make, Makefileを利用することで、変更箇所だけを再作成す
る分割コンパイルが可能
 並列ワークフロー処理◦ make -jで並列にmake処理を実行可能◦ makeを拡張したGXP makeを利用することで、大規模な並列処理を実行可能

第34回お試しアカウント付き並列プログラミング講習会（2014/03/12）

92