MPI による並列プログラミング演習 大塚 智宏 北村 聡 天野 英晴 天野研究室 PDARCH グループ 1 ターゲットマシン (SGI Altix3700) の構成 詳細は,http://www.sgi.co.jp/servers/altix/ を参照のこと. • • • • 2 プロセッサ : Itanium2 1.3GHz × 8 (全体では 64PU) メモリ : 48GB (全体では 384GB) OS : SGI Advanced Linux Environment 3.0 (kernel 2.4.21 ベース) MPI : SGI Message Passing Toolkit (MPT) MPI による並列プログラミング MPI (Message Passing Interface) は,主に分散メモリ型並列計算機上でメッセージパッシングモデルに基づく並列プログラミ ングを行うための標準的な API 仕様である.現在では,メッセージパッシングの事実上の標準として広く用いられている. 2.1 メッセージパッシング 分散メモリ型並列計算機 (クラスタも含む) では,各プロセスは独立なアドレス空間を持つため,共有変数による並列プログ ラミングは直接には実現できない.各プロセスは,メッセージを交換し合うことにより,協調して処理を進める. メッセージ通信には,Point-to-Point 通信と Collective 通信の 2 種類がある.Point-to-Point 通信では,一対のプロセス間で, 片方が送信者 (Sender),もう片方が受信者 (Receiver) として,それぞれ送信・受信のための関数を実行して通信を行う.一 方,Collective 通信では,2 つ以上のプロセスが同じ関数を実行して協調的な通信を行う.一般に Collective 通信は,複数の Point-to-Point 通信で代用可能である. また,MPI では,SPMD (Single Program Multiple Data) 型と呼ばれるスタイルに基づいてプログラムを記述する.これは,複 数のプロセスが全て同一のプログラムを実行し,プロセス番号によって分岐して処理を進めるもので,並列プログラミングで は最も一般的なプログラム記述法である.MPI 環境下でプログラムが実行されると,指定した数のプロセスが生成され,並列 計算機やクラスタ内の各プロセッサに分配される. 2.2 サンプルプログラム MPI では,最低限 6 つの関数を使えばたいていのプログラムを記述することができる.以下に,C 版のサンプルプログラム を示す. 1 ¶ ³ 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: µ • • • • • • • • • 2.3 #include <stdio.h> #include <mpi.h> #define MSIZE 64 int main(int argc, char **argv) { char msg[MSIZE]; int pid, nprocs, i; MPI_Status status; MPI_Init(&argc, &argv); MPI_Comm_rank(MPI_COMM_WORLD, &pid); MPI_Comm_size(MPI_COMM_WORLD, &nprocs); if (pid == 0) { for (i = 1; i < nprocs; i++) { MPI_Recv(msg, MSIZE, MPI_CHAR, i, 0, MPI_COMM_WORLD, &status); fputs(msg, stdout); } } else { sprintf(msg, "Hello, world! (from process #%d)\n", pid); MPI_Send(msg, MSIZE, MPI_CHAR, 0, 0, MPI_COMM_WORLD); } MPI_Finalize(); return 0; } ´ 2: ヘッダファイル mpi.h をインクルードする. 12: MPI の初期化. 13: 自プロセスのプロセス番号を求める. 14: 全プロセス数を求める. 16∼21: プロセス 0 の場合の処理. 17∼20: 自分以外の全プロセス (プロセス 1 ∼ nprocs−1) から順にメッセージを受信し,表示する. 22∼25: プロセス 0 以外の場合の処理. 24: プロセス 0 にメッセージを送信する. 27: MPI の終了. 基本的な 6 つの関数 MPI Init MPI の初期化を行う.argc, argv には,コマンドライン引数として受け取ったものをそのまま渡さなければならない. ¶ int MPI_Init( int char mpi_init(ierr) integer µ *argc, ***argv ierr ³ /* argc へのポインタ */ /* argv へのポインタ */ ); ! 返却コード ´ 2 MPI Finalize MPI の終了処理を行う. ¶ ³ int MPI_Finalize(); mpi_finalize(ierr) integer µ ierr ! 返却コード ´ MPI Comm rank コミュニケータ comm 中の自プロセスのランク (プロセス番号) を求める. ¶ int MPI_Comm_rank( MPI_Comm int comm, *rank mpi_comm_rank(comm, rank, ierr) integer comm, rank integer ierr µ ³ /* コミュニケータ */ /* プロセス ID (出力) */ ); ! 返却コード ´ MPI Comm size コミュニケータ comm 中のプロセス数を求める. ¶ int MPI_Comm_size( MPI_Comm int comm, *size mpi_comm_size(comm, size, ierr) integer comm, size integer ierr µ ³ /* コミュニケータ */ /* プロセス数 (出力) */ ); ! 返却コード ´ MPI Send プロセス dest にデータを送信する. ¶ int MPI_Send( void int MPI_Datatype int int MPI_Comm *buf, count, datatype, dest, tag, comm ³ /* /* /* /* /* /* 送信バッファ */ 送信データの要素数 */ 各要素のデータ型 */ 送信先プロセス ID */ タグ */ コミュニケータ */ ); mpi_send(buf, count, datatype, dest, tag, comm, ierr) <type> buf(*) integer count, datatype, dest, tag, comm integer ierr ! 返却コード µ MPI Recv プロセス source からデータを受信する. 3 ´ ¶ ³ int MPI_Recv( void int MPI_Datatype int int MPI_Comm MPI_Status *buf, count, datatype, source, tag, comm, *status /* /* /* /* /* /* /* 受信バッファ */ 受信データの要素数 */ 各要素のデータ型 */ 受信元プロセス ID */ タグ */ コミュニケータ */ ステータス (出力) */ ); mpi_recv(buf, count, datatype, source, tag, comm, status, ierr) <type> buf(*) integer count, datatype, source, tag, comm, status(mpi_status_size) integer ierr ! 返却コード µ ´ • コミュニケータ (C では MPI_Comm 型) は,プロセスのサブセットを「通信空間」として扱うためのもので,全プロセスで 構成される MPI_COMM_WORLD があらかじめ定義されている.とりあえず,引数 comm には MPI_COMM_WORLD を指定すれば よい. • タグは,メッセージを区別するためのもので,送信側と同じタグを指定しないとメッセージは受信できない. • MPI_Recv の引数 status には,MPI_Status 型変数へのポインタを渡す (C の場合).MPI_Status 型は,MPI_SOURCE, MPI_TAG, MPI_ERROR の 3 つのメンバを持つ構造体で,それぞれ送信プロセス ID,タグ,エラーコードが格納される. • MPI_Send および MPI_Recv では,パラメータ count と datatype でメッセージの大きさを指定する.すなわち,メッセー ジは count 個の値の列を含み,それぞれの MPI データ型が datatype である.MPI データ型には以下のものがある. MPI データ型 MPI_CHAR MPI_SHORT MPI_INT MPI_LONG MPI_UNSIGNED_CHAR MPI_UNSIGNED_SHORT MPI_UNSIGNED MPI_UNSIGNED_LONG MPI_FLOAT MPI_DOUBLE MPI_LONG_DOUBLE 2.4 対応する C の型 char short int long unsigned char unsigned short unsigned int unsigned long float double long double Collective 通信 Collective 通信では,2 つ以上のプロセスが同一の関数を実行して協調的な通信を行う.Collvective 通信関数の機能は基本的 にはすべて MPI_Send や MPI_Recv 等の Point-to-Point 通信関数の組み合わせで代用できる.しかし,効率的に実装されたもの を用いれば,Point-to-Point 通信を用いて手でチューニングするよりも楽にパフォーマンス向上が得られる場合があるし,プロ グラムが読みやすくなるというメリットがある. ここでは各関数の詳細には触れないが,興味のある方は後述の資料を参照して頂きたい. 2.5 その他の関数 MPI Barrier バリア同期を行う.すなわち,全プロセスがこの関数を呼ぶまでプロセスをブロックする. 4 ¶ ³ int MPI_Barrier( MPI_Comm comm mpi_barrier(comm, ierr) integer comm integer ierr µ /* コミュニケータ */ ); ! 返却コード ´ MPI Wtime ある時点からの経過時間 (掛け時計時間) を返す.単位は秒. ¶ ³ double MPI_Wtime(); double precision mpi_wtime() µ ´ 以下に,実行時間の測定例を示す. ¶ ³ double start, finish; ... MPI_Barrier(MPI_COMM_WORLD); start = MPI_Wtime(); /* 全プロセスがここにたどり着くまで待つ */ /* 測定開始 */ ... /* 何らかの処理 */ MPI_Barrier(MPI_COMM_WORLD); finish = MPI_Wtime(); if (pid == 0) printf("Elapsed time = %f[sec]\n", finish - start); µ /* 測定終了 */ ´ MPI にはこの他にも非常に多くの関数がある.中でも重要なのはノンブロッキング通信関数である.ノンブロッキング通信 において,送信や受信は,要求を発行する関数と,終了を待つ関数とに分かれている.要求の発行と終了待ちとの間に他の演 算を行うことで,通信と計算のオーバラップを行い,パフォーマンスを向上させることができる.詳しい説明は省略するが,興 味のある方は後で紹介する資料を参照されたい. 3 Altix3700 上での MPI プログラミング まず Altix3700 システムにログインする必要がある.altix.educ.cc.keio.ac.jp (131.113.108.84) というホストに ssh でログインする1 . ¶ ³ localhost% ssh -l ログイン名 altix.educ.cc.keio.ac.jp µ ´ さきほどのサンプルプログラムをコンパイルし,実行してみよう.コンパイルコマンドは icc で,MPI 関数をリンクするた めに -lmpi オプションが必要である2 . ¶ ³ altix% icc -o hello hello.c -lmpi µ ´ うまくコンパイルできたら,実行してみよう.実行するためには,mpirun というコマンドを用い,-np オプションによって 起動するプロセス数を指定する. 1 最初にログインする前に,ログイン名をシステムに登録しておく必要がある.4.4 2 Fortran77 の場合は ifort コマンドを使用する. 5 節を参照のこと. ¶ ³ altix% Hello, Hello, Hello, Hello, Hello, Hello, Hello, µ 4 mpirun world! world! world! world! world! world! world! -np 8 (from (from (from (from (from (from (from ./hello process process process process process process process #1) #2) #3) #4) #5) #6) #7) ´ 課題 4.1 問題 MPI を用いて,重力多体問題のシミュレーションを並列に行うプログラムを作成せよ. 多体問題とは,相互作用を及ぼし合う 3 体以上からなる系を扱う問題のことである.重力多体問題は,その中で相互作用が 重力 (万有引力) によるものである場合を扱い,星団や銀河のシミュレーションを行う場合の基本的なモデルとして用いられる. N 個の質点が与えられたとき,重力多体問題における運動方程式は以下の式で表される. X x j − xi d2 xi =− Gm j 2 dt |x j − xi |3 1≤ j≤N, j,i ここで, xi , mi はそれぞれ質点 i の位置,質量であり,G は万有引力定数である.しかし,この問題は,N ≥ 3 の場合一般に は解析的に解けないことが分かっているため,上式を数値積分することによりシミュレーションを行うのが普通である. シミュレーションは,一般に以下の手順で行われる. 1. N 個の質点の質量 mi ,初期位置 xi ,初期速度 vi (1 ≤ i ≤ N) が与えられる. 2. 質点 i が各質点から受ける重力の総和を計算することにより,加速度 ai を求める. 3. ai について時間積分を行い,質点 i の速度 vi および位置 xi を更新する. 4. 手順 2, 3 を全質点について行う. 5. 手順 2∼4 を時間ステップ数 T だけ繰り返す. 今回の問題では,以上の手順を行った後の各質点の位置 xi および速度 vi を求めてもらう.実際には,main ルーチンその他 のひな型についてはこちらの提供するものを使い,上記手順に従ってシミュレーションを行うルーチン solve_gmbp の中身を 並列化によって高速化するのが目標である. 4.1.1 問題の詳細 はじめ,各プロセスは初期データ取得ルーチンを呼ぶことによって N 個の質点の質量 mi ,初期位置 xi ,初期速度 vi の全体 を取得する (つまり,全プロセスが同じデータを取得する).m は倍精度浮動小数点型の配列であり, x および v は以下の構造 体 (C/C++の場合) を要素とする配列である.初期データは数種類用意されており,毎回ランダムにどれかが取得される. ¶ ³ typedef struct double double double } vector_t; µ { x; y; z; /* x 成分 */ /* y 成分 */ /* z 成分 */ ´ solve_gmbp ルーチンは,各プロセスにおいて,m, x,v を引数として呼び出され,シミュレーション結果である T ステッ プ後の位置,速度を再び x,v に格納して返す.この際,最終的な結果としてはプロセス 0 のもののみが採用されるため,他の プロセスでは特に結果を格納しなくてもよい. 6 solve_gmbp 内には,並列化されていないシミュレーションコードがすでに記述されているので,これを並列化することに よって高速化を行えばよい.ただし,このコードでは,数値積分法として 1 次 Symplectic 法 (詳細は略) を採用している.この 手の問題では,数値積分法やその他の部分の計算方法を変えた場合,結果が大きく変わってしまうことがあるので十分注意し て欲しい. この他,solve_gmbp 内では,外部変数 pid および nprocs にそれぞれ自身のプロセス ID と全プロセス数があらかじめ格納 されている. 最後に,結果検証ルーチンが呼び出され,あらかじめ保存されている結果と照合することにより判定を行う.その際,2 乗 ノルムによる誤差ノルム率 (Quality Index) を計算し,一定値以上となった場合には不正解と判定する. 実行時間は,solve_gmbp ルーチンを呼び出す直前からリターンした直後までの時間を計測する. 4.1.2 プログラム作成上のルール • • • • 実装言語は C, C++, Fortran77 のいずれかとする.これらを組み合わせて使用しても構わない. プロセス数は 8 までとする.用いるプロセス数は固定でも構わない. 並列化に用いるアルゴリズムは自由だが,並列化ツールとして用いるのは MPI のみとする. 提出されたプログラムをこちらで実行し,その実行時間と,得られた結果の精度を元に評価を行う (主要な基準は実行時 間の方である). • こちらで用意したファイルのうち,main.c,util.c,data.c の 3 つについては改変せずに用いること.サンプルプロ グラムと共に Web 上で配布する. • ここで紹介した以外の MPI 関数を用いても構わない. 4.1.3 ヘッダファイルについて ヘッダファイル gmbp.h 内には以下の定数等が定義されている. • • • • • • N : 質点の数. T : タイムステップ数. DT : 時間刻み幅 (タイムステップ間隔). G : 万有引力定数. USE_MPI : #define されていると,MPI を使用する. USE_FIXED_DATA : #define されていると,毎回同じ初期データが取得されるようになる.(デバッグ用) USE_MPI をコメントアウトすると,solve_gmbp ルーチン以外の場所にある MPI 関数が無効になる.自宅の PC 等,MPI が ない環境で試してみたい場合に利用するとよい. 4.2 提出について すべてのソースファイルをホームディレクトリ以下のどこかのディレクトリにまとめ, • • • • ディレクトリのパス,ソースファイルのリスト コンパイル・実行方法 (プロセス数等) プログラムの解説 (アルゴリズム,並列化方法等) 考察・感想 を書いたメールを 7 月 26 日 24:00 (7 月 27 日 0:00) までに [email protected] 宛に提出する.Subject は [MPI] ログ イン名 とすること.正しく提出されれば,自動的に返信メールが来るはずである.レポートを Word や PDF ファイルにして添 付しても構わない. なお,コピーしたと見なせるレポートがあった場合,それらのレポートは採点しない.誰かにコピーされたりしないように パミッションを設定するなど,自分のファイルは自分で保護すること. 質問があれば,[email protected] まで. 4.3 評価について プログラム自体の評価は,実行時間が主な基準となる.公平を期すため,提出されたソースファイルをこちらでコンパイル・ 実行した結果を公式の実行結果とする.その際,コンパイルオプションはすべて同じものを指定し,こちらで用意した数種類 のデータで実行してその平均値を採用する予定である. 7 4.4 アカウントについて 理工学 ITC の UNIX アカウント (ログイン名 y*****) を取得する必要がある.以前に取得したことがあっても,今年度の利用 申請を行っていない場合はあらためて申請が必要である.詳細は http://www.educ.cc.keio.ac.jp/guide/account2.html を参照のこと. また,Altix3700 システムにログインするには,ログイン名をシステムに登録してもらう必要があるため,最初にログインす る前にログイン名を [email protected] まで知らせること. また,Altix3700 の利用に際しては以下の点に注意して欲しい. • 簡単なソースファイル編集,コンパイル,課題に関連した計算処理以外の目的で利用しないこと. • プログラムを実行する前に top コマンド等を実行して,他のユーザのプロセスが実行されていないか確認すること.他 のユーザのジョブ実行と重なってしまうと,時間計測が正確に行えないだけでなく,場合によってはメモリとスワップ領 域を使い果たしてシステムが落ちる可能性があるので要注意. • プロセッサ,メモリ等のリソースを浪費しないこと.システム側の制限により,CPU 時間を 5 分以上使っているプロセ スは問答無用で kill されることになっている.この他,メモリを確保したまま長時間放置されているプロセス等を発見し たら,理工学 ITC に頼んで処理してもらうので知らせて欲しい. 例年,提出期限が近くなるとシステムが混雑し,思うように実行時間が計測できなくなったり,システムにトラブルが発生 することが多いため,早めに取り掛かることを強くお勧めする. なお,課題提出期限を過ぎた後しばらくすると登録が解除されて Altix3700 システムにはログインできなくなる. 4.5 連絡事項について 課題実施期間中の連絡事項は基本的にすべてメールで行うので,定期的にメールを確認すること.連絡用のメールアドレス を変更したい場合などは [email protected] まで. 5 Web 上の情報源 この授業のページ MPI の本家 MPI-J メーリングリスト SGI Altix 3000 シリーズ NEMO 天野研 PDARCH グループ (参考) 6 http://www.am.ics.keio.ac.jp/comparc/ http://www.mpi-forum.org/ http://phase.hpcc.jp/phase/mpi-j/ml/ http://www.sgi.com/products/remarketed/altix3000/ http://www.sgi.co.jp/servers/altix/ http://bima.astro.umd.edu/nemo/ http://www.am.ics.keio.ac.jp/proj/pdarch/ 改訂履歴 • 2007/6/29: バージョン 1.0. • 2007/6/29: mpirun の使い方を修正. • 2007/7/7: ソースファイル名変更に伴う修正.また,締切を 7/26 に延長. 8
© Copyright 2024 Paperzz