HPCセミナー

Size: px
Start display at page:

Download "HPCセミナー"

Transcription

1 並列プログラミング技法 (MPI 詳説 ) 高度情報科学技術研究機構神戸センター 宮内敦 0

2 本日の講義内容 MPIの基礎知識 MPI 関数各論 並列性能評価 具体的な問題への応用 1

3 2 MPI の基礎知識 1. MPI 規格 (MPI standard) 2. MPI ライブラリ

4 3 MPI とは プロセス並列を前提としたプロセス間のメッセージ交換に関する標準仕様 適用対象は分散記憶アーキテクチャー上の分散アドレス空間における SPMD モデル ネットワーク接続された異機種クラスター環境にも対応 先行した PVM(Parallel Virtual Machine) に不足していた機能を採り入れている 現在ではスレッド並列 直接メモリアクセス MPMD の機能も提供されている

5 MPI Standard MPI Forum が発行する規格書 全ての基準となる最も重要な文献 最新版は version3.1 現在 4.0 へ向け改訂作業中 = Magna Carta 1215 (The British Library, UK) *MPI Forum = 大学 研究機関 ベンダーから構成されるボランティアベースの協議会 4

6 5 バージョンの変遷と特徴 Point to Point Communication Datatypes Collective Communication Process Topology 1.0 May Jun Jul 97 Final version 1.3 May 08 Nonblocking Collectives Enhancement in One-Sided Comm. Enhancement in Process Topology Tool Information Interface 2.0 Jul Jun Sep Sep Jun 15 One-Sided Communications Parallel I/O Process Creation Distributed Graph Topology Minor Changes Error Corrections

7 MPI + X X = OpenMP, pthread, OpenSHMEM 従来のハイブリッド並列 X = None MPI-4.0 ではスレッド並列機能を強化 (ISC17) MPI だけでハイブリッド並列を閉じる方向? 4.0 では他に fault tolerance, resilience も重視通信の roll back 機能などを検討中 6

8 規格の内容 (MPI standard 3.1) 要素通信 (Point-to-Point Communication) データ型 (Datatypes) 集団通信 (Collective Communication) コミュニケータ (Groups, Contexts, Communicators and Cashing ) トポロジ (Process Topologies) 環境管理 (MPI Environmental Management) 情報オブジェクト (The Info Object) プロセス生成 (Process Creation and Management) 片側通信 (One-Sided Communications) 外部インターフェイス (External Interfaces) ファイル入出力 (I/O) ツール情報 (Tool Support) 7

9 注意すべき用語 バッファ (buffer) MPI では 3 種類のバッファが使われる送受信バッファ (send/recv buffer) はデータを格納した変数 配列システムバッファ (system buffer) はユーザに不可視 (opaque) だがデッドロックに関係する場合があり要注意添付バッファ (attached buffer) はユーザ自身で割当てる要素通信のバッファモードにおいてのみ使われる 復帰 (return) と完了 (completion) 復帰は後続する命令を実行可能な状態 ( 注 :return を値を返すという意味で用いる場合もある ) 完了は全ての手順が終了し通信前に戻った状態 閉塞 / 非閉塞 (blocking/nonblocking) 閉塞通信は送受信バッファが解放されるまで復帰しない非閉塞通信は即座に復帰し 後で完了したか確認する ( これを遅延同期 (defer synchronization) という ) 非同期通信 (asynchronous communication) 非閉塞通信とは違う概念 MPI では使わない * *The term asynchronous communication is not used in MPI, pp. 279, Using MPI, 2nd ed., MIT Press,

10 9 参考図書等 Using MPI Second Edition* W. Gropp, E. Lusk and A. Skjellum, MIT press, 1999 Using Advanced MPI W. Gropp, T. Hoefler, R. Thakur and E. Lusk, MIT press, 2014 Parallel Programming in C with MPI and OpenMP M. J. Quinn, McGraw-Hill, 2008 Parallel Programming with MPI P. Pacheco, Morgan Kaufmann, 1996 Tutorials** * Using MPI Third Edition ( **query words = MPI, parallel computing, high performance computing, message passing, etc.

11 10 MPI の基礎知識 1. MPI 規格 (MPI Standard) 2. MPI ライブラリ

12 特徴 MPI Standard に準拠して開発される プロセス並列モデル プロセス間通信でメッセージ交換 オープンソフトから商用ソフトまで多数 ライブラリにより性能の違いやバグ 代表的ライブラリ OpenMPI FT, LA, LAM joint team 現在の最大勢力 MPICH * Argonne National Lab. 根強い人気 MVAPICH Ohio State Univ. GPUに強み LAM/MPI Indiana Univ. かつてクラスタ向けに人気 CHIMP Edinburgh P.C.C. 初期のライブラリ Cray-MPI, IBM-MPI, Intel-MPI, Fujitsu-MPI etc. *MPICH is pronounced Em Pee Eye See Aych, not Emm Pitch., pp. 329, Using MPI, 2nd ed., MIT Press,

13 12 実装状況 (2016 年 6 月 ) Implementation Status(MPI3.1), as of June 2016 ( c.f. NBC = NonBlocking Collective, RMA = Remote Memory Access, F08 = Fortran2008

14 命名規則 (Naming conventions) 他 全ての名前は接頭辞 MPI_ で始まる 定数 型 状態 演算等は全て大文字 例 : MPI_COMM_WORLD, MPI_INT, MPI_SUCCESS, MPI_SUM, etc. 関数は最初の一文字のみ大文字 残りは全て小文字 例 : MPI_Comm_rank(), MPI_Init(), MPI_Send(), MPI_Bcast(), etc. 通信が成功した時の戻り値は MPI_SUCCESS if(mpi_xxx()) は期待通りに動作しない場合あり失敗したときの値も実装依存 13

15 14 MPI 関数各論 1. 集団通信 2. 要素通信 3. 片側通信 4. マルチスレッド 5. 派生データ型 6. ファイル I/O 7. コミュニケータ トポロジー 8. プロセス生成 9. その他

16 15 集団通信とは 注意点 コミュニケータ内の多プロセス間で一斉に行う通信 一般に要素通信を用いて実装される コミュニケータ内の全プロセスで関数呼出しが必要 実際に全てのプロセスが送受信するとは限らない 引数の値は基本的に全てのプロセスで同じ root, comm は全てのプロセスで同じ値を指定する 送受信バッファはプロセス毎に異なっても良い 関数名に v の付くものはプロセス毎にデータ数が異なる (bcast/scatter/scatterv/gather/gatherv/reduce で使用されないバッファには MPI_BOTTOM を指定できる )

17 16 集団通信関数一覧 One to All All to One Some to All All to All Blocking MPI_Bcast MPI_Scatter MPI_Scatterv MPI_Gather MPI_Gatherv MPI_Reduce MPI_Scan MPI_Exscan MPI_Allgather MPI_Allgatherv MPI_Alltoall MPI_Alltoallv MPI_Alltoallw MPI_Allreduce MPI_Reduce_scatter_block MPI_Reduce_scatter MPI_Barrier Nonblocking MPI_Ibcast MPI_Iscatter MPI_Iscatterv MPI_Igather MPI_Igatherv MPI_Ireduce MPI_Iscan MPI_Iexscan MPI_Iallgather MPI_Iallgatherv MPI_Ialltoall MPI_Ialltoallv MPI_Ialltoallw MPI_Iallreduce MPI_Ireduce_scatter_block MPI_Ireduce_scatter MPI_Ibarrier MPI_IN_PLACE Intercomm

18 MPI_Bcast Function prototype int MPI_Bcast( void* buffer, int count, MPI_Datatype datatype, int root, MPI_Comm comm ) Example (bcast.c) int buf[2]; MPI_Bcast(buf, 2, MPI_INT, 1, MPI_COMM_WORLD); root の持つデータを全プロセスにコピーする MPI_COMM_WORLD MPI_COMM_WORLD P0 buf P0 buf P1 buf Bcast P1 buf P2 buf P2 buf P3 buf P3 buf

19 MPI_Scatter Function prototype int MPI_Scatter( const void* sendbuf, int sendcount, MPI_Datatype sendtype, void* recvbuf, int recvcount, MPI_Datatype recvtype, int root, MPI_Comm comm ) Example (scatter.c) int sbuf[8], rbuf[2]; MPI_Scatter(sbuf, 2, MPI_INT, rbuf, 2, MPI_INT, 1, MPI_COMM_WORLD); root の持つデータを全プロセスに分配する MPI_COMM_WORLD MPI_COMM_WORLD P0 P1 sbuf sbuf Scatter P0 P1 rbuf rbuf P2 sbuf P2 rbuf 0 1 P3 sbuf P3 rbuf

20 19 MPI_Scatterv Function prototype int MPI_Scatterv( const void* sendbuf, const int sendcounts[], const int displs[], MPI_Datatype sendtype, void* recvbuf, int recvcount, MPI_Datatype recvtype, int root, MPI_Comm comm ) Example (scatterv.c) int sbuf[11], rbuf[3]; int scounts[4]={1,2,3,2}, displs[4]={0,2,5,9}; MPI_Scatterv(sbuf, scounts, displs, MPI_INT, rbuf, 3, MPI_INT, 1, MPI_COMM_WORLD); MPI_COMM_WORLD MPI_COMM_WORLD P0 P1 sbuf sbuf Scatterv P0 P1 rbuf rbuf P2 sbuf P2 rbuf P3 sbuf P3 rbuf 0 1 2

21 20 MPI_Scatter/MPI_Scatterv の注意点 MPI_Scatterv は MPI_Scatter をデータ長可変にしたもの 送信側パラメータ (sendbuf, sendcount, sendcounts[], displs[], sendtype) root の値のみ有効 それ以外の値は無視される 受信側パラメータ (recvbuf, recvcount, recvtype) recvcount は受信するデータ長以上であれば良い recvcount が受信するデータ長未満の場合はエラー Scatterv の recvcount は本来プロセス毎に異なる通常は sendcounts[rank] とする (3 でも正常動作 ) recvbuf の配列長は recvcount 以上必要 recvbuf の不要な配列要素は無視される recvtype と sendtype は異なっても良いが受信データ長が送信より少ないとエラー 分割されたデータの送信先はプロセス番号順

22 MPI_Gather Function prototype int MPI_Gather( const void* sendbuf, int sendcount, MPI_Datatype sendtype, void* recvbuf, int recvcount, MPI_Datatype recvtype, int root, MPI_Comm comm ) Example (gather.c) int sbuf[2], rbuf[8]; MPI_Gather(sbuf, 2, MPI_INT, rbuf, 2, MPI_INT, 1, MPI_COMM_WORLD); 全プロセスのデータを root に収集する MPI_COMM_WORLD MPI_COMM_WORLD P0 P1 sbuf sbuf Gather P0 P1 rbuf rbuf P2 sbuf 0 1 P2 rbuf P3 sbuf 0 1 P3 rbuf

23 22 MPI_Gatherv Function prototype int MPI_Gatherv( const void* sendbuf, int sendcount, MPI_Datatype sendtype, void* recvbuf, const int recvcounts[], const int displs[], MPI_Datatype recvtype, int root, MPI_Comm comm ) Example (gatherv.c) int sbuf[3], rbuf[11]; int rcounts[4]={1,2,3,2}, displs[4]={0,2,5,9}; MPI_Gatherv(sbuf, 3, MPI_INT, rbuf, rcounts, displs, MPI_INT, 1, MPI_COMM_WORLD); MPI_COMM_WORLD MPI_COMM_WORLD P0 P1 sbuf sbuf Gatherv P0 P1 rbuf rbuf P2 sbuf P2 rbuf P3 sbuf P3 rbuf

24 MPI_Gather/MPI_Gatherv の注意点 MPI_Gatherv は MPI_Gather をデータ長可変にしたもの 送信側パラメータ (sendbuf, sendcount, sendtype) Gatherv の sendcount はプロセス毎に異なる通常は recvcounts[rank] とする 受信側パラメータ (recvbuf, recvcount, recvcounts[], displs[], recvtype) root の値のみ有効 それ以外の値は無視される recvcount, recvcounts[] は受信するデータ長以上であれば良い recvcount, recvcounts[] が受信するデータ長未満の場合はエラー recvcounts[] の各要素の値は本来異なる gatherv.c の場合 recvcounts[]={1,2,3,2} でも {3,3,3,3} でも正常に動作 recvbuf の配列長は (recvcount or recvcounts[])*nproc 以上必要 recvbuf の不要な配列要素は無視される recvtype と sendtype は異なっても良いが受信データのバイト数が不足するとエラー 受信データの開始位置はプロセス番号順 23

25 MPI_Reduce Function prototype int MPI_Reduce( const void* sendbuf, void* recvbuf, int count, MPI_Datatype datatype, MPI_Op op, int root, MPI_Comm comm ) Example (reduce.c) int sbuf[2], rbuf[2]; MPI_Reduce(sbuf, rbuf, 2, MPI_INT, MPI_SUM, 1, MPI_COMM_WORLD); 全プロセスのデータを root に収集して総和 MPI_COMM_WORLD MPI_COMM_WORLD P0 sbuf 2 5 P0 rbuf P1 sbuf Reduce P1 rbuf = = P2 sbuf 6 3 P2 rbuf P3 sbuf 4 1 P3 rbuf

26 MPI_Scan Function prototype int MPI_Scan( const void* sendbuf, void* recvbuf, int count, MPI_Datatype datatype, MPI_Op op, MPI_Comm comm ) Example (scan.c) int sbuf[2], rbuf[2]; MPI_Scan(sbuf, rbuf, 2, MPI_INT, MPI_SUM, MPI_COMM_WORLD); 自分を含め自分より番号の若いプロセス上の値の総和 MPI_COMM_WORLD MPI_COMM_WORLD P0 P1 sbuf sbuf Scan P0 P1 rbuf rbuf =2 5=5 2=2+0 12=5+7 P2 sbuf P2 rbuf = =5+7+3 P3 sbuf P3 rbuf = =

27 MPI_Exscan Function prototype int MPI_Exscan( const void* sendbuf, void* recvbuf, int count, MPI_Datatype datatype, MPI_Op op, MPI_Comm comm ) Example (exscan.c) int sbuf[2], rbuf[2]; MPI_Exscan(sbuf, rbuf, 2, MPI_INT, MPI_SUM, MPI_COMM_WORLD); 自分を除く自分より番号の若いプロセス上の値の総和 MPI_COMM_WORLD MPI_COMM_WORLD P0 P1 sbuf sbuf Exscan P0 P1 rbuf rbuf =-- --=-- 2=2 5=5 P2 sbuf P2 rbuf =2+0 12=5+7 P3 sbuf P3 rbuf = =

28 27 MPI_Reduce/MPI_Scan/MPI_Exscan の注意点 受信バッファ (recvbuf) の値 MPI_Reduce では root のみ値を代入 MPI_Scan では全プロセスで値を代入 MPI_Exscan ではプロセス 0 以外で値を代入

29 28 MPI_Scan/MPI_Exscan の代表的な使い方 大域配列のオフセット値を求める 分散配列 大域配列 Process0 Process1 Process2 Process int in, out; in = 10; // local array size out = 0; MPI_Exscan( &in, &out, 1, MPI_INT, MPI_SUM, MPI_COMM_WORLD ); printf( rank %d begins from %d n, rank, out); >mpiexec n 4./a.out rank 0 begins from 0 rank 1 begins from 10 rank 2 begins from 20 rank 3 begins from 30 >

30 29 定義済みの主なデータ型と演算 Integer: Floating point: Complex: Logical: Byte: MPI_MAX MPI_MIN MPI_MAXLOC MPI_MINLOC MPI_SUM MPI_PROD MPI_LAND MPI_LOR MPI_LXOR MPI_BAND MPI_BOR MPI_BXOR MPI_INT, MPI_LONG, MPI_UNSIGNED, etc. MPI_FLOAT, MPI_DOUBLE, etc. MPI_C_COMPLEX, MPI_C_DOUBLE_COMPLEX, etc. MPI_C_BOOL, etc. MPI_BYTE 最大値最小値最大値と指標最小値と指標総和総積論理積論理和論理排他和ビット積ビット和ビット排他和 Integer Floating Complex Logical Byte

31 MPI_MAXLOC/MPI_MINLOC の使い方 最大の実数値とその指標を探す Example (maxloc.c) struct{ float value; int index; } in[2], out[2]; in[0].value =...; in[0].index =...; in[1].value =...; in[1].index =...; MPI_Reduce( in, out, 2, MPI_FLOAT_INT, MPI_MAXLOC, 1, MPI_COMM_WORLD ); 指標は必ず整数 value が整数の場合は MPI_2INT 型 (MPI_INT_INT ではない ) 例 in[0].value in[0].index in[1].value in[1].index Process Process Process Process プロセス 1 には以下の値が格納される out[0].value out[0].index out[1].value out[1].index Process

32 戻り値なし ユーザ定義演算 2 次元ベクトル合成 Example (reduceop.c) typedef struct{ float vx, vy; } fvec2; void addvec(void *invec, void* iovec, int *len, MPI_Datatype *dptr) { fvec2 *a = (fvec2 *)invec; // in vector この例では4が代入される fvec2 *b = (fvec2 *)iovec; // inout vector for(int i=0; i<*len; ++i) { b->vx += a->vx; b->vy += a->vy; 演算本体 ( 結果を iovec 側に格納する ) ++a; ++b; } } MPI_Datatype vtype; MPI_Type_contiguous(2, MPI_FLOAT, &vtype); MPI_Type_commit(&vtype); MPI_Op myop; MPI_Op_create(addvec, 1, &myop); dptr は省略不可 fvec2 を MPI_Datatype に変換 可換演算は true ( 実装依存 ) を指定 fvec2 in[4], sum[4]; MPI_Reduce(in, sum, 4, vtype, myop, 1, MPI_COMM_WORLD); MPI_Op_free(&myOp); 31

33 MPI_Allgather Function prototype int MPI_Allgather( const void* sendbuf, int sendcount, MPI_Datatype sendtype, void* recvbuf, int recvcount, MPI_Datatype recvtype, MPI_Comm comm ) Example (allgather.c) int sbuf[2], rbuf[8]; MPI_Allgather(sbuf, 2, MPI_INT, rbuf, 2, MPI_INT, MPI_COMM_WORLD); 引数は Gather とほぼ同じ (root が無い ) 動作は Gather+Bcast MPI_COMM_WORLD MPI_COMM_WORLD P0 P1 sbuf sbuf Allgather P0 P1 rbuf rbuf P2 sbuf 0 1 P2 rbuf P3 sbuf 0 1 P3 rbuf

34 MPI_Allgatherv Function prototype int MPI_Allgatherv( const void* sendbuf, int sendcount, MPI_Datatype sendtype, void* recvbuf, const int recvcounts[], const int displs[], MPI_Datatype recvtype, MPI_Comm comm ) Example (allgatherv.c) int sbuf[3], rbuf[11]; int rcounts[4]={1,2,3,2}, displs[4]={0,2,5,9}; MPI_Allgatherv(sbuf, 3, MPI_INT, rbuf, rcounts, displs, MPI_INT, MPI_COMM_WORLD); 注 :rcounts, displsはrootの値だけ有効 sendcountの値はプロセス毎に異なる ( この例ではプロセス2) 引数はGathervとほぼ同じ(rootが無い) 動作はGatherv+Bcast MPI_COMM_WORLD MPI_COMM_WORLD P0 P1 sbuf sbuf Allgatherv P0 P1 rbuf rbuf P2 sbuf P2 rbuf P3 sbuf P3 rbuf

35 MPI_Allreduce Function prototype int MPI_Allreduce( const void* sendbuf, void* recvbuf, int count, MPI_Datatype datatype, MPI_Op op, MPI_Comm comm ) Example (allreduce.c) int sbuf[2], rbuf[2]; MPI_Allreduce(sbuf, rbuf, 2, MPI_INT, MPI_SUM, MPI_COMM_WORLD); 引数は Reduce とほぼ同じ (root が無い ) 動作は Reduce+Bcast MPI_COMM_WORLD MPI_COMM_WORLD P0 P1 sbuf sbuf Allreduce P0 P1 rbuf rbuf = = = = P2 sbuf P2 rbuf = = P3 sbuf P3 rbuf = =

36 MPI_Reduce_scatter_block Function prototype int MPI_Reduce_scatter_block( const void* sendbuf, void* recvbuf, int recvcount, MPI_Datatype datatype, MPI_Op op, MPI_Comm comm ) Example (reducescatterblock.c) int sbuf[8], rbuf[2]; MPI_Scatter_block(sbuf, rbuf, 2, MPI_INT, MPI_SUM, MPI_COMM_WORLD); 引数は Reduce とほぼ同じ (root が無い ) 動作は Reduce+Scatter(sum に Reduce して Scatter) MPI_COMM_WORLD MPI_COMM_WORLD P0 P1 sbuf sbuf sum Reduce _scatter _block P0 P1 rbuf rbuf P2 P3 sbuf sbuf = = = = = = = = P2 P3 rbuf rbuf

37 MPI_Reduce_scatter Function prototype int MPI_Reduce_scatter( const void* sendbuf, void* recvbuf, const int recvcounts[], MPI_Datatype datatype, MPI_Op op, MPI_Comm comm ) Example (reducescatter.c) int sbuf[8], rbuf[3]; int rcounts[4]={1,2,3,2}; MPI_Scatter(sbuf, rbuf, rcounts, MPI_INT, MPI_SUM, MPI_COMM_WORLD); Reduce とほぼ同じ ( 引数に root が無い recvcount が配列 ) 動作は Reduce+Scatterv(sum に Reduce して Scatterv) MPI_COMM_WORLD MPI_COMM_WORLD P0 P1 sbuf sbuf sum Reduce _scatter P0 P1 sbuf sbuf P2 P3 sbuf sbuf = = = = = = = = P2 P3 sbuf sbuf

38 MPI_Alltoall Function prototype int MPI_Alltoall( const void* sendbuf, int sendcount, MPI_Datatype sendtype, void* recvbuf, int recvcount, MPI_Datatype recvtype, MPI_Comm comm ) Example (alltoall.c) int sbuf[8], rbuf[8]; MPI_Alltoall(sbuf, 2, MPI_INT, rbuf, 2, MPI_INT, MPI_COMM_WORLD); 引数は Gather とほぼ同じ (root が無い ) 動作はプロセス毎に sbuf の開始位置を変えて Gather, またはプロセス毎に rbuf の開始位置を変えて Scatter sbuf, rbuf に十分な大きさがあれば sendcount!=recvcount も可能 (intercomm の場合など ) MPI_COMM_WORLD MPI_COMM_WORLD P0 P1 sbuf sbuf Alltoall P0 P1 rbuf rbuf P2 sbuf P2 rbuf P3 sbuf P3 rbuf

39 MPI_Alltoallv Function prototype int MPI_Alltoallv( const void* sendbuf, const int sendcounts[], const int sdispls[], MPI_Datatype sendtype, void* recvbuf, const int recvcounts[], const int rdispls[], MPI_Datatype recvtype, MPI_Comm comm ) scounts, sdispls, rcounts, rdispls の値は整合的でなければならない scounts, rcounts の値は互いに転置関係 scounts rcounts Process0 { a0, a1, a2, a3 } { a0, b0, c0, d0 } Process1 { b0, b1, b2, b3 } { a1, b1, c1, d1 } Process2 { c0, c1, c2, c3 } { a2, b2, c2, d2 } Process3 { d0, d1, d2, d3 } { a3, b3, c3, d3 } sendbuf, recvbuf には十分な大きさが必要 int sendbuf[ssize]; // ssize > sdispls[0]+sdispls[1]+... int recvbuf[rsize]; // rsize > rdispls[0]+rdispls[1]+... 引数は Alltoall とほぼ同じ (sendcount, recvcount が配列 ) 動作は各プロセスが sbuf と rbuf の開始位置を変えて Gather 38

40 39 Example (alltoallv.c) int sbuf[13], rbuf[13]; int scounts[4], sdispls[4], rcounts[4], rdispls[4]; MPI_Alltoallv(sbuf, scounts, sdispls, MPI_INT, rbuf, rcounts, rdispls, MPI_INT, 1, MPI_COMM_WORLD); scounts sdispls rcounts rdispls Process0 { 2, 1, 3, 2 } { 0, 2, 4, 8 } { 2, 1, 2, 3 } { 0, 3, 5, 9 } Process1 { 1, 2, 2, 3 } { 1, 3, 5, 7 } { 1, 2, 3, 2 } { 2, 4, 7,11 } Process2 { 2, 3, 1, 2 } { 2, 5, 8,11 } { 3, 2, 1, 2 } { 0, 4, 8,10 } Process3 { 3, 2, 2, 1 } { 2, 6, 9,12 } { 2, 3, 2, 1 } { 1, 3, 6, 9 } プロセス数が 4 で上記のパラメータの場合 MPI_COMM_WORLD MPI_COMM_WORLD P0 P1 sbuf sbuf Alltoallv P0 P1 rbuf rbuf P2 sbuf P2 rbuf P3 sbuf P3 rbuf

41 40 MPI_Alltoallw Function prototype int MPI_Alltoallw( const void* sendbuf, const int sendcounts[], const int sdispls[], const MPI_Datatype sendtypes[], void* recvbuf, const int recvcounts[], const int rdispls[], const MPI_Datatype recvtypes[], MPI_Comm comm ) プロセス毎に異なった Datatype sendbuf, recvbuf には十分な大きさが必要 sdispls, rdispls はバイト数で指定する Example (alltoallw.c) sdispls[0] = rdispls[0] = 0; for(int i=0; i<size-1; ++i) { sdispls[i+1] = sdispls[i] + sizeof(sendtypes[i])*nsendcounts[i]; rdispls[i+1] = rdispls[i] + sizeof(recvtypes[i])*nrecvcounts[i]; } 引数は Alltoallv とほぼ同じ (sendtypes, recvtypes が配列 )

42 41 MPI_Barrier Function prototype int MPI_Barrier( MPI_Comm comm ) Example MPI_Barrier(MPI_COMM_WORLD); 全プロセスがコールするまで待ち合わせる 全プロセスが同時に復帰する訳ではない ( タイムラグ有り ) ハードウェアによって高速化している場合もある

43 その他の関数 Function prototype int MPI_Reduce_local( const void* inbuf, void* inoutbuf, int count, MPI_Datatype datatype, MPI_Op op ) Example int ibuf[2], iobuf[2]; MPI_Reduce_local(ibuf, iobuf, 2, MPI_INT, MPI_SUM ); 引数に root と MPI_Comm が無い プロセス内のみで reduce Function prototype int MPI_Op_commutative (MPI_Op op, int *commute ) Example int iscommutative; MPI_Op_commutative(MPI_INT, &iscommutative ); 演算が可換か否かを返す (true or false) 42

44 43 非閉塞 (Nonblocking) 通信 通信相手の状態に関係なく即座に復帰 後から Test/Wait 関数で完了 ノード内に通信用コプロセッサ等を持つ場合には Linux カーネルを改造し通信処理を荷卸し (off-load) することで通信の隠蔽 (overwrap) が可能な場合あり * 荷卸しできない場合は Test/Wait 関数の中で通信を開始するので通信は隠蔽できない (multi-thread 化すれば隠蔽可能 ) 非閉塞通信は本来デッドロックを避けるために導入 MPI standard の中に隠蔽に関する規定は無い *With suitable hardware, may proceed concurrently with computations..., pp. 47, MPI Standard 3.1 *whether such overlapping is possible may depend on the hardware environment, pp. 109, Using MPI, 2nd ed., MIT Press, 1999

45 非閉塞通信の使い方 Ibcast と Ireduce を使う場合 Example int buf[3] =..., sbuf[2] =..., rbuf[2] =... ; // buffers MPI_Request req[2]; MPI_Ibcast( buf, 3, MPI_INT, MPI_COMM_WORLD, &req[0] ); // some workloads MPI_Ireduce( sbuf, rbuf, 2, MPI_INT, MPI_SUM, 1, MPI_COMM_WORLD, &req[1] ); // another workloads MPI_Waitall(2, req, MPI_STATUSES_IGNORE); 即座に復帰 即座に復帰 待ち合せて完了 集団通信で status は不要 閉塞通信より引数が一つ (&req[ ]) 増えただけ Waitall が復帰するまで buf, sbuf, rbuf にアクセスできない その他の集団通信の使い方も上記と同じ Wait, Test については要素通信の中で説明する 44

46 非閉塞 Barrier の使い方 仮定 : 処理 A と B は同時に実行できない 1. blocking-barrier で分離する (Bulk Synchronous) MPI_Barrier Process 0 A busy wait B Process 1 A B time MPI_Barrier B は同時に開始するが busy wait が発生する 2. A,B と同時実行可能な C を挟んで non-blocking barrier で分離する MPI_Ibarrier MPI_Wait Process 0 A C B Process 1 A C B time MPI_Ibarrier MPI_Wait busy wait は解消するが B は同時に開始しない 45

47 送受信バッファの共通化 送信バッファに MPI_IN_PLACE を指定するもの root の指定のみ有効 MPI_Gather, MPI_Gatherv, MPI_Reduce 全プロセスで指定必要 MPI_Scan, MPI_Exscan, MPI_Allgather, MPI_Allgatherv, MPI_Allreduce, MPI_Alltoall, MPI_Alltoallv, MPI_Alltoallw, MPI_Reduce_scatter_block, MPI_Reduce_scatter 受信バッファに MPI_IN_PLACE を指定するもの root の指定のみ有効 MPI_Scatter, MPI_Scatterv 非対応 MPI_Bcast, MPI_Barrier, MPI_Reduce_local, MPI_Op_commutative 非閉塞通信も閉塞通信と全く同じメモリ節約に有効だが 同一アドレスへのread/write 発生により効率面で不利 C 言語ではポインタを使えばメモリコピー不要で配列入替えが可能 46

48 47 MPI 関数各論 1. 集団通信 2. 要素通信 3. 片側通信 4. マルチスレッド 5. 派生データ型 6. ファイル I/O 7. コミュニケータ トポロジー 8. プロセス生成 9. その他

49 48 要素通信とは 注意点 最も基本的な通信方法 コミュニケータ内の一対のプロセス間の通信 一方が送信し 他方が受信する 送信側が制御する push mechanism 送受信を一つにまとめた複合通信が用意されている オーバーヘッドが軽い持続通信が用意されている 送信側にはモードがある 不適切なモード選択はデッドロックを引き起こす

50 要素通信関数一覧 Send Recv Probe Combined Persistent MPI_Send MPI_Ssend MPI_Bsend MPI_Rsend MPI_Recv MPI_Mrecv* Blocking MPI_Probe MPI_Mprobe* MPI_Sendrecv MPI_Sendrecv_replace MPI_Send_init MPI_Ssend_init MPI_Bsend_init MPI_Rsend_init MPI_Recv_init Nonblocking MPI_Isend MPI_Issend MPI_Ibsend MPI_Irsend MPI_Irecv MPI_Imrecv* MPI_Iprobe MPI_Improbe* MPI_Start MPI_Startall Intercomm * MPI_Mrecv, MPI_Mprobe, MPI_Imrecv, MPI_Improbe はマルチスレッドで説明する 49

51 要素通信関数一覧 ( 続 ) Complete Request Status Buffer Blocking MPI_Wait MPI_Waitany MPI_Waitall MPI_Waitsome MPI_Cancel MPI_Request_free MPI_Request_get_status MPI_Test_cancelled MPI_Get_count MPI_Get_element* MPI_Get_element_x* MPI_Buffer_attach MPI_Buffer_detach Nonblocking MPI_Test MPI_Testany MPI_Testall MPI_Testsome * MPI_Get_element, MPI_Get_element_x の説明は省略 50

52 MPI_Send Function prototype int MPI_Send( const void* buf, int count, MPI_Datatype datatype, int dest, int tag, MPI_Comm comm ) int buf[2]; MPI_Send(buf, 2, MPI_INT, 1, 9, MPI_COMM_WORLD); buf から始まる 2 つの整数にタグ 9 を付けてプロセス 1 に送る MPI_Recv Function prototype int MPI_Recv( void* buf, int count, MPI_Datatype datatype, int source, int tag, MPI_Comm comm, MPI_Status *status ) int buf[2]; MPI_Status status; MPI_Recv(buf, 2, MPI_INT, 0, 9, MPI_COMM_WORLD, &status ); タグ 9 が付いた 2 つの整数をプロセス 0 から受け取り buf に格納する タグは通信の順序を識別するためにユーザが付ける整数 status は MPI_SOURCE, MPI_TAG, MPI_ERROR からなる構造体 MPI_Send の buf 以外の引数をエンベロープ (envelope) と呼ぶ 51

53 52 2 プロセスの例 Proc0 から Proc1 にデータを送る Example (sendrecv01.c) int sbuf[2], rbuf[2]; if(rank==0) { sbuf[0] = 10; sbuf[1] = 20; MPI_Send( sbuf, 2, MPI_INT, 1, 9, MPI_COMM_WORLD ); } else if(rank==1) MPI_Recv( rbuf, 2, MPI_INT, 0, 9, MPI_COMM_WORLD, MPI_STATUS_IGNORE ); 注 :status は必要ないので MPI_STATUS_IGNORE で無効にしている Send Proc0 1 4 Proc1 2 Recv 3 1 Proc0 が Send を開始 2 Proc1 が Recv を開始 3 Proc1 の Recv が復帰 ( 完了 ) 4 Proc0 の Send が復帰 ( 完了 ) 正常終了

54 Proc0 と Proc1 がデータを交換する ( その 1) Example (sendrecv02.c) int sbuf[2], rbuf[2]; if(rank==0) { sbuf[0] = 10; sbuf[1] = 20; MPI_Send( sbuf, 2, MPI_INT, 1, 8, MPI_COMM_WORLD ); MPI_Recv( rbuf, 2, MPI_INT, 1, 9, MPI_COMM_WORLD, MPI_STATUS_IGNORE ); } else if(rank==1) { sbuf[0] = 20; sbuf[1] = 30; MPI_Recv( rbuf, 2, MPI_INT, 0, 8, MPI_COMM_WORLD, MPI_STATUS_IGNORE ); MPI_Send( sbuf, 2, MPI_INT, 0, 9, MPI_COMM_WORLD ); } Send Proc Recv 7 Proc1 2 Recv 3 5 Send 8 1 Proc0 が Send を開始 2 Proc1 が Recv を開始 3 Proc1 の Recv が復帰 ( 完了 ) 4 Proc0 の Send が復帰 ( 完了 ) 5 Proc1 が Send を開始 6 Proc0 が Recv を開始 7 Proc0 の Recv が復帰 ( 完了 ) 8 Proc1 の Send が復帰 ( 完了 ) 正常終了 53

55 54 Proc0 と Proc1 がデータを交換する ( その 2) Example (sendrecv03.c) int sbuf[2], rbuf[2]; if(rank==0) { sbuf[0] = 10; sbuf[1] = 20; MPI_Recv( rbuf, 2, MPI_INT, 1, 9, MPI_COMM_WORLD, MPI_STATUS_IGNORE ); MPI_Send( sbuf, 2, MPI_INT, 1, 8, MPI_COMM_WORLD ); } else if(rank==1) { sbuf[0] = 20; sbuf[1] = 30; MPI_Recv( rbuf, 2, MPI_INT, 0, 8, MPI_COMM_WORLD, MPI_STATUS_IGNORE ); MPI_Send( sbuf, 2, MPI_INT, 0, 9, MPI_COMM_WORLD ); } Proc0 1 Recv Proc1 2 Recv 1 Proc0 が Recv を開始 2 Proc1 が Recv を開始 3 相手側が Send を開始するまで Recv は復帰できない 4 Recv が復帰しないと Send を開始できない 互いに相手を待ち続ける

56 Proc0 と Proc1 がデータを交換する ( その 3) Example (sendrecv04.c) int sbuf[2], rbuf[2]; if(rank==0) { sbuf[0] = 10; sbuf[1] = 20; MPI_Send( sbuf, 2, MPI_INT, 1, 8, MPI_COMM_WORLD ); MPI_Recv( rbuf, 2, MPI_INT, 1, 9, MPI_COMM_WORLD, MPI_STATUS_IGNORE ); } else if(rank==1) { sbuf[0] = 20; sbuf[1] = 30; MPI_Send( sbuf, 2, MPI_INT, 0, 9, MPI_COMM_WORLD ); MPI_Recv( rbuf, 2, MPI_INT, 0, 8, MPI_COMM_WORLD, MPI_STATUS_IGNORE ); } Proc0 1 Send 5 7 Recv 正常終了 Proc1 2 Send 6 8 Recv 10 システムバッファ データが小さい場合 (<16KB) 1 Proc0 が Send を開始 2 Proc1 が Send を開始 3 Proc0 がデータをバッファリング 4 Proc1 がデータをバッファリング 5 Proc0 の Send が復帰 6 Proc1 の Send が復帰 7 Proc0 が Recv を開始 8 Proc1 が Recv を開始 9 Proc0 の Recv が復帰 10 Proc1 の Recv が復帰 バッファリング閾値は実装依存!! 55

57 56 Proc0 と Proc1 がデータを交換する ( その 4) Example (sendrecv05.c) int sbuf[2], rbuf[2]; if(rank==0) { sbuf[0] = 10; sbuf[1] = 20; MPI_Send( sbuf, 2, MPI_INT, 1, 8, MPI_COMM_WORLD ); MPI_Recv( rbuf, 2, MPI_INT, 1, 9, MPI_COMM_WORLD, MPI_STATUS_IGNORE ); } else if(rank==1) { sbuf[0] = 20; sbuf[1] = 30; MPI_Send( sbuf, 2, MPI_INT, 0, 9, MPI_COMM_WORLD ); MPI_Recv( rbuf, 2, MPI_INT, 0, 8, MPI_COMM_WORLD, MPI_STATUS_IGNORE ); } Proc0 1 Send Proc1 2 Send データが大きい場合 (>16KB) 1 Proc0 が Send を開始 2 Proc1 が Send を開始 3 相手側が Recv を開始するまで Send は復帰できない 4 Send が復帰しないと Recv を開始できない 互いに相手を待ち続ける

58 57 通信モード 送信関数には 4 種類のモードがある Standard mode MPI_Send, MPI_Isend, MPI_Send_init Synchronous mode MPI_Ssend, MPI_Issend, MPI_Ssend_init Ready mode MPI_Rsend, MPI_Irsend, MPI_Rsend_init Buffered mode MPI_Bsend, MPI_Ibsend, MPI_Bsend_init 受信関数にはモードがない (push mechanism) MPI_Recv, MPI_Irecv, MPI_Recv_init

59 各モードの特徴 Standard データが小さい場合はシステムバッファにバッファリング データが大きい場合は受信側とハンドシェイク Synchronous バッファリングせず受信側とハンドシェイク 最もデッドロック起き易い このモードでデッドロックしないプログラムをsafe programと呼ぶ Ready 受信側の状態に関係なく即座に送信 受信側が既に待機している場合のみ開始可能 それ以外はエラーまたは不定状態 Buffered ユーザが設定した添付バッファにバッファリング 58

60 通信モードの実装方法 MPICH では 2 つの通信プロトコルを定義 * Eager protocol エンベロープに続けてデータも送信 Rendezvous protocol エンベロープだけ送り 準備が整ったらデータを送信 送信関数の引数 MPI_Send( buf, 2, MPI_INT, 1, 9, MPI_COMM_WORLD ); data** envelope message * MPI standard に規定はない ** buf から始まるデータ全体を指す 59

61 60 recv 側の基本動作 未処理の recv を expected queue に登録 未処理の send を unexpected queue に登録 send が到着すると expected queue に matching recv を探す recv が発行されると unexpected queue に matching send を探す Eager protocol a) recv 先行 inquire send recv unexpected queue no matching send register recv inquire matching recv exists store rbuf expected queue send inquire no matching recv expected queue b) send 先行 store register send sysbuf copy rbuf recv inquire matching send exists unexpected queue

62 Rendezvous protocol c) recv 先行 inquire send recv unexpected queue no matching send register recv inquire matching recv exists expected queue store rbuf send d) send 先行 recv inquire no matching recv register send inquire matching send exists expected queue unexpected queue store rbuf 61

63 62 通信モードと protocol の対応例 Standard ( 短メッセージはバッファリング有り Eager それ以外はバッファリング無し Rendezvous) Synchronous ( バッファリング無し Rendezvous) Ready ( バッファリング無し Eager) Buffered ( ユーザ定義バッファ有り Rendezvous)

64 通信モードを使ってデッドロックを避ける プロセス0でMPI_SendをMPI_Bsendに置き換える. プロセス1はバッファリングを抑止するためMPI_Ssendを使う. Example (mode01.c) int sbuf[2], rbuf[2]; if(rank==0) { sbuf[0] = 10; sbuf[1] = 20; MPI_Bsend( sbuf, 2, MPI_INT, 1, 8, MPI_COMM_WORLD ); MPI_Recv( rbuf, 2, MPI_INT, 1, 9, MPI_COMM_WORLD, MPI_STATUS_IGNORE ); } else if(rank==1) { sbuf[0] = 20; sbuf[1] = 30; MPI_Ssend( sbuf, 2, MPI_INT, 0, 9, MPI_COMM_WORLD ); MPI_Recv( rbuf, 2, MPI_INT, 0, 8, MPI_COMM_WORLD, MPI_STATUS_IGNORE ); } Bsend Proc0 Proc Recv 8 3 正常終了 2 Ssend 6 7 Recv 9 1 Proc0 が Bsend を開始 2 Proc1 が Ssend を開始 3 添付バッファにバッファリング 4 Proc0 が Bsend から復帰 5 Proc0 が Recv を開始 6 Proc1 が Ssend から復帰 7 Proc1 が Recv を開始 8 Proc0 が Recv から復帰 9 Proc1 が Recv から復帰 63

65 64 MPI_Buffer_attach/MPI_Buffer_detach/ MPI_Bsend/MPI_Ssend Function prototype int MPI_Buffer_attach( void* buffer, int size ) int MPI_Buffer_detach( void* buffer_addr, int* size ) int MPI_Bsend( const void* buf, int count, MPI_Datatype datatype, int dest, int tag, MPI_Comm comm ) #define BUFFER_SIZE int bufsize = sizeof(int)*buffer_size; void *buf = malloc((size_t)bufsize); MPI_Buffer_attach(buf, bufsize); if(rank==0) MPI_Bsend(buf, 5000, MPI_INT, 1, 9, MPI_COMM_WORLD); else if(rank==1) MPI_Recv(buf, 5000, MPI_INT, 0, 9, MPI_COMM_WORLD); MPI_Buffer_detach(buf, &bufsize); ユーザ定義のバッファを生成 解放する 注 : バッファサイズの指定はバイト数! Buffer_detach の size はポインタ型!

66 3 プロセスのデータ交換 周期境界の場合 Example (mode02.c) int sbuf[2], rbuf[2]; if(rank==0) { sbuf[0] = 10; sbuf[1] = 20; MPI_Send( sbuf, 2, MPI_INT, 1, 9, MPI_COMM_WORLD ); MPI_Recv( rbuf, 2, MPI_INT, 2, 7, MPI_COMM_WORLD, MPI_STATUS_IGNORE ); } else if(rank==1) { sbuf[0] = 30; sbuf[1] = 40; MPI_Send( sbuf, 2, MPI_INT, 2, 8, MPI_COMM_WORLD ); MPI_Recv( rbuf, 2, MPI_INT, 0, 9, MPI_COMM_WORLD, MPI_STATUS_IGNORE ); } else if(rank==2) { sbuf[0] = 50; sbuf[1] = 60; MPI_Send( sbuf, 2, MPI_INT, 0, 7, MPI_COMM_WORLD ); MPI_Recv( rbuf, 2, MPI_INT, 1, 8, MPI_COMM_WORLD, MPI_STATUS_IGNORE ); } Proc0 Proc1 Proc2 Send Send Send 正常終了できるかはバッファリングに依存 Recv Recv Recv Buffered mode を使う 65

67 プロセス0でMPI_SendをMPI_Bsendに置き換える. プロセス1と2はバッファリングを抑止するためMPI_Ssendを使う. Function prototype int MPI_Ssend( const void* buf, int count, MPI_Datatype datatype, int dest, int tag, MPI_Comm comm ) Example (mode03.c) int sbuf[2], rbuf[2]; if(rank==0) { sbuf[0] = 10; sbuf[1] = 20; MPI_Bsend( sbuf, 2, MPI_INT, 1, 9, MPI_COMM_WORLD ); MPI_Recv( rbuf, 2, MPI_INT, 2, 7, MPI_COMM_WORLD, MPI_STATUS_IGNORE ); } else if(rank==1) { sbuf[0] = 30; sbuf[1] = 40; MPI_Ssend( sbuf, 2, MPI_INT, 2, 8, MPI_COMM_WORLD ); MPI_Recv( rbuf, 2, MPI_INT, 0, 9, MPI_COMM_WORLD, MPI_STATUS_IGNORE ); } else if(rank==2) { sbuf[0] = 50; sbuf[1] = 60; MPI_Ssend( sbuf, 2, MPI_INT, 0, 7, MPI_COMM_WORLD ); MPI_Recv( rbuf, 2, MPI_INT, 1, 8, MPI_COMM_WORLD, MPI_STATUS_IGNORE ); } 1 tag=7 の送受信が完了 2 tag=8 の送受信が完了 3 tag=9 の送受信が完了 添付バッファサイズが十分なら正常終了 しかし送受信は逐次的 非効率 66

68 全てのプロセスで MPI_Send を MPI_Bsend に置き換える.. Example (mode04.c) int sbuf[2], rbuf[2]; if(rank==0) { sbuf[0] = 10; sbuf[1] = 20; MPI_Bsend( sbuf, 2, MPI_INT, 1, 9, MPI_COMM_WORLD ); MPI_Recv( rbuf, 2, MPI_INT, 2, 7, MPI_COMM_WORLD, MPI_STATUS_IGNORE ); } else if(rank==1) { sbuf[0] = 30; sbuf[1] = 40; MPI_Bsend( sbuf, 2, MPI_INT, 2, 8, MPI_COMM_WORLD ); MPI_Recv( rbuf, 2, MPI_INT, 0, 9, MPI_COMM_WORLD, MPI_STATUS_IGNORE ); } else if(rank==2) { sbuf[0] = 50; sbuf[1] = 60; MPI_Bsend( sbuf, 2, MPI_INT, 0, 7, MPI_COMM_WORLD ); MPI_Recv( rbuf, 2, MPI_INT, 1, 8, MPI_COMM_WORLD, MPI_STATUS_IGNORE ); } 添付バッファサイズが十分なら正常終了 通信は並列に実行可能しかしメモリコピーの時間が必要データサイズが大きな場合非効率 非閉塞 Synchronous 通信を使う! 67

69 MPI_Issend 全てのプロセスでMPI_SendをMPI_Issendに置き換える. 後からMPI_Waitで完了させる. Function prototype int MPI_Issend( const void* buf, int count, MPI_Datatype datatype, int dest, int tag, MPI_Comm comm, MPI_Request *request ) Example (mode05.c) MPI_Request req; int sbuf[2], rbuf[2]; if(rank==0) { sbuf[0] = 10; sbuf[1] = 20; MPI_Issend( sbuf, 2, MPI_INT, 1, 9, MPI_COMM_WORLD, &req ); MPI_Recv( rbuf, 2, MPI_INT, 2, 7, MPI_COMM_WORLD, MPI_STATUS_IGNORE ); } else if(rank==1) { sbuf[0] = 30; sbuf[1] = 40; MPI_Issend( sbuf, 2, MPI_INT, 2, 8, MPI_COMM_WORLD, &req ); MPI_Recv( rbuf, 2, MPI_INT, 0, 9, MPI_COMM_WORLD, MPI_STATUS_IGNORE ); } else if(rank==2) { sbuf[0] = 50; sbuf[1] = 60; MPI_Issend( sbuf, 2, MPI_INT, 0, 7, MPI_COMM_WORLD, &req ); MPI_Recv( rbuf, 2, MPI_INT, 1, 8, MPI_COMM_WORLD, MPI_STATUS_IGNORE ); } MPI_Wait( &req, MPI_STATUS_IGNORE ); 正常終了 ( 並列的 メモリコピー不要 ) 但しリクエストの完了が必要 68

70 完了関数の基本動作 閉塞通信では復帰 = 完了なので不要 非閉塞通信 ( 持続通信も含む ) では通信ハンドル (request) を生成して即座に復帰する 通信の完了には request を引数に Wait または Test 関数を呼ぶ 通信が完了していれば request から status が生成される recv 側は MPI_Get_count で status から受信データ数を得る send 側の request は MPI_request_free ですぐに解放しても良い Wait 関数 (MPI_Wait, MPI_Waitall, MPI_Waitany, MPI_Waitsome) Wait は request の完了まで待ち 完了後に status を返す Wait の動作は非局所的 ( 他プロセスに依存 ) で blocking Test 関数 (MPI_Test, MPI_Testall, MPI_Testany, MPI_Testsome) Test は request の状態を flag に返して復帰する status の値は flag=true の時には正常値 flag=false の時は不定値となる Test の動作は局所的 ( 自プロセスで完結 ) で nonblocking 69

71 70 完了関数の引数一覧 int MPI_Request int int int MPI_Status MPI_Wait ( request, *status ) MPI_Test ( request, *flag, *status ) MPI_Wait_all ( count, requests[], statuses[] ) MPI_Test_all ( count, requests[], *flag, statuses[] ) MPI_Wait_any ( count, requests[], *index, *status ) MPI_Test_any ( count, requests[], *flag, *index, *status ) MPI_Wait_some ( incount, requests[], *outcount, indices[], statuses[] ) MPI_Test_some ( incount, requests[], *outcount, indices[], statuses[] ) all は requests[0,, count-1] 全てについて Wail/Test any は requests[0,, count-1] のどれか一つ (index にその番号を返す ) some は requests[0,, incount-1] の内 *outcount 個 番号は indices Test_some は all, any と仕様が違うので注意 既に完了した request を再度 Wait, Test しても問題ない 非閉塞集団通信の場合の status の内容は不定 ( 記述無し )

72 71 完了関数の引数一覧 ( 続き ) MPI_Request int MPI_Status MPI_Cancel ( *request, ) MPI_Request_free ( *request, ) MPI_Request_get_status ( request, *flag, *status ) Cancel は request を取り消すが その後に MPI_Wait か MPI_Test で完了するか MPI_Request_free で解放する必要がある 非閉塞の要素通信は cancel できるが 集団通信はできない Cancel は重い処理なのでなるべく使用しない Request_free は request の割当てを解除 (deallocate) する解放された request は MPI_Wait や MPI_Test の引数に指定できない Request_get_status は request が完了したかどうかを調べ結果を flag と status に返す const MPI_Status MPI_Test_cancelled ( *status, *flag ) status を調べて対応する通信が cancel に成功したかを flag に返す int

73 複合通信 (Combined communication) 自プロセス内の送信と受信を一つの関数で実行する Function prototype 一対の送受信ではないことに注意 通信相手側は通常の send, recv で受けてることもできる バッファを共通化した関数もある 閉塞通信のみ int MPI_Sendrecv ( const void *sendbuf, int sendcount, MPI_Datatype sendtype, int dest, int sendtag, void *recvbuf, int recvcount, MPI_Datatype recvtype, int source, int recvtag, MPI_Comm comm, MPI_Status *status ) int MPI_Sendrecv_replace ( void *buf, int count, MPI_Datatype datatype, int dest, int sendtag, int source, int recvtag, MPI_Comm comm, MPI_Status *status ) Example (-----.c) int sbuf[2], rbuf[2], buf[2]; int left, right; MPI_sendrecv( sbuf, 2, MPI_INT, left, 9, rbuf, 2, MPI_INT, right, 8, MPI_COMM_WORLD, MPI_STATUS_IGNORE ); MPI_sendrecv_replace( buf, 2, MPI_INT, left, 9, right, 8, MPI_COMM_WORLD, MPI_STATUS_IGNORE ); replace ではデータ型とサイズは送信と受信で同じでなければならない 72

74 持続通信 (Persistent communication) 最初に作った request を何度も再利用できる 通信開始は request を start させるだけでよい 非閉塞通信と同様に test, wait を呼んで完了させる Function prototype int MPI_Send_init( const void *buf, int count, MPI_Datatype datatype, int dest, int tag, MPI_Comm comm, MPI_Request *request ) int MPI_Ssend_init( const void *buf, int count, MPI_Datatype datatype, int dest, int tag, MPI_Comm comm, MPI_Request *request ) int MPI_Bsend_init( const void *buf, int count, MPI_Datatype datatype, int dest, int tag, MPI_Comm comm, MPI_Request *request ) int MPI_Rsend_init( const void *buf, int count, MPI_Datatype datatype, int dest, int tag, MPI_Comm comm, MPI_Request *request ) int MPI_Recv_init( const void *buf, int count, MPI_Datatype datatype, int source, int tag, MPI_Comm comm, MPI_Request *request ) int MPI_Start( MPI_Request *request ) int MPI_Startall( int count, MPI_Request array_of_requests [] ) 73

75 74 Example (-----.c) int sbuf[100], rbur[100]; MPI_Request req[2]; MPI_Send_init( sbuf, 100, MPI_INT, left, 9, MPI_COMM_WORLD, &(req[0]) ); MPI_Recv_init( rbuf, 100, MPI_INT, left, 8, MPI_COMM_WORLD, &(req[1]) ); for(int n=0; n<nstep; ++n) { // setup sbuf } MPI_Startall( 2, req ); // overlap calculations MPI_Waitall( 2, req, MPI_STATUSES_IGNORE ); // read rbuf

76 MPI_PROC_NULL を使う データを一斉に隣のプロセスに送るシフト通信の場合両端のプロセスは送信または受信のみとなる 送受信関数の dest/source に MPI_PROC_NULL を指定すると通信せずに復帰する これを使うとシフト通信のプログラムが少し見易くなる int sbuf[10], rbuf[10]; int size, rank; MPI_Comm_size( MPI_COMM_WORLD, &size ); MPI_Comm_rank( MPI_COMM_WORLD, &rank ); int dest = ( rank<size-1? rank+1 : MPI_PROC_NULL ); int src = ( rank>0? rank-1 : MPI_PROC_NULL ); MPI_Send( sbuf, 10, MPI_INT, dest, 1, MPI_COMM_WORLD ); MPI_Recv( rbuf, 10, MPI_INT, src, 1, MPI_COMM_WORLD, MPI_STATUS_IGNORE ); Proc0 Proc1 Proc2 Send Send Send MPI_PROC_NULL Recv Recv Recv MPI_PROC_NULL 75

77 MPI_ANY_SOURCE/MPI_ANY_TAG を使う マスターワーカモデル (Master-Worker model) では各ワーカがマスターに送ってくるタイミングが不定 プロセス番号とタグを指定して受信する方法では無駄な待ちが発生する 順不同にデータを受け取りたい 受信関数の source, tag に MPI_ANY_SOURCE, MPI_ANY_TAG を指定すると到着した順 (First come, first served) に受信する int rbuf[100]; int count; if( master ) MPI_Recv( rbuf, count, MPI_INT, MPI_ANY_SOURCE, MPI_ANY_TAG, MPI_COMM_WORLD, MPI_STATUS_IGNORE ); count は実際に受信するデータより大きな値でも可 しかし送信されたデータのサイズが予め分らないので受信バッファ rbuf のサイズを決められない 不足すると segmentation fault 等を発生しエラー終了 MPI_Probe で事前に status のみ取得する! 76

78 MPI_Probe/MPI_Iprobe/MPI_Get_count MPI_Probe はデータは受け取らず status のみ受け取る MPI_Iprobe はその非閉塞版 flag は true または false を返す MPI_Get_count は status から受信データのサイズを抽出する int MPI_Probe( int source, int tag, MPI_Comm comm, MPI_Status *status ) int MPI_Iprobe( int source, int tag, MPI_Comm comm, int *flag, MPI_Status *status ) int MPI_Get_count( const MPI_Status *status, MPI_Datatype datatype, int *count ) Int MPI_Alloc_mem( MPI_Aint size, MPI_Info info, void *baseptr ) int *rbuf; int count; MPI_Status status; if( master ) { MPI_Probe( MPI_ANY_SOURCE, MPI_ANY_TAG, MPI_COMM_WORLD, &status ); MPI_Get_count( &status, MPI_INT, &count ); MPI_Alloc_mem( count*sizdof(int), MPI_INFO_NULL, rbuf ); MPI_Recv( rbuf, count, MPI_INT, status.mpi_source, status.mpi_tag, MPI_COMM_WORLD, MPI_STATUS_IGNORE ); } 注 :status は MPI_SOURCE, MPI_TAG, MPI_ERROR 等をメンバとして持つ構造体 Probe / Iprobe はマルチスレッド実行時に問題あり 77

79 78 MPI 関数各論 1. 集団通信 2. 要素通信 3. 片側通信 4. マルチスレッド 5. 派生データ型 6. ファイル I/O 7. コミュニケータ トポロジー 8. プロセス生成 9. その他

80 79 片側通信とは 注意点 各プロセスのメモリ上にウィンドウ (window) と呼ばれる公開領域を設定し この領域に対して送受信する ウィンドウ初期化 送受信 同期の 3 ステップがある 送受信関数の呼び出しは送信側または受信側のみ 比較 演算を組合わせた送受信も可能 送受信関数には request を返すものもある 通信は request が無い場合でも同期が必要 同期方法には 2 種類の能動的同期 (active target synchronization) と 1 種類の受動的同期 (passive target synchronization) がある

81 片側通信関数一覧 Initialization MPI_Win_create MPI_Win_create_dynamic + MPI_Win_attach/detach MPI_Win_allocate MPI_Win_allocate_shared* MPI_Win_free Query MPI_Win_shared_query* Communication Nonlocal MPI_Put MPI_Get MPI_Accumurate MPI_Get_accumurate MPI_Fetch_and_op MPI_Compare_and_swap Local MPI_Rput MPI_Rget MPI_Raccumurate MPI_Rget_accumurate * MPI_Win_allocate_shared, MPI_Win_shared_query はマルチスレッドのページで説明する 80

82 片側通信関数一覧 ( 続 ) Synchronization Group Info Active target MPI_Win_Fence MPI_Win_Start MPI_Win_Post MPI_Win_Complete MPI_Win_Wait MPI_Win_Test MPI_Win_get_group* MPI_Win_set_info* MPI_Win_get_info* Passive target MPI_Win_lock MPI_Win_lock_all MPI_Win_unlock MPI_Win_unlock_all MPI_Win_flush MPI_Win_flush_all MPI_Win_flush_local MPI_Win_flush_local_all MPI_Win_sync * MPI_Win_get_group, MPI_Win_set_info, MPI_Win_get_info の説明は省略 81

83 初期化関数の引数 function Void MPI_Aint int MPI_Info MPI_Comm void MPI_Win MPI_Win_create *base size disp_unit info comm *win MPI_Win_create_dynamic info comm *win MPI_Win_allocate size disp_unit info comm *baseptr *win MPI_Win_allocate_shared size disp_unit info comm *baseptr *win MPI_Free *win 全て collective call である size と disp_unit はバイト数を指定する base, size, disp_unit, info はプロセス毎に異なってもよい MPI_Win_create は base から始まる size バイトの領域を設定する size==0 の場合は base に MPI_BOTTOM を指定してもよい MPI_Win_allocate はシステムが size バイトの領域を確保 その先頭番地を baseptr で返す (symmetric allocation できれば create より scalability 良い可能性 ) MPI_Win_create_dynamic は領域を確保せずにウィンドウを作成する通信する前に MPI_Win_attach でメモリ割当てが必要 MPI_Win_detach で解放してから再度割り当てることができる MPI_Win void MPI_Aint MPI_Win_attach ( win *base size ) MPI_Win_detach ( win *base ) どちらも local call size はバイト数指定 base, size はプロセス毎に異なってもよい MPI_Win_detach の引数 *base は正確には const void 82

84 送受信関数の引数 origin compare result target function void int Datatype void void int Datatype int Aint int Datatype Op Win Request MPI_Put *addr count type rank disp count type win MPI_Get *addr count type rank disp count type win MPI_Accumulate *addr count type rank disp count type op win MPI_Get_accumulate *addr count type *addr count type rank disp count type op win MPI_Fetch_and_op *addr *addr type rank disp op win MPI_Compare_and_swap *addr *addr *addr type rank disp win MPI_Rput *addr count type rank disp count type win *request MPI_Rget *addr count type rank disp count type win *request MPI_Raccumulate *addr count type rank disp count type op win *request MPI_Rget_accumulate *addr count type *addr count type rank disp count type op win *request c.f. abbreviations: MPI_Datatype => Datatype, MPI_Aint => Aint, MPI_Op => Op, MPI_Win => Win, MPI_Request => Request また origin と compare の void は正確には const void 関数の呼出し側 (caller) プロセスを origin 相手側 (callee) を target と呼ぶ データ移動の始点を source 終点を destination と呼ぶ MPI_Put origin=source, target=destination MPI_Get origin=destination, target=source target 側は memory window 内のデータのみアクセス可能 origin 側は制約なし 83

85 84 送受信関数の引数 ( 続 ) 動作は非閉塞的であり 必ず同期が必要 Put は origin の内容を target に代入 Get は target の内容を origin に代入 Op は既定義の操作のみ ( ユーザ定義は不可 ) origin と target の間で演算 Accumurate は演算結果を target に格納 Op = MPI_REPLACE の場合は origin の内容を target に代入 Get_accumulate は target の内容を result に保存後 演算結果を target に格納 Op = MPI_REPLACE の場合は origin の内容を target に代入 Op = MPI_NO_OP の場合は origin と target の内容は不変 Fetch_and_op は target は Get_accumulate でデータが 1 要素の場合に特化 Compare_and_swap も 1 要素のみ対象 target の内容を result に保存し compare と target の内容が等しい場合のみ origin の内容を target に代入 R のついた関数は request を返し MPI_Test, MPI_Wait 等で local に同期できる ( 但し passive target synchronization でしか使えない )

86 85 同期関数の引数 function int int MPI_Group int MPI_Win int MPI_Win_fence assert win MPI_Win_start group assert win MPI_Win_complete win MPI_Win_post group assert win MPI_Win_wait win MPI_Win_test win flag MPI_Win_lock type rank assert win MPI_Win_unlock rank win MPI_Win_flush rank win MPI_Win_flush_local rank win MPI_Win_lock_all assert win MPI_Win_unlock_all win MPI_Win_flush_all win MPI_Win_flush_local_all win MPI_Win_sync win -----

87 86 同期の方法 Active target: origin と target の両側で同期関数を呼ぶ origin は access epoch の間だけ通信できる target は exposure epoch の間だけウィンドウを公開する 以下の 2 種類の方法がある a. MPI_Win_fence b. MPI_Win_start + MPI_Win_complete / MPI_Win_post + MPI_Win_wait Passive target: origin 側のみが同期関数を呼ぶ origin は access epoch の間だけ通信できる target は同期関数を呼ばないので epoch はない 方法は下記 1 種類のみ a. MPI_Win_lock + MPI_Win_unlock, (MPI_Win_lock_all + MPI_Win_unlock_all)

88 Active target (collective synchronization) MPI_Win_fence を呼ぶ MPI_Win_fence は collective call である MPI_Win_fence と MPI_Win_fence の間が epoch になり 後ろの MPI_Win_fence がその間の通信を完了する 通信関数を呼ぶと origin なので access epoch と解釈される 通信関数を呼ばない場合は exposure epoch と解釈される コミュニケータ内の全プロセスが全ウィンドウにアクセス可能 通信相手の数が多く しかも頻繁に変わる場合に使う origin process target process MPI_Win_fence MPI_Win_fence access epoch MPI_Put MPI_Get buffer buffer window exposure epoch MPI_Win_fence MPI_Win_fence 87

89 Active target (restricted synchronization) origin 側は MPI_Win_start/MPI_Win_complete target 側は MPI_Win_post/MPI_Win_wait を呼ぶ 通信する相手は MPI_Win_start で group を指定する ウィンドウを公開する相手は MPI_Win_post で group を指定する target 側が post するまで通信は始まらない origin 側が complete した後 wait が復帰する (strong synchronization) バッファリングする実装ではこの制約は無い (weak synchronization) 通信相手の数が少なく しかも固定的な場合に使う origin process target process MPI_Win_start( group, ) MPI_Win_post( group, ) access epoch MPI_Put MPI_Get buffer buffer window exposure epoch MPI_Win_complete MPI_Win_wait *MPI_Win_test は MPI_Win_wait の非閉塞版 88

90 Passive target (lock synchronization) origin 側は MPI_Win_lock/MPI_Win_unlock または MPI_Win_lock_all/MPI_Win_unlock_all を呼ぶ 通信する相手は lock/unlock では rank のみ lock_all/unlock_all では win の全プロセス lock_all/unlock_all は collective call ではない Target 側のウィンドウを複数のプロセスが共用する場合は type = MPI_LOCK_SHARED 1 つのプロセスが排他的 (atomic) に使用する場合は type = MPI_LOCK_EXCLUSIVE を指定する origin process MPI_Win_lock( type, rank, ) target process access epoch MPI_Put MPI_Get buffer buffer MPI_Win_unlock( rank, ) window 一般に flush は待ち状態の送受信を強制的に完了させる MPI_Win_flush は rank に対する送受信 MPI_Win_fllush_all は win 内の全送受信を origin, target の両側で完了させる MPI_Win_flush_local, MPI_Win_flush_local_all は origin 側のみ完了させる MPI_Win_sync はウィンドウを整合化し epoch を仕切りなおす 89

91 90 MPI 関数各論 1. 集団通信 2. 要素通信 3. 片側通信 4. マルチスレッド 5. 派生データ型 6. ファイル I/O 7. コミュニケータ トポロジー 8. プロセス生成 9. その他

92 91 マルチスレッド時の MPI 関数実行 MPI ではマルチスレッド時の実行に関して低い順に以下の 4 つのレベルが設定されている 実行環境により設定可能なレベルは異なる MPI_THREAD_SINGLE シングルスレッド時のみ実行可能 MPI_THREAD_FUNNELED マルチスレッド時はマスタースレッドのみ実行可能 MPI_THREAD_SERIALIZED マルチスレッド時は同時に一つのスレッドのみ実行可能 * MPI_THREAD_MULTIPLE マルチスレッド時も制約なしにどのスレッドも実行可能 * スレッド間の排他制御はユーザの責任

93 レベル指定付き初期化 Function prototype int MPI_Init_thread( int *argc, char ***argv, int required, int *provided ) Example (thread01.c) int provided; MPI_Init_thread( argc, argv, MPI_THREAD_MULTIPLE, &provided ); if( provided!=mpi_thread_multiple ) printf( MPI_THREAD_MULTIPLE is not supported! n ); 注 :MPI_Init 同様 argc, argv は省略可能 required はプロセス毎に異なる値でも可 問い合わせ関数 Function prototype int MPI_Query_thread( int *provided ) int MPI_Is_thread_main( int *flag ) Example (thread02.c) int provided, flag; MPI_Query_thread( &provided ); if( provided!=mpi_thread_multiple ) printf( MPI_THREAD_MULTIPLE is not supported! n ); MPI_Is_thread_main( &flag ); if( flag ) printf( I am master thread! n ); 92

94 スレッド共有記憶の設定 Function prototype int MPI_Win_allocate_shared( MPI_Aint size, int disp_unit, MPI_Info info, MPI_Comm comm, void *baseptr, MPI_Win win ) comm のプロセスが共有する size バイトのメモリウィンドウ win を割当てそのポインタを baseptr に返す Function prototype int MPI_Win_shared_query( MPI_Win win, int rank, MPI_Aint size, int disp_unit, void *baseptr ) MPI_Win_allocate_shared で割当てたメモリウィンドウの情報を返す Example (-----.c) MPI_Comm oldcomm, newcomm; MPI_Info info = MPI_INFO_NULL; int type = MPI_COMM_TYPE_SHARED; int key = ; MPI_Comm_split_type( oldcomm, type, key, info, newcomm ); 93

95 スレッド共有記憶の設定 Function prototype int MPI_Comm_split_type( MPI_Comm comm, int split_type, int key, MPI_Info info, MPI_Comm newcomm ) 共有記憶領域毎に分離したコミュニケータを生成 Example (-----.c) MPI_Comm oldcomm, newcomm; MPI_Info info = MPI_INFO_NULL; int type = MPI_COMM_TYPE_SHARED; int key = ; MPI_Comm_split_type( oldcomm, type, key, info, newcomm ); MPI_Comm_create_group ( comm, group, tag, *newcomm ) comm はイントラのみ group 内で collective call tag はマルチスレッド実行の時に使う 94

96 MPI_Mprobe/MPI_Mrecv /MPI_Improbe/MPI_Imrecv 複数のスレッドが MPI_Probe を実行した時 タイミングによって後続の MPI_Recv がデータを取り違える可能性がある MPI_THREAD_MULTIPLE 環境では thread safe な MPI_Mprobe と MPI_Mrecv (Matching Probe/Recv) を使う MPI_Improbe と MPI_Imrecv はその非閉塞バージョン Probe と Recv は閉塞と非閉塞を組み合わせてもよい Function prototype int MPI_Mprobe( int source, int tag, MPI_Comm comm, MPI_Message *message, MPI_Status *status ) int MPI_Mrecv( void *buf, int count, MPI_Datatype datatype, MPI_Message *message, MPI_Status *status ) int MPI_Improbe( int source, int tag, MPI_Comm comm, int *flag, MPI_Message *message, MPI_Status *status ) int MPI_Imrecv( void *buf, int count, MPI_Datatype datatype, MPI_Message *message, MPI_Request *request ) 注 :MPI_Improbe の引数には request が無い (Wait/Test 不要 ) 代わりに flag がある ( 受信可能なデータの有無 ) また MPI_Imrecv の引数には status が無い (Wait/Test で取得 ) 95

97 Example (mprobe.c) int *rbuf; int count; MPI_Status status; MPI_Message message; if( master ) { MPI_Mprobe( MPI_ANY_SOURCE, MPI_ANY_TAG, MPI_COMM_WORLD, &message, &status ); MPI_Get_count( &status, MPI_INT, &count ); MPI_Alloc_mem( count*sizdof(int), MPI_INFO_NULL, rbuf ); MPI_Mrecv( rbuf, count, MPI_INT, &message, MPI_STATUS_IGNORE ); } Example (improbe.c) int *rbuf; int count, flag; MPI_Status status; MPI_Message message; MPI_Request request; if( master ) { MPI_Improbe( MPI_ANY_SOURCE, MPI_ANY_TAG, MPI_COMM_WORLD, &flag, &message, &status ); if(!flag ) continue; MPI_Get_count( &status, MPI_INT, &count ); MPI_Alloc_mem( count*sizdof(int), MPI_INFO_NULL, rbuf ); MPI_Imrecv( rbuf, count, MPI_INT, &message, &request ); MPI_Wait( &request, MPI_STATUS_IGNORE ); } 96

98 97 MPI 関数各論 1. 集団通信 2. 要素通信 3. 片側通信 4. マルチスレッド 5. 派生データ型 6. ファイル I/O 7. コミュニケータ トポロジー 8. プロセス生成 9. その他

99 98 派生データ型とは 注意点 基本型を組み合わせてユーザが定義する構造を持ったデータ型 ギャップを挟んだデータや複数の型をメンバーにもつ構造体なども定義できる さらに派生データ型を組み合わせた派生データ型も定義可能 関数名に一部整合的でないものが存在する ( 動詞 Create が欠けている ) 長さの指定が要素数の場合とバイト数の場合がある ギャップを間引いて圧縮したい場合は MPI_Pack で圧縮し MPI_Unpack で復元する

100 派生データ型関数一覧 Definition Elements MPI_Type_contiguous MPI_Type_vector MPI_Type_create_indexed_block MPI_Type_indexed MPI_Type_create_struct MPI_Type_create_subarray* MPI_Type_create_darray* MPI_Type_create_resized* Bytes MPI_Type_create_hvector MPI_Type_create_hindexed_block MPI_Type_create_hindexed management MPI_Type_commit MPI_Type_free MPI_Type_dup* MPI_Get_address* * MPI_Type_create_subarray, MPI_Type_create_darray はファイル I/O で説明する MPI_Type_create_resized, MPI_Type_dup, MPI_Get_address の説明は省略 99

101 派生データ型関数一覧 ( 続 ) Information int/aint MPI_Type_size MPI_Type_get_extent* MPI_Type_get_true_extent* MPI_Type_get_elements* MPI_Type_get_envelope* MPI_Type_get_contents* MPI_Count MPI_Type_size_x* MPI_Type_get_extent_x* MPI_Type_get_true_extent_x* MPI_Type_get_elements_x* Pack/Unpack Deposit MPI_Pack MPI_Pack_size MPI_Pack_external* MPI_Pack_external_size* MPI_Unpack Withdrawal MPI_Unpack_external* * MPI_Type_size, MPI_Pack, MPI_Unpack, MPI_Pack_size 以外の説明は省略 100

102 101 MPI_Type_contiguous Function prototype int MPI_Type_contiguous( int count, MPI_Datatype oldtype, MPI_Datatype *newtype ) Example (-----.c) MPI_Datatype newtype; MPI_Type_contigous(4, MPI_INT, &newtype); oldtype のデータを count 個連接した型を定義する newtype = int int int int

103 102 MPI_Type_vector/MPI_Type_create_hvector Function prototype int MPI_Type_vector(int count, int blocklength, int stride, MPI_Datatype oldtype, MPI_Datatype *newtype) int MPI_Type_create_hvector(int count, int blocklength, MPI_Aint stride, MPI_Datatype oldtype, MPI_Datatype *newtype) Example (-----.c) MPI_Datatype newtype; MPI_Type_vector(3, 2, 4, MPI_INT, &newtype); 連続する blocklengh 個のデータを count 回繰り返す ブロック間の距離は stride で指定する stride の単位は vector は要素数 hvector はバイト数 (h は heterogeneous の頭文字 ) stride newtype = int int int int int int int int int int blocklength count

104 103 MPI_Type_create_indexed_block /MPI_Type_create_hindexed_block Function prototype int MPI_Type_create_indexed_block(int count, int blocklength, const int array_of_displacements[], MPI_Datatype oldtype, MPI_Datatype *newtype) int MPI_Type_create_hindexed_block(int count, int blocklength, const MPI_Aint array_of_displacements[], MPI_Datatype oldtype, MPI_Datatype *newtype) Example (-----.c) MPI_Datatype newtype; const int displacements = {4,3,0}; MPI_Type_indexed_block(3, 2, displacements, MPI_INT, &newtype); MPI_Type_vector で stride の指定を可変にしたもの array_of_displacements の単位は indexed_block は要素数 hindexed_block はバイト数 displacements[0] displacements[1] newtype = int int int int int int int int int blocklength count

105 104 MPI_Type_indexed/MPI_Type_create_hindexed Function prototype int MPI_Type_indexed(int count, const int array_of_blocklengths[], const int array_of_displacements[], MPI_Datatype oldtype, MPI_Datatype *newtype) int MPI_Type_create_hindexed(int count, const int array_of_blocklengths[], const MPI_Aint array_of_displacements[], MPI_Datatype oldtype, MPI_Datatype *newtype) Example (-----.c) MPI_Datatype newtype; const int blocklengths = {2,1,3}; const int displacements = {4,3,0}; MPI_Type_indexed(3, blocklengths, displacements, MPI_INT, &newtype); MPI_Type_vector で blocklengh, stride の指定を可変にしたもの array_of_displacements の単位は indexed は要素数 hindexed はバイト数 displacements[0] displacements[1] newtype = int int int int int int int int int int blocklengths[0] blocklengths[1] blocklengths[2] count

106 105 MPI_Type_create_struct Function prototype int MPI_Type_create_struct(int count, const int array_of_blocklengths[], const MPI_Aint array_of_displacements[], MPI_Datatype array_of_types[], MPI_Datatype *newtype) Example (-----.c) MPI_Datatype newtype; const int blocklengths = {2,1,3}; const int displacements = {16,24,0}; MPI_Datatype types = {MPI_INT, MPI_FLOAT, MPI_CHAR}; MPI_Type_indexed(3, blocklengths, displacements, types, &newtype); MPI_Type_vector で blocklengh, stride, oldtype の指定を可変にしたもの array_of_displacements の単位はバイト数 displacements[0] displacements[1] newtype = int int float char char char blocklengths[0] blocklengths[1] blocklengths[2] count

107 106 MPI_Type_commit Function prototype int MPI_Type_commit(MPI_Datatype *datatype) Example (-----.c) MPI_Datatype newtype; MPI_Type_commit(&newtype); 派生データ型を通信に使えるよう有効化する MPI_Type_free Function prototype int MPI_Type_free(MPI_Datatype *datatype) Example (-----.c) MPI_Datatype newtype; MPI_Type_free(&newtype); 派生データ型を解放する (deallocate する )

108 MPI_Pack Function prototype int MPI_Pack(const void *inbuf, int incount, MPI_Datatype datatype, void *outbuf, int outsize, int *position, MPI_Comm comm) inbuf から始まる incount 個の datatype 型データを outbuf から始まる長さ outsize のバッファに push した後にカレントポインタ position を返す Example (-----.c) float in0[2] = {0.1, 0.2}; int in1[3] = {11, 12, 13}; int position = 0; char out[1000]; MPI_Comm comm = MPI_COMM_WORLD; MPI_Pack(in0, 2, MPI_FLOAT, out, 1000, &position, comm); MPI_Pack(in1, 3, MPI_INT, out, 1000, &position, comm); MPI_Send(out, position, MPI_PACKED, 1, 9, MPI_COMM_WORLD); inbuf = float float inbuf = int int int incount outbuf = float float int int int incount 1000 bytes position position position 107

109 MPI_Unpack Function prototype int MPI_Unpack(const void *inbuf, int insize, int *position, void *outbuf, int outcount, MPI_Datatype datatype, MPI_Comm comm) inbuf から始まる長さ insize のバッファのカレントポインタ position から outcount 個の datatype 型データを pop して outbuf に格納する Example (-----.c) MPI_recv の recvsize が position でないことに注意 float out0[2]; int out1[3]; int position = 0; char in[1000]; MPI_Comm comm = MPI_COMM_WORLD; MPI_Recv(in, 1000, MPI_PACKED, 0, 9, comm, MPI_STATUS_IGNORE); MPI_Pack(in, 1000, &position, out0, 2, MPI_FLOAT, comm); MPI_Pack(in, 1000, &position, out1, 3, MPI_INT, comm); inbuf = float float int int outbuf = float float int 1000 bytes position position position outbuf = int int int outcount outcount 108

110 109 MPI_Type_size Function prototype int MPI_Type_size(MPI_Datatype datatype, int *size) Example (-----.c) MPI_Datatype mytype; int size; MPI_Type_size(mytype, &size); datatype 型の大きさをバイト数で size に返す MPI_Pack_size Function prototype int MPI_Pack_size(int incount, MPI_Datatype datatype, MPI_Comm comm, int *size) Example (-----.c) MPI_Datatype mytype; int size; MPI_Pack_size(10, mytype, MPI_COMM_WORLD, &size); incount 個の datatype 型データを pack するために必要なバイト数を size に返す

111 110 MPI 関数各論 1. 集団通信 2. 要素通信 3. 片側通信 4. マルチスレッド 5. 派生データ型 6. ファイル I/O 7. コミュニケータ トポロジー 8. プロセス生成 9. その他

112 MPI_I/O を用いない場合 (POSIX) a. 書式付き #define BUFSIZE 100 int main( int argc, char *argv[] ) { int rank, buf[bufsize]; char fname[128]; MPI_Init( &argc, &argv ); MPI_Comm_rank( MPI_COMM_WORLD, &rank ); sprintf( fname, myfile%.4d, rank ); b. 書式無し #define BUFSIZE 100 int main( int argc, char *argv[] ) { int rank, buf[bufsize]; char fname[128]; MPI_Init( &argc, &argv ); MPI_Comm_rank( MPI_COMM_WORLD, &rank ); sprintf( fname, myfile%.4d, rank ); } FILE *fp = fopen( fname, w ); for( int i=0; i<bufsize; ++i ) fprintf( %d n, buf[i], fp ); fclose( fp ); MPI_Finalize(); return 0; } FILE *fp = fopen( fname, wb ); fwrite( buf, sizeof(int), BUFSIZE, fp ); fclose( fp ); MPI_Finalize(); return 0; プロセス毎にファイルを作る分離ファイル (separate files) 書式付き (formatted) と書式無し (unformatted) が可能 書式付きはテキストエディターで読書き可能で便利だが書式変換とループ文が必要なためオーバーヘッドが大きい 111

113 112 MPI_I/O を用いる場合 c. 書式無し分離ファイル #define BUFSIZE 100 int main( int argc, char *argv[] ) { int rank, buf[bufsize]; char fname[128]; MPI_Init( &argc, &argv ); MPI_Comm_rank( MPI_COMM_WORLD, &rank ); sprintf( fname, myfile%.4d, rank ); // myfile0000, myfile0001, myfile0002 MPI_File fp; MPI_File_open( MPI_COMM_SELF, fname, MPI_MODE_WRONLY MPI_MODE_CREATE, MPI_INFO_NULL, &fp ); MPI_File_write( fp, buf, BUFSIZE, MPI_INT, MPI_STATUS_IGNORE ); MPI_File_close( fp ); } MPI_Finalize(); return 0; 書式無し (unformatted file) のみ可能

114 113 d. 書式無し共通ファイル (common file) #define BUFSIZE 100 int main( int argc, char *argv[] ) { int rank, buf[bufsize]; char fname[128]; MPI_Init( &argc, &argv ); sprintf( fname, myfile, rank ); // myfile only MPI_File fp; MPI_File_open( MPI_COMM_WORLD, fname, MPI_MODE_WRONLY MPI_MODE_CREATE, MPI_INFO_NULL, &fp ); MPI_File_seek( fp, rank*bufsize, MPI_SEEK_SET ); MPI_File_write( fp, buf, BUFSIZE, MPI_INT, MPI_STATUS_IGNORE ); MPI_File_close( fp ); } MPI_Finalize(); return 0; コミュニケータ内に 1 つだけファイルを作る 書式無し (unformatted file) のみ可能

115 114 File I/O MPI_File_open, MPI_File_close, MPI_File_delete, MPI_File_preallocate, MPI_File_set_view, MPI_File_get_view, MPI_File_set_size, MPI_File_get_size, MPI_File_set_info, MPI_File_get_into, MPI_File_set_atomicity, MPI_File_get_atomicity, MPI_File_seek, MPI_File_seek_shared, MPI_File_get_position, MPI_File_get_position_shared, MPI_File_get_byte_offset, MPI_File_get_type_extent, MPI_Register_datarep, MPI_File_get_group, MPI_File_get_amode, MPI_File_sync,

116 データアクセス関数 Read Write Blocking MPI_File_read MPI_File_read_at MPI_File_read_shared MPI_File_read_all MPI_File_read_at_all MPI_File_read_ordered MPI_File_write MPI_File_write_at MPI_File_write_shared MPI_File_write_all MPI_File_write_at_all MPI_File_write_ordered Nonblocking MPI_File_iread MPI_File_iread_at MPI_File_iread_shared MPI_File_read_all_begin/end MPI_File_read_at_all_begin/end MPI_File_read_ordered_begin/end MPI_File_iwrite MPI_File_iwrite_at MPI_File_iwrite_shared MPI_File_write_all_begin/end MPI_File_write_at_all_begin/end MPI_File_write_ordered_begin/end 個別ファイルポインタ (individual file pointer) 陽的オフセット (explicit offset) 共有ファイルポインタ (shared file pointer) 独立 I/O(independent I/O) 集団 I/O(collective I/O) 分割集団 I/O(split collective I/O) 115

117 116 個別ファイルポインタ プロセス毎に持つファイルポインタからの相対位置で読書き 陽的オフセットファイルポインタを用いず直接位置を指定して読書き 共有ファイルポインタコミュニケータで共有する1つのファイルポインタから相対位置で読書き 独立 I/O: コミュニケータ内の任意のプロセスが呼び出せる関数集団 I/O: コミュニケータ内の全プロセスが呼ばなければならない関数分割集団 I/O: 非閉塞の集団 I/Oは wait, test ではなく end で完了する * 独立 I/O よりも集団 I/O の方が読書きが速い ( 数十倍速いことも少なくない )

118 117 MPI_Type_create_subarray Function prototype int MPI_Type_create_subarray(int ndims, const int array_of_sizes[], const int array_of_subsizes[], const int array_of_starts[], int order, MPI_Datatype oldtype, MPI_Datatype *newtype) Example (-----.c) MPI_Datatype newtype; const int sizes = {100, 100}; const int subsizes = {25, 25}; const int starts = {20, 40}; MPI_Type_create_subarray(2, sizes, subsizes, starts, MPI_ORDER_C, MPI_INT, &newtype); ファイル I/O で filetype に指定し 配列全体の一部だけ読み書きするために用いる

119 118 MPI 関数各論 1. 集団通信 2. 要素通信 3. 片側通信 4. マルチスレッド 5. 派生データ型 6. ファイル I/O 7. コミュニケータ トポロジー 8. プロセス生成 9. その他

120 119 グループ コミュニケータ トポロジーの関係 イントラ コミュニケータグループ ranks = {0, 1, 2,, n-1} コンテキストアトリビュート インター コミュニケータグループ ranks = {0, 1, 2,, n-1} グループ ranks = {0, 1, 2,, m-1} コンテキストアトリビュート コミュニケータには 2 種類ある イントラ コミュニケータはグループを 1 つ持つ インター コミュニケータはグループを 2 つ持つ グループはランク番号の単純集合 コンテキストは通信範囲を限定する機能を持つ アトリビュートはユーザによって与えられる情報 トポロジーは 1 つのイントラ コミュニケータと仮想トポロジーから構成される 仮想トポロジーはアトリビュートの一種でノード間の結合や重みなどの高次情報 トポロジー イントラ コミュニケータ グループ ranks = {0, 1, 2,, n-1} コンテキスト アトリビュート 仮想トポロジー

121 グループの編集 MPI_Comm_group( comm, *group ) コミュニケータ comm からグループ group を返す comm がインター コミュニケータの場合は local group の group を返す MPI_Group_size( group, *size ) group の要素数を返す MPI_Group_rank( group, *rank ) 自プロセスの rank 番号を返す 存在しない場合は MPI_UNDEFINED を返す MPI_Group_compare( group1, group2, *result ) group1 と group2 を比較する, 完全に同じ場合は result に MPI_IDENT, 順序だけ異なる場合は MPI_SIMILAR, その他は MPI_UNEQUAL を返す MPI_Group_translate _ranks( group1, n, ranks1[ ], group2, *ranks2[ ] ) group1 の ranks1[i] 番のプロセスが group2 では何番に対応するかを rank2[i] に返す 対応するものがなければ M MPI_UNDEFINED を返す MPI_Group_free( *group ) group に MPI_GROUP_NULL を代入し無効にする * MPI_Comm_group と MPI_Group_xxx は全て non-collective 120

122 グループの編集 ( 続 ) group1 = {0, 1, 2, 3, 4, 5}, group2 = {2, 4, 6, 8,10} ユーザが新規にグループを定義することはできない 既存のコミュニケータから抽出したグループを編集する MPI_Group_union( group1, group2, *newgroup ) MPI_Group_intersection( group1, group2, *newgroup ) MPI_Group_difference( group1, group2, *newgroup ) *newgroup = {0, 1, 2, 3, 4, 5, 6, 8,10} *newgroup = {2, 4} *newgroup = {0, 1, 3, 5} group 1 group 2 group 1 group 2 group 1 group 2 MPI_Group_union *newgroup MPI_Group_intersection *newgroup MPI_Group_difference *newgroup * 空集合の場合は MPI_GROUP_EMPTY が返される 121

123 グループの編集 ( 続 ) group = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12}, ranks = {1, 3, 6, 9,12} MPI_Group_incl( group, 5, ranks, *newgroup ) MPI_Group_excl( group, 5, ranks, *newgroup ) ranks の要素が group の要素に無い時はエラーになる incl は group から ranks で指定したランクを抜き出す excl は group から ranks で指定したランクを削除する incl と excl の和集合は group になる group = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12}, ranges = {0, 7, 2, 8,12, 3} *newgroup = {1, 3, 6, 9,12} *newgroup = {0, 2, 4, 5, 7, 8,10,11} (0,7,2) (8,12,3) MPI_Group_range_incl( group, 2, ranges, *newgroup ) MPI_Group_range_excl( group, 2, ranges, *newgroup ) *newgroup = {0, 2, 4, 6, 8,11} *newgroup = {1, 3, 5, 7, 9,10,12} ranges は (first, last, stride) の組の繰り返し上の例では (0,7,2) と (8,12,3) の 2 組 各組は first から last まで stride おきの番号を指定する 指定された番号が group の要素に無い時はエラーになる range_incl は group から指定された番号を抜き出す range_excl は group から指定された番号を削除する range_incl と range_excl の和集合は group になる 122

124 123 コミュニケータの編集 MPI_Comm_size( comm, *size ) comm の要素数を返す comm がインター コミュニケータの場合は local group の要素数を返す comm 内で non-collective call MPI_Comm_rank( comm, *rank ) 自プロセスの rank 番号を返す comm がインター コミュニケータの場合は local group 内の rank 番号を返す comm 内で non-collective call MPI_Comm_compare( comm1, comm2, *result ) comm1 と comm2 を比較し, 完全に一致する場合は MPI_IDENT, ランク番号の順序だけ異なる場合は MPI_SIMILAR, context だけ異なる場合は MPI_CONGRUENT, その他は MPI_UNEQUAL を result に返す comm 内で non-collective call

125 124 コミュニケータの編集 ( 続 ) MPI_Comm_dup ( comm, *newcomm ) comm の複製を *newcomm に返す comm 内で collective call MPI_Comm_dup_with_info (comm, info, *newcomm ) comm を複製し info を上書きして *newcomm に返す comm 内で collective call MPI_Comm_idup ( comm, *newcomm, *request ) MPI_Comm_dup の非閉塞版 comm 内で collective call MPI_Comm_free( *comm ) comm に MPI_COMM_NULL を代入し無効にする MPI_COMM_WORLD には適用しない ( できない ) comm 内で collective call

126 コミュニケータの編集 ( 続 ) MPI_Comm_create( comm, group, *newcomm ) comm の部分集合 group のコミュニケータを作成し *newcomm に返す group に属さないプロセスには *newcomm に MPI_COMM_NULL を返す comm はイントラ インターどちらも可 *newcomm は comm と同種 comm の attribute は引き継がない comm 内で collective call インター コミュニケータ comm MPI_Comm_group group group group group sub-group *newcomm sub-group MPI_Comm_create sub-group MPI_Gtoup_incl etc. sub-group イントラ コミュニケータインター コミュニケータで group が 1 つの場合と同じ MPI_Comm_create_group ( comm, group, tag, *newcomm ) マルチスレッドの項で説明 125

127 コミュニケータの編集 ( 続 ) MPI_Comm_split ( comm, color, key, *newcomm ) color 毎に comm の部分コミュニケータを同名で作成し *newcomm に返す ランク番号は key の値が小さいものから 0, 1, 2, の順に付けられる color=mpi_undefined と指定すると *newcomm には MPI_COMM_NULL を返す comm 内で collective call インター コミュニケータの場合 comm group group (red,1) (red,2) (red,0) (red,2) (blue,1) (blue,3) (blue,1) MPI_Comm_split rank=0 *newcomm group group rank=1 rank=0 rank=1 + *newcomm group group (color,key) rank=0 rank=1 rank=0 イントラ コミュニケータの場合インター コミュニケータで group が 1 つに同じ MPI_Comm_split_type ( comm, color, key, *newcomm ) マルチスレッドの項で説明 126

128 127 インター コミュニケータの編集 MPI_Comm_test_inter ( comm, *flag ) comm がインター コミュニケータであれば flag に true を返す comm 内で non-collective call MPI_Comm_remote_size ( comm, *size ) remote group の size を返す comm 内で non-collective call MPI_Comm_remote_group ( comm, *group ) remote group を返す comm 内で non-collective call MPI_Intercomm_merge ( intercomm, high, *newintracomm ) intercomm をイントラ コミュニケータに変換して *newintracomm に返す high=false の group から昇順にランク番号を付ける intercomm 内で collective call

129 128 インター コミュニケータの編集 ( 続 ) MPI_Intercomm_create ( local_comm, local_leader, peer_comm, remote_leader, tag, *newintercomm ) local_comm と remote_leader が属するコミュニケータからインター コミュニケータを生成し *newintercomm に返す 両方のコミュニケータに属するプロセスが存在してはならない (disjoint communicators) peer_comm は local_comm と remote_comm を包含するコミュニケータ local_leader は local_comm 内のランク番号 remote_leader は peer_comm 内のランク番号 local_comm と peer_comm 内で collective call peer_comm local_comm remote_comm group group MPI_Intercomm_create peer_comm *newintercomm group group peer_comm intercomm group group MPI_Intercomm_merge peer_comm *newintracomm group

130 129 インター コミュニケータの作成例 MPI_COMM_WORLD からイントラ コミュニケータを 2 つ (Fluid,Solid) 作る 各々のコミュニケータ内でランク番号が設定される (F0, F1, F2, S0, S1, S2, S3) Fluid と Solid からインター コミュニケータ Aircraft を作る Fluid MPI_COMM_WORLD Aircraft Solid P0,F0 P4,S0 P6,S2 P1,F1 P2,F2 P5,S1 P7,S3 P3

131 Example (intercomm.c) int main( int argc, char *argv[] ) { int rank, size; MPI_Init( &argc, &argv ); MPI_Comm_size( MPI_COMM_WORLD, &size ); MPI_Comm_rank( MPI_COMM_WORLD, &rank ); MPI_Group MPI_GROUP_WORLD, fgroup, sgroup; MPI_Comm_group( MPI_COMM_WORLD, &MPI_GROUP_WORLD ); int franks[3] = { 0, 1, 2 }; int sranks[4] = { 4, 5, 6, 7 }; MPI_Group_incl( MPI_GROUP_WORLD, 3, franks, &fgroup ); MPI_Group_incl( MPI_GROUP_WORLD, 4, sranks, &sgroup ); MPI_Comm Fluid, Solid, Aircraft; MPI_Comm_create( MPI_COMM_WORLD, fgroup, &Fluid ); MPI_Comm_create( MPI_COMM_WORLD, sgroup, &Solid ); WORLD から部分集合のグループを 2 つ作る それぞれのグループからコミュニケータを生成する } if( fcomm!=mpi_comm_null ) { const int fleader = 0; const int sleader = 4; MPI_Intercomm_create( Fluid, fleader, MPI_COMM_WORLD, sleader, 0, &Aircraft ); } if( scomm!=mpi_comm_null ) { 2つのコミュニケータから const int sleader = 0; インター コミュニケータを生成する const int fleader = 0; MPI_Intercomm_create( Solid, sleader, MPI_COMM_WORLD, fleader, 0, &Aircraft ); } MPI_Finalize(); return 0; 130

132 131 インター通信 (Inter-communication) 2つのgroup 間で通信する 集団通信では MPI_IN_PLACE は使えない 要素通信では dest, source に remote の rank を指定 片側通信はインター通信できない

133 132 MPI_Bcast Fluid のプロセス 1 から Solid に Bcast する場合 comm=aircraft に設定する root を以下のよう設定する F0: root = MPI_PROC_NULL F1: root = MPI_ROOT F2: root = MPI_PROC_NULL S0: root = 1 S1: root = 1 S2: root = 1 S3: root = 1 Fluid MPI_COMM_WORLD Aircraft Solid P0,F0 P4,S0 P6,S2 P1,F1 P2,F2 P5,S1 P7,S3 P3

134 133 MPI_Scatter/MPI_Scatterv comm=aircraft に設定する root を以下のよう設定する F0: root = MPI_PROC_NULL F1: root = MPI_ROOT F2: root = MPI_PROC_NULL Fluid のプロセス 1 の値が分割され Solid の全プロセスに格納 通信は Bcast と同方向 S0: root = 1 S1: root = 1 S2: root = 1 S3: root = 1 Fluid MPI_COMM_WORLD Aircraft Solid P0,F0 P4,S0 P6,S2 P1,F1 P2,F2 P5,S1 P7,S3 P3

135 134 MPI_Gather/MPI_Gatherv/MPI_Reduce comm=aircraft に設定する root を以下のよう設定する F0: root = MPI_PROC_NULL F1: root = MPI_ROOT F2: root = MPI_PROC_NULL Solid 内の全プロセスの値が集められ Fluid のプロセス 1 に格納 通信は Bcast と逆方向 MPI_COMM_WORLD S0: root = 1 S1: root = 1 S2: root = 1 S3: root = 1 Fluid Aircraft Solid P0,F0 P4,S0 P6,S2 P1,F1 P2,F2 P5,S1 P7,S3 P3

136 135 MPI_Allgather/MPI_Allgatherv/MPI_Allreduce comm=aircraftに設定する rootは設定不要 Solid 内の全プロセスの値が集められFluidの各プロセスに格納 Fluid 内の全プロセスの値が集められSolidの各プロセスに格納 通信は双方向のAllgather! sendcount=0にすると単方向のallgatherになる MPI_COMM_WORLD Fluid Aircraft Solid P0,F0 P4,S0 P6,S2 P1,F1 P2,F2 P5,S1 P7,S3 P3

137 136 MPI_Alltoall/MPI_Alltoallv/MPI_Alltoallw comm=aircraftに設定する rootは設定不要 Solid 内の全プロセスの値が分割されFluidの各プロセスに連結格納 Fluid 内の全プロセスの値が分割されSolidの各プロセスに連結格納 通信は双方向のAlltoall! sendcount=0にすると単方向のalltoallになる MPI_COMM_WORLD Fluid Aircraft Solid P0,F0 P4,S0 P6,S2 P1,F1 P2,F2 P5,S1 P7,S3 P3

138 137 MPI_Reduce_scatter_block/MPI_Reduce_scatter comm=aircraftに設定する rootは設定不要 Solid 内の全プロセスの値が総和されFluidの各プロセスに分割格納 Fluid 内の全プロセスの値が総和されSolidの各プロセスに分割格納 通信は双方向のReduce_scatter! MPI_Barrier comm=aircraftに設定する Solid 内の全プロセスがコールまでFluidのプロセスは待機 Fluid 内の全プロセスがコールまでSolidのプロセスは待機 非閉塞通信の動作 使用方法も完了手順を除いて閉塞通信と同じ

139 138 Topology MPI_Cart_create, MPI_Dims_create, MPI_Cartdim_get, MPI_Cart_get, MPI_Cart_rank, MPI_Cart_coords, MPI_Cart_shift, MPI_Cart_sub, MPI_Cart_map, MPI_Graph_create, MPI_Topo_test, MPI_Graphdims_get, MPI_Graph_get, MPI_Graph_neighbors_count, MPI_Graph_neighbors, MPI_Graph_map, MPI_Dist_graph_create_adjacent, MPI_Dist_graph_create, MPI_Dist_graph_neighbors_count, MPI_Dist_graph_neighbors, MPI_Neighbor_allgather, MPI_Neighbor_allgatherv, MPI_Neighbor_alltoall, MPI_Neighbor_alltoallv, MPI_Neighbor_alltoallw, MPI_Ineighbor_allgather, MPI_Ineighbor_allgatherv, MPI_Ineighbor_alltoall, MPI_Ineighbor_alltoallv, MPI_Ineighbor_alltoallw, Inter-communication はできない

140 139 MPI 関数各論 1. 集団通信 2. 要素通信 3. 片側通信 4. マルチスレッド 5. 派生データ型 6. ファイル I/O 7. コミュニケータ トポロジー 8. プロセス生成 9. その他

141 140 プロセス生成とは 注意点 MPI プログラム実行中 動的にプロセスを生成可能 Unix の fork に似た機能 生成したプロセス上で任意のプログラムを実行可能 呼出し側プロセスはインター コミュニケータの local に 生成されたプロセスは remote に置かれる コミュニケータを共有しないプロセス間にも socket のようなポートを設定することで通信可能 呼出し側は必ずイントラ コミュニケータ 生成しても MPI_COMM_WORLD は不変 ( インター コミュニケータに包含される ) ポートの動作は実装や環境に依存する (Ubuntu は不可?)

142 プロセス生成の例 最初 MPI_COMM_WORLD は 4 つのプロセスを持つとする MPI_Comm_spawn を使い comm 以外の引数を以下のように仮定する MPI_Comm_spawn ( command, *argv[], maxprocs, info, root, comm, *intercomm, errcode[] ) maxprocs 個のプロセスを生成し argv をオプションとして command を実行する 生成したプロセスを remote とするインター コミュニケータを inter_comm に返す command= worker プログラム名はworker argv[]=mpi_argv_null オプションは無し maxprocs=3 3つのプロセスを生成する info=mpi_info_null infoは無し root=0 rootはランク0 番とする errcode[]=mpi_errocodes_ignore エラーコードは無視する comm の値が MPI_COMM_WORLD か MPI_COMM_SELF かによって生成されるプロセスの構成が異なる MPI_Comm_spawn_multiple( ) MPI_Comm_spawn で command が複数の場合 command 毎に argv 等を設定する MPI_Comm_get_parent( *parent ) 親プロセス parent に返す MPI_Comm_join には Berkeley socket interface が必要なので説明は省略 141

143 142 Example (commspawn.c) #include <stdio.h> #include mpi.h int main( int argc, char *argv[] ) { int rank, size; MPI_Init( &argc, &argv ); MPI_Comm_size( MPI_COMM_WORLD, &size ); MPI_Comm_rank( MPI_COMM_WORLD, &rank ); MPI_Comm intercomm; MPI_Comm comm = MPI_COMM_SELF; // MPI_Comm comm = MPI_COMM_WORLD; プロセスを3つ生成し worker を実行 int maxprocs = 3, root = 0; MPI_Comm_spawn( worker, MPI_ARGV_NULL, maxprocs, MPI_INFO_NULL, root, comm, &intercomm, MPI_ERROCODES_IGNORE ); int wrank, wsize, rsize; MPI_Comm_size( intercomm, &wsize ); MPI_Comm_rank( intercomm, &wrank ); MPI_Comm_remote_size( intercomm, &rsize ); インター コミュニケータのサイズとランクを取得 Remote group のサイズを取得 } MPI_Finalize(); return 0;

144 143 Example (worker.c) #include <stdio.h> #include mpi.h int main( int argc, char *argv[] ) { MPI_Comm parent; int rank, size, rsize; MPI_Init( &argc, &argv ); MPI_Comm_get_parent( &parent ); MPI_Comm_remote_size( parent, &rsize ); MPI_Comm_size( MPI_COMM_WORLD, &size ); MPI_Comm_rank( MPI_COMM_WORLD, &rank ); 親プロセスを取得 親プロセスのサイズを取得 } MPI_Finalize(); return 0;

145 inter local remote local group は MPI_COMM_WORLD remote group は生成した 3 つのプロセス intercomm は 1 つ comm == MPI_COMM_WORLD inter remote inter remote local group は各プロセス (i.e. MPI_COMM_SELF) local local 各プロセスに 3 プロセスの remote group intercomm は 4 つ remote local local remote inter inter comm == MPI_COMM_SELF 最初の MPI_COMM_WORLD のプロセス 144

146 145 ポートを使ったプロセス間通信 MPI_Open_port, MPI_Close_port, MPI_Comm_accept, MPI_Comm_connect, MPI_Comm_disconnect, MPI_Publish_name, MPI_Unpublish_name, MPI_Lookup_name,

147 146 MPI 関数各論 1. 集団通信 2. 要素通信 3. 片側通信 4. マルチスレッド 5. 派生データ型 6. ファイル I/O 7. コミュニケータ トポロジー 8. プロセス生成 9. その他

148 Environmental バージョン ノード名 メモリ割当て 時刻 MPI プログラムの初期化 終了 スレッド MPI_Get_version, MPI_Get_library_version, MPI_Get_processor_name, MPI_Alloc_mem, MPI_Free_mem, MPI_Wtime, MPI_Wtick, MPI_Init, MPI_Init_thread*, MPI_Initialized, MPI_Finalize, MPI_Finalized, MPI_Abort, MPI_Query_thread*, MPI_Is_thread_main*, MPI_Get_version は整数 MPI_Get_library_version は文字列で返す MPI_Get_processor_name は Unix の hostname と同じ MPI_Alloc_mem, MPI_Free_mem は通常 malloc, free と同じだが最適化している場合もある MPI_Wtime は時刻 MPI_Wtick は時間単位 (= 測定精度 ) を返す * MPI_Init_thread, MPI_Query_thread, MPI_Is_thread_main はマルチスレッドで説明する 147

149 Info コミュニケータ ウィンドウ ファイル トポロジの関数引数に与える性能最適化のためのヒントを Info オブジェクトと呼ぶ 以下のような関数が利用可能 MPI_Info_create, MPI_Info_dup, MPI_Info_free, MPI_Info_set, MPI_Info_get, MPI_Info_get_valuelen, MPI_Info_get_nkeys, MPI_Info_get_nthkey, MPI_Info_delete, Info で利用可能な値は各ライブラリのユーザマニュアル等に記載されている Info オブジェクトを引数に取る関数 MPI_Comm_spawn, MPI_Comm_spawn_multiple, MPI_Comm_dup_with_info, MPI_Comm_accept, MPI_Comm_connect, MPI_Comm_open_port, MPI_Comm_lookup_name, MPI_Comm_publish_name, MPI_Comm_unpbulish_name, MPI_Comm_set_info, MPI_Comm_get_info, MPI_Dist_graph_create, MPI_Dist_graph_create_adjucent, MPI_Win_create, MPI_Win_allocate, MPI_Win_allocate_shared, MPI_Win_create_dynamic, MPI_Win_set_info, MPI_Win_get_info, MPI_File_open, MPI_File_delete, MPI_File_set_view, MPI_File_set_info, MPI_File_get_info, 148

150 Caching コミュニケータ ウィンドウ 派生データ型に Attribute と呼ばれる付加情報を持たせるために用いる トポロジはコミュニケータに Attribute を加えることで実現されている 以下のような関数が利用可能 MPI_Comm_create_keyval, MPI_Comm_free_keyval, MPI_Comm_set_attr, MPI_Comm_get_attr, MPI_Comm_delete_attr, MPI_Win_create_keyval, MPI_Win_free_keyval, MPI_Win_set_attr, MPI_Win_get_attr, MPI_Win_delete_attr, MPI_Type_create_keyval, MPI_Type_free_keyval, MPI_Type_set_attr, MPI_Type_get_attr, MPI_Type_delete_attr, create_keyval には以下のコールバック関数を指定する typedef int MPI_Comm_copy_attr_function( MPI_Comm oldcomm, int keyval, void val_in, void *val_out, int flag ); typedef int MPI_Win_copy_attr_function( MPI_Win oldwin, int keyval, void val_in, void *val_out, int flag ); typedef int MPI_Type_copy_attr_function( MPI_Datatype oldtype, int keyval, void val_in, void *val_out, int flag ); typedef int MPI_Comm_delete_attr_function( MPI_Comm comm, int keyval, void *val, void *state ); typedef int MPI_Win_delete_attr_function( MPI_Win win, int keyval, void *val, void *state ); typedef int MPI_Type_delete_attr_function( MPI_Datatype type, int keyval, void *val, void *state ); 149

151 150 Naming コミュニケータ ウィンドウ 派生データ型に文字列型の名前を持たせるために用いる 以下のような関数が利用可能 MPI_Comm_set_name, MPI_Comm_get_name, MPI_Win_set_name, MPI_Win_get_name, MPI_Type_set_name, MPI_Type_get_name,

152 Error handling コミュニケータ ウィンドウ ファイルにエラーハンドラを設定するために用いる 2 種類の定義済みハンドラ (MPI_ERROS_ARE_FATAL, MPI_ERRORS_RETURN) 既定のハンドラはコミュニーケータとウィンドウが MPI_ERROS_ARE_FATAL ファイルが MPI_ERRORS_RETURN ユーザ自身で独自のハンドラを定義することもできる 以下のような関数が利用可能 MPI_Comm_create_errhandler, MPI_Comm_set_errhandler, MPI_Comm_get_errhandler, MPI_Comm_call_errhandler, MPI_Win_create_errhandler, MPI_Win_set_errhandler, MPI_Win_get_errhandler, MPI_Win_call_errhandler, MPI_File_create_errhandler, MPI_File_set_errhandler, MPI_File_get_errhandler, MPI_File_call_errhandler, MPI_Error_class, MPI_Error_string, MPI_Add_error_class, MPI_Add_error_code, MPI_Add_error_string, MPI_Errhandler_free, 151

153 152 External interfaces ユーザ独自の非閉塞通信を定義するためのもの generalized request と status の振舞いを定義する 以下のような関数が利用可能 Generalized request: MPI_Grequest_start, MPI_Grequest_complete, Status: MPI_Status_set_elements, MPI_Status_set_elements_x, MPI_Status_set_cancelled,

154 153 Tool support Tool information interface: MPI_T_pvar_get_num, MPI_T_pvar_get_info, MPI_T_pvar_get_index, MPI_T_pvar_handle_alloc, MPI_T_pvar_handle_free, MPI_T_pvar_read, MPI_T_pvar_write, MPI_T_pvar_session_create, MPI_T_pvar_session_free, MPI_T_pvar_start, MPI_T_pvar_stop, MPI_T_pvar_reset, MPI_T_pvar_readreset, MPI_T_cvar_get_num, MPI_T_cvar_get_info, MPI_T_cvar_get_index, MPI_T_cvar_handle_alloc, MPI_T_cvar_handle_free, MPI_T_cvar_read, MPI_T_cvar_write, MPI_T_enum_get_info, MPI_T_enum_get_item, MPI_T_Init_thraed, MPI_T_finalize, MPI_T_category_get_num, MPI_T_category_get_info, MPI_T_category_get_cvars, MPI_T_category_get_pvars, MPI_T_category_get_categories, MPI_T_category_changed, Profiling interface: MPI_Pcontrol, Tool information interface は MPI_T_init_thread と MPI_T_finalize の間で呼べる MPI_Init の前や MPI_Finalize の後でも呼ぶことができる pvar は performance variables cvar は control variables の略 C のみ定義されている (Fortran では使用できない )

155 154 並列性能評価 1. 並列性能について 2. 通信性能について

156 スケーリング性能 1. Strong scaling (Amdahl s law) タスクを細分した場合の処理速度 (speedup) t=t 0 t=t 0 /4 t=t 0 /9 Gene M. Amdahl, Validity of the single processor approach to achieving large scale computing capabilities, AFIPS Conference Proceedings, (30), , Weak scaling (Gustafson s law) タスクを追加した場合の単位時間当たり処理量 (throughput) x-flops 4x-FLOPS 9x-FLOPS John L. Gustafson, Reevaluating Amdahl s law, Communication of the ACM, 31(5), ,

157 Amdahl s law 逐次処理時間の内で並列部分 ( 分割可能 ) を p 逐次部分を s とすると並列処理時間は下図のようになる s p 逐次処理 s p/n 逐次処理時間を並列処理時間で除した値を速度向上 (Speedup) 速度向上をプロセス数 N で除した値を効率 (Efficiency) と定義する S = 並列処理 s + p s + pτn = N α + 1 Nα + 1, E a = S N = α + 1 Nα + 1 十分な効率を得るには α は小さな値が必要 α = s p E a の例 N α

158 Gustafson s law 並列処理時間の内で比例部分 ( 並列可能 ) を p 定数部分を s とする もしこれを逐次処理した場合 処理時間は下図のようになる s p 並列処理 s Np 逐次処理時間を並列処理時間で除した値を処理向上 (throughput gain) 処理向上をプロセス数 N で除した値を効率 (Efficiency) と定義する G = 逐次処理 s + Np s + p = N 1 + α Τ N 1 + α, E g = G N = 1 + α Τ N 1 + α α = s p 比較的大きな α でも効率は良い値となる (c.f. α = Nα) E g の例 N α

159 158 実測時間を用いた性能評価 Strong scaling プロセス数 n と m の 2 点で評価する ( 但し n>m とする ) Amdahl s law に従うと仮定すると T n = s + この式を解いて pτn, T m = s + pτm, s = nt n mt m n m, p = nm T m T n n m 従って α = s p = nt n mt m n = Τ m T m Τ T n nm T m T n n T m ΤT n 1 効率と速度向上は α と n を用いて以下の式で表される T n はプロセス数 n の実測時間 E a = α + 1 nα + 1, S = ne a, 一般に m が n に近い程良い値になる m = 1 で評価できれば理想的

160 Weak scaling プロセス数 n と m の 2 点で評価する ( 但し n>m とする ) Gustafson s law に従い さらに s はプロセス数に比例すると仮定 T n = s + p, T m = m n s + p, T n はプロセス数 n の実行時間 この式を解いて 従って s = n T n T m n m, p = nt m mt n n m α = s p = n T n T m = 1 T m Τ T n nt m mt n T m ΤT n mτn 効率と処理向上は α と n を用いて以下の式で表される E g = 1 + α Τ n, G = ne 1 + α g, * Weak scaling の場合, s が通信, p が計算タスクを含むと考えるのが合理的である従って通信オーバーヘッド等プロセス数に依存するのは s と見做すべきあるが 解を得るには依存性に何らかの仮定が必要である 159

161 160 並列性能評価 1. 並列性能について 2. 通信性能について

162 レイテンシ (Latency) と帯域幅 (Band width) [msec] 典型的な通信性能 レイテンシ : 通信準備等に必要な固定時間帯域幅 : 定常的な通信速度のこと 時間 パケット長 レイテンシ (usec) 帯域幅 (GB/s) 通信時間はデータサイズが小さい時はレイテンシに律速され パケット長を超える辺りから帯域幅が効いてくる データサイズ ベンチマーク手法 [KB] Ping-pong 2 つのプロセス間で交互に送受信 Full-bisection 全プロセスの半分が送信 残りが受信 Exchange 全プロセスが隣接プロセスと送受信 Intel MPI Benchmark(IMB) MPI 関数の網羅的ベンチマークスイート 161

163 162 具体的な問題への応用 1. 構造格子系 ( 差分法 ) 2. 非構造格子系 ( 有限要素法, 有限体積法 ) 3. フーリエ変換 4. MPI Tips

164 163 2 次元差分法ヤコビ法によるポアソン方程式 ( φ = f) の解法 領域分割法 (Domain Decomposition) 計算格子全体を分割して各プロセスで分担 領域分割 全格子 (18x10 格子点 ) 境界のデータは隣接プロセスとの通信で取得 6 プロセスで領域分割部分格子は 6x5 格子点 差分計算に必要となる内部境界点 ( 赤色 ) は隣接プロセスと通信 外部境界 ( 青色 ) は境界条件を適用

165 164 ステンシル (Stencil) による通信パターンの違い 5 点差分 : w i,j = 1 4 φ i+1,j + φ i 1,j + φ i,j+1 + φ i,j 1 h 2 f i,j j + 1 j j 1 隣接する 4 つのプロセスと通信 i 1 i i 点差分 : w i,j = 1 8 ቀφ i+1,j + φ i 1,j + φ i,j+1 + φ i,j 1 ൯ +φ i+1,j+1 + φ i 1,j+1 + φ i+1,j 1 + φ i 1,j 1 3h 2 f i,j j + 1 j j 1 隣接する 8 つのプロセスと通信 i 1 i i + 1

166 165 5 点差分における MPI 通信のポイント カーテシアン トポロジ (MPI_Cart_create) を使う隣接プロセスの特定が容易なので間違う可能性が低いプロセスの物理的配置 (Affinity) をユーザ自身で最適化するのは困難だが ( インターコネクトの物理的形状や通信バンド幅等の知識が必要 ) ベンダー提供ライブラリでは最適化されている可能性がある注 :MPI_Dims_create の因数分解は ( 特に高次元で ) あまり賢くない ( 例 : 9=1x9 ) 派生データ型を使う派生データ型は一度定義しておけば Pack/Unpack の必要がなく便利ベンダーによっては特定ハードウェアに最適化している可能性がある注 : ベクトル化 マルチスレッド化した Pack/Unpack の方が速い場合もある 複合通信 (MPI_Send_recv) を使う複数の送受信の順序をユーザ自身で最適化するのは困難非閉塞通信も通信チャネル数や帯域幅が十分でないと無駄な待ちが発生する多プロセス数のシフト通信 ( 一斉に隣に送る ) では特に効果的注 : 閉塞通信なので通信の隠蔽はできない

167 5 点差分 ( 通信隠蔽無し ) 1. コミュニケータ (cart2d) の定義 jacobi2d5p.c 16 // define a cartesian topology 17 MPI_Comm cart2d; 18 int ndims = 2; プロセス配置は2 次元 19 int reorder = true; プロセス並替えを許可 20 int dims[2] = { 0, 0 }; 21 int periods[2] = { false, false }; 境界は非周期 22 int east, west, north, south; 23 MPI_Dims_create( size, ndims, dims ); sizeを因数分解した値をdimsに返す 24 MPI_Cart_create( basecomm, ndims, dims, periods, reorder, &cart2d ); 25 MPI_Cart_shift( cart2d, 1, 1, &west, &east ); 26 MPI_Cart_shift( cart2d, 0, 1, &south, &north ); MPI_Cart_shift が返すプロセス番号 a, b の位置関係 ( 1, 1, &a, &b ) ( 0, 1, &a, &b ) ( 0, -1, &a, &b ) a Process b b a ( 1, -1, &a, &b ) Process Process b Process a a b 166

168 2. 派生データ型 (xghost, yghost) の定義 jacobi2d5p.c 49 // define derived datatypes 50 MPI_Datatype xghost, yghost; 51 MPI_Type_vector( 1, ny, ny+2, MPI_FLOAT, &xghost ); 52 MPI_Type_vector( nx, 1, ny+2, MPI_FLOAT, &yghost ); 53 MPI_Type_commit( &xghost ); 54 MPI_Type_commit( &yghost ); xghost yghost stride blocklength ny ny+2 ny+2 blocklength stride 1 1 count nx count 注 : データは Y 軸方向に連続 167

169 Y 軸方向の通信 jacobi2d5p.c 56 // send buffers // recv buffers 57 void *sbuf_n = &(phi[1][ny]); void *rbuf_n = &(phi[1][ 0]); 58 void *sbuf_s = &(phi[1][ 1]); void *rbuf_s = &(phi[1][ny+1]); 66 // shift northward 67 MPI_Sendrecv( sbuf_n, 1, yghost, north, 0 68 rbuf_n, 1, yghost, south, 0, cart2d, status ); 69 // shift southward 70 MPI_Sendrecv( sbuf_s, 1, yghost, south, 0, 71 rbuf_s, 1, yghost, north, 0, cart2d, status ); buffers sbuf_n rbuf_n north send yghost Self yghost recv northward buffers rbuf_s sbuf_s north recv yghost Self yghost send southward south south

170 xghost xghost xghost xghost X 軸方向の通信 jacobi2d5p.c 59 void *sbuf_e = &(phi[nx][1]); void *rbuf_e = &(phi[ 0][1]); 60 void *sbuf_w = &(phi[ 1][1]); void *rbuf_w = &(phi[nx+1][1]); 72 // shift eastward 73 MPI_Sendrecv( sbuf_e, 1, xghost, east, 0 74 rbuf_e, 1, xghost, west, 0, cart2d, status ); 75 // shift westward 76 MPI_Sendrecv( sbuf_w, 1, xghost, west, 0, 77 rbuf_w, 1, xghost, east, 0, cart2d, status ); eastward westward recv send send recv west Self east west Self east buffers rbuf_e sbuf_e buffers sbuf_w rbuf_w

171 170 5 点差分 ( 通信隠蔽有り ) カーテシアン トポロジと派生データ型は隠蔽無しと同じ 通信を隠蔽するために非閉塞通信を使い MPI_Waitall で完了する 完了するまでの間に領域内部の計算を行う 通信完了後に領域境界の計算を行う 1. Y-X 軸方向の通信 jacobi2d5poverlap.c 67 // shift northward 68 MPI_Isend( sbuf_n, 1, yghost, north, 0, cart2d, &(req[0]) ); 69 MPI_Irecv( rbuf_n, 1, yghost, south, 0, cart2d, &(req[1]) ); 70 // shift southward 71 MPI_Isend( sbuf_s, 1, yghost, south, 0, cart2d, &(req[2]) ); 72 MPI_Irecv( rbuf_s, 1, yghost, north, 0, cart2d, &(req[3]) ); 73 // shift eastward 74 MPI_Isend( sbuf_e, 1, xghost, east, 0, cart2d, &(req[4]) ); 75 MPI_Irecv( rbuf_e, 1, xghost, west, 0, cart2d, &(req[5]) ); 76 // shift westward 77 MPI_Isend( sbuf_w, 1, xghost, west, 0, cart2d, &(req[6]) ); 78 MPI_Irecv( rbuf_w, 1, xghost, east, 0, cart2d, &(req[7]) );

172 領域内部の計算と通信の完了 jacobi2d5poverlap.c 80 // Jacobi iteration, interior 81 for( int i=2; i<=nx-1; ++i ) 82 for( int j=2; j<=ny-1; ++j ) 内部点のループ 83 w[i][j] = 0.25*( phi[i+1][j ] + phi[i-1][j ] 84 phi[i ][j+1] + phi[i ][j-1] h*h*f[i][j] ); MPI_Waitall( 8, req, status ); ny+1 ny 計算領域の分類 内部点 Y 軸境界点 X 軸境界点 nx nx+1

173 領域境界の計算 jacobi2d5poverlap.c 88 // Jacobi iteration, fringe 89 const int jn = ny, js = 1; 90 for( int i=1; i<=nx; ++i ) 91 { 92 w[i][jn] = 0.25*( phi[i ][jn+1] + phi[i ][jn-1] 93 phi[i+1][jn ] + phi[i-1][jn ] h*h*f[i][jn] ); 94 w[i][js] = 0.25*( phi[i ][js+1] + phi[i ][js-1] 95 phi[i+1][js ] + phi[i-1][js ] h*h*f[i][js] ); 96 } 97 const int ie = nx, iw = 1; 98 for( int j=2; j<=ny-1; ++j ) 99 { X 軸境界点 Y 軸境界点 100 w[ie][j] = 0.25*( phi[ie ][j+1] + phi[ie ][j-1] 101 phi[ie+1][j ] + phi[ie-1][j ] h*h*f[ie][j] ); 102 w[iw][j] = 0.25*( phi[iw ][j+1] + phi[iw ][j-1] 103 phi[iw+1][j ] + phi[iw-1][j ] h*h*f[iw][j] ); 104 }

174 5 点差分 ( 持続通信 ) 前例とほとんど同じ 最初に送受信リクエストを作成しておく 通信は Startall で開始し Wailall で完了させる 1. 送受信リクエストの作成 jacobi2d5ppersistent.c 62 // initialize persistent sends 63 MPI_Request req[8]; 64 MPI_Ssend_init( sbuf_n, 1, yghost, north, 0, cart2d, &(req[0]) ); 65 MPI_Ssend_init( sbuf_s, 1, yghost, south, 0, cart2d, &(req[1]) ); 66 MPI_Ssend_init( sbuf_e, 1, xghost, east, 0, cart2d, &(req[2]) ); 67 MPI_Ssend_init( sbuf_w, 1, xghost, west, 0, cart2d, &(req[3]) ); 68 MPI_Recv_init( rbuf_n, 1, yghost, south, 0, cart2d, &(req[4]) ); 69 MPI_Recv_init( rbuf_s, 1, yghost, north, 0, cart2d, &(req[5]) ); 70 MPI_Recv_init( rbuf_e, 1, xghost, west, 0, cart2d, &(req[6]) ); 71 MPI_Recv_init( rbuf_w, 1, xghost, east, 0, cart2d, &(req[7]) ); メモリコピーを回避するためここでは Synchronous send を使う 2. Y-X 軸方向の通信 77 // start persistent sends 78 MPI_Startall( 8, req ); 173

175 9 点差分 ( 通信隠蔽無し ) 1. コミュニケータの定義は5 点差分と同じ 2. 派生データ型は xghost を y 軸の全領域とする 3. この派生データ型の場合はY-Xの順で逐次的に通信する jacobi2d9p.c 49 // define derived datatypes 50 MPI_Datatype xghost, yghost; 51 MPI_Type_vector( 1, ny+2, ny+2, MPI_FLOAT, &xghost ); 52 MPI_Type_vector( nx, 1, ny+2, MPI_FLOAT, &yghost ); 53 MPI_Type_commit( &xghost ); 54 MPI_Type_commit( &yghost ); blocklength xghost stride yghost ny+2 ny+2 ny+2 blocklength 1 stride 1 count nx count 174

176 Y 軸方向の通信 jacobi2d9p.c 56 // send buffers // recv buffers 57 void *sbuf_n = &(phi[1][ny]); void *rbuf_n = &(phi[1][ 0]); 58 void *sbuf_s = &(phi[1][ 1]); void *rbuf_s = &(phi[1][ny+1]); 66 // shift northward 67 MPI_Sendrecv( sbuf_n, 1, yghost, north, 0 68 rbuf_n, 1, yghost, south, 0, cart2d, status ); 69 // shift southward 70 MPI_Sendrecv( sbuf_s, 1, yghost, south, 0, 71 rbuf_s, 1, yghost, north, 0, cart2d, status ); buffers sbuf_n rbuf_n north send yghost Self yghost recv northward buffers rbuf_s sbuf_s north recv yghost Self yghost send southward south south

177 xghost xghost xghost xghost X 軸方向の通信 jacobi2d9p.c 59 void *sbuf_e = &(phi[nx][0]); void *rbuf_e = &(phi[ 0][0]); 60 void *sbuf_w = &(phi[ 1][0]); void *rbuf_w = &(phi[nx+1][0]); 72 // shift eastward 73 MPI_Sendrecv( sbuf_e, 1, xghost, east, 0 74 rbuf_e, 1, xghost, west, 0, cart2d, status ); 75 // shift westward 76 MPI_Sendrecv( sbuf_w, 1, xghost, west, 0, 77 rbuf_w, 1, xghost, east, 0, cart2d, status ); eastward westward recv send send recv west Self east west Self east buffers rbuf_e sbuf_e buffers sbuf_w rbuf_w

178 177 具体的な問題への応用 1. 構造格子系 ( 差分法 ) 2. 非構造格子系 ( 有限要素法, 有限体積法 ) 3. フーリエ変換 4. MPI Tips

179 178 具体的な問題への応用 1. 構造格子系 ( 差分法 ) 2. 非構造格子系 ( 有限要素法, 有限体積法 ) 3. フーリエ変換 4. MPI Tips

180 2 次元フーリエ変換 計算手順 入力 Y 軸変換転置通信 X 軸変換出力 A[Nx][Ny] Y FFT transpose X FFT B[Ny][Nx] 2 次元転置通信 (4 プロセスの場合 ) A[i][j] 4 by 4 all-to-all B[j][i] P3 unit stride y Ny x P0 P1 P2 P3 Nx/4 y x unit stride P2 P1 P0 Nx Ny/4 配列全体を X 軸で分割 配列全体を Y 軸で分割 添字を交換 (i-j j-i) 179

181 2 次元フーリエ変換 ( 続 ) データ型の定義 sblock ( 送信側 ) stride=ny 添字を巡回置換すると受信側は不連続な並びとなるので受信データ型は 2 段階で定義する * 定義した型は使用前に commit しておく MPI_Type_vector(Nx/4, Ny/4, Ny, MPI_FLOAT, &sblock); unit stride y x blocklength=ny/4 y rblock ( 受信側 ) x unit stride blocklength=1 count=nx/4 stride=nx count=ny/4 count=nx/4 [slice] stride=sizeof(float) [bytes] blocklength=1 [slice] MPI_Type_vector(Ny/4, 1, Nx, MPI_FLOAT, &slice); MPI_Type_create_hvector(Nx/4, 1, sizeof(float), slice, &rblock); 180

182 sdispls 2 次元フーリエ変換 ( 続 ) 通信 A[i][j] 4 by 4 all-to-all B[j][i] Nx P3 unit stride y x P0 P1 P2 P3 Nx/4 Ny y x unit stride P2 P1 P0 rdispls Ny/4 displs をバイト単位で指定するために Alltoallw を使う for(int i=0; i<4; ++i) { scounts[i]=1; sdispls[i]=i*ny/4*sizeof(float); stypes[i]=sblock; rcounts[i]=1; rdispls[i]=i*nx/4*sizeof(float); rtypes[i]=rblock; } MPI_Alltoallw(A, scounts, sdispls, stypes, B, rcounts, rdispls, rtypes, MPI_COMM_WORLD); 181

183 3 次元フーリエ変換 (2 次元転置 ) 計算手順 入力 Z-Y 軸変換 Z-X 平面内転置通信 X 軸変換出力 A[Nx][Ny][Nz] Z-Y FFT transpose X FFT B[Ny][Nz][Nx] 2 次元転置通信 (4 プロセスの場合 ) A[i][j][k] 4 by 4 all-to-all Nz/4 P3 B[j][k][i] unit stride z Nz y x P0 P1 P2 P3 Nx/4 配列全体を X 軸で分割 Ny P2 P1 z y P0 x Ny unit stride Nx 配列全体をZ 軸で分割 添字 iを最内側, kを左移動 (i-j-k j-k-i) 182

184 3 次元フーリエ変換 (3 次元転置 ) 計算手順 入力 Z 軸変換 Z-Y 平面内転置通信 Y 軸変換 A[Nx][Ny][Nz] Z FFT transpose Y FFT 出力 C[Nz][Ny][Nx] X 軸変換 X FFT Y-X 平面内転置通信 transpose コミュニーケータ切替 switch comm 3 次元転置通信 Z-Y(4 プロセスの場合 ) 部分コミュニケータ Czy0 Czy1 P1 P0 P1 P0 2 by 2 all-to-all 配列全体をX 軸で分割 添字 jを最内側,kを左移動 (i-j-k i-k-j) 部分コミュニケータ Czy0 Czy1 P1 P1 unit stride z Nz y x Nx/2 Ny/2 Nz/2 P0 Nx/2 P0 Ny z y unit stride x 183

185 184 3 次元フーリエ変換 (3 次元転置 ) 3 次元転置通信 Y-X(4 プロセスの場合 ) 部分コミュニケータ 配列全体を Y 軸で分割 添字 i を最内側 j を左移動 (i-k-j k-j-i) 部分コミュニケータ z y unit stride x P1 P0 P0 P0 P1 P1 Cyx1 Cyx0 2 by 2 all-to-all P0 P1 P1 Cyx1 Cyx0 z y x unit stride Nz/2 P0 P1 Ny Nz/2 P0 Ny/2 Nx/2 Nx MPI_Comm_split で部分コミュニケータを作る 2 次元フーリエ変換と同様に型を定義する 各コミュニーケータ内で Alltoallw 通信する 通信を隠蔽する場合はパイプライン化する

186 185 具体的な問題への応用 1. 構造格子系 ( 差分法 ) 2. 非構造格子系 ( 有限要素法, 有限体積法 ) 3. フーリエ変換 4. MPI Tips

187 MPI 通信の心得 1. 集団通信を使う 通信手順の最適化 2. トポロジを使う コミュニケータの最適化 3. 派生データ型を使う メモリコピー削減 ( システムによって悪くなる場合もある ) 4. データはまとめて通信する 回数削減, 長サイズ化 5. データ量の均一化 (BSP* の場合 ) 無駄な待ち時間回避 *Bulk Synchronous Parallel: barrier で計算と通信を分離する並列化手法 186

188 Appendix A MPE(Multi-Processing Environment) Library MPICH の開発グループが提供するユーティリティー群 ( 他の MPI ライブラリからも利用可能 ) 以下の機能が提供されている Logging routines X window graphics Sequential section Shared counter Tag management Miscellaneous Logging routines は性能プロファイリングに利用される それ以外の機能はほとんど使われない *The MPE Multiprocessing Environment, Appendix C, Using MPI, 2nd ed., MIT Press, 1999 * 187

189 Logging routines の基本的な使い方 #include mpi.h #include mpe.h MPI_Init( &argc, &argv); MPE_Init_log(); ヘッダファイルをインクルード ログ取得開始 const int bgnid = 1; const int endid = 2; MPE_Describe_state(bgnID, endid, Bcast, red:vlines3 ); MPE_Log_event(bgnID, 0, start ); // target section MPI_Bcast etc. MPE_Log_event(endID, 0, stop ); MPE_Finish_log( test.log ); MPI_Finalize(); 計時開始 計時終了 ログ取得終了, ファイル書出し MPE_Describe_state で計測領域の開始 ID:bgnID, 終了 ID:endID, 領域名 : Bcast, 表示パターン : red:vlines3 を定義する ID 番号は重複してはならない 188

190 Jumpshot-3 Visualization Program SLOG-2 形式のファイルを可視化するプログラム下図のようにプロセス毎のタイムライン等を表示できる 実際には 100 プロセス 100 秒程度までそれ以上は画面スクロール等の操作が困難 189

HPCセミナー

HPCセミナー 並列プログラミング技法 (MPI 詳説 ) 高度情報科学技術研究機構神戸センター 宮内敦 0 本日の講義内容 MPIの基礎知識 MPI 関数各論 並列性能評価 具体的な問題への応用 1 2 MPI の基礎知識 1. MPI 規格 (MPI standard) 2. MPI ライブラリ 3 MPI 規格 (MPI standard) とは プロセス並列を前提としたプロセス間のメッセージ交換に関する標準仕様

More information

Microsoft PowerPoint MPI.v...O...~...O.e.L.X.g(...Q..)

Microsoft PowerPoint MPI.v...O...~...O.e.L.X.g(...Q..) MPI プログラミング Information Initiative Center, Hokkaido Univ. MPI ライブラリを利用した分散メモリ型並列プログラミング 分散メモリ型並列処理 : 基礎 分散メモリマルチコンピュータの構成 プロセッサエレメントが専用のメモリ ( ローカルメモリ ) を搭載 スケーラビリティが高い 例 :HITACHI SR8000 Interconnection

More information

Microsoft PowerPoint - 講義:片方向通信.pptx

Microsoft PowerPoint - 講義:片方向通信.pptx MPI( 片方向通信 ) 09 年 3 月 5 日 神戸大学大学院システム情報学研究科計算科学専攻横川三津夫 09/3/5 KOBE HPC Spring School 09 分散メモリ型並列計算機 複数のプロセッサがネットワークで接続されており, れぞれのプロセッサ (PE) が, メモリを持っている. 各 PE が自分のメモリ領域のみアクセス可能 特徴数千から数万 PE 規模の並列システムが可能

More information

NUMAの構成

NUMAの構成 メッセージパッシング プログラミング 天野 共有メモリ対メッセージパッシング 共有メモリモデル 共有変数を用いた単純な記述自動並列化コンパイラ簡単なディレクティブによる並列化 :OpenMP メッセージパッシング 形式検証が可能 ( ブロッキング ) 副作用がない ( 共有変数は副作用そのもの ) コストが小さい メッセージパッシングモデル 共有変数は使わない 共有メモリがないマシンでも実装可能 クラスタ

More information

Microsoft PowerPoint - KHPCSS pptx

Microsoft PowerPoint - KHPCSS pptx KOBE HPC サマースクール 2018( 初級 ) 9. 1 対 1 通信関数, 集団通信関数 2018/8/8 KOBE HPC サマースクール 2018 1 2018/8/8 KOBE HPC サマースクール 2018 2 MPI プログラム (M-2):1 対 1 通信関数 問題 1 から 100 までの整数の和を 2 並列で求めなさい. プログラムの方針 プロセス0: 1から50までの和を求める.

More information

Microsoft PowerPoint - 講義:コミュニケータ.pptx

Microsoft PowerPoint - 講義:コミュニケータ.pptx コミュニケータとデータタイプ (Communicator and Datatype) 2019 年 3 月 15 日 神戸大学大学院システム情報学研究科横川三津夫 2019/3/15 Kobe HPC Spring School 2019 1 講義の内容 コミュニケータ (Communicator) データタイプ (Datatype) 演習問題 2019/3/15 Kobe HPC Spring School

More information

2 T 1 N n T n α = T 1 nt n (1) α = 1 100% OpenMP MPI OpenMP OpenMP MPI (Message Passing Interface) MPI MPICH OpenMPI 1 OpenMP MPI MPI (trivial p

2 T 1 N n T n α = T 1 nt n (1) α = 1 100% OpenMP MPI OpenMP OpenMP MPI (Message Passing Interface) MPI MPICH OpenMPI 1 OpenMP MPI MPI (trivial p 22 6 22 MPI MPI 1 1 2 2 3 MPI 3 4 7 4.1.................................. 7 4.2 ( )................................ 10 4.3 (Allreduce )................................. 12 5 14 5.1........................................

More information

PowerPoint プレゼンテーション

PowerPoint プレゼンテーション AICS 公開ソフトウェア講習会 15 回 表題通信ライブラリと I/O ライブラリ 場所 AICS R104-2 時間 2016/03/23 ( 水 ) 13:30-17:00 13:30-13:40 全体説明 13:40-14:10 PRDMA 14:10-14:40 MPICH 14:40-15:10 PVAS 15:10-15:30 休憩 15:30-16:00 Carp 16:00-16:30

More information

スライド 1

スライド 1 目次 2.MPI プログラミング入門 この資料は, スーパーコン 10 で使用したものである. ごく基本的な内容なので, 現在でも十分利用できると思われるものなので, ここに紹介させて頂く. ただし, 古い情報も含まれているので注意が必要である. 今年度版の解説は, 本選の初日に配布する予定である. 1/20 2.MPI プログラミング入門 (1) 基本 説明 MPI (message passing

More information

main() {... } main() { main() { main() {......... } } } main() { main() { main() {......... } } } main() { if(rank==)... } main() { if(rank==)... } main() { if(rank==x)... } P(N) P(N) / P(M) * ( M / N

More information

86

86 86 86 86 main() {... } main() { main() { main() {......... } } } 86 main() { main() { main() {......... } } } main() { if(rank==)... } main() { if(rank==)... } main() { if(rank==x)... } 86 P(N) P(N) /

More information

MPI コミュニケータ操作

MPI コミュニケータ操作 コミュニケータとデータタイプ 辻田祐一 (RIKEN AICS) 講義 演習内容 MPI における重要な概念 コミュニケータ データタイプ MPI-IO 集団型 I/O MPI-IO の演習 2 コミュニケータ MPI におけるプロセスの 集団 集団的な操作などにおける操作対象となる MPI における集団的な操作とは? 集団型通信 (Collective Communication) 集団型 I/O(Collective

More information

Microsoft PowerPoint - 演習1:並列化と評価.pptx

Microsoft PowerPoint - 演習1:並列化と評価.pptx 講義 2& 演習 1 プログラム並列化と性能評価 神戸大学大学院システム情報学研究科横川三津夫 yokokawa@port.kobe-u.ac.jp 2014/3/5 RIKEN AICS HPC Spring School 2014: プログラム並列化と性能評価 1 2014/3/5 RIKEN AICS HPC Spring School 2014: プログラム並列化と性能評価 2 2 次元温度分布の計算

More information

para02-2.dvi

para02-2.dvi 2002 2 2002 4 23 : MPI MPI 1 MPI MPI(Message Passing Interface) MPI UNIX Windows Machintosh OS, MPI 2 1 1 2 2.1 1 1 1 1 1 1 Fig. 1 A B C F Fig. 2 A B F Fig. 1 1 1 Fig. 2 2.2 Fig. 3 1 . Fig. 4 Fig. 3 Fig.

More information

演習 II 2 つの講義の演習 奇数回 : 連続系アルゴリズム 部分 偶数回 : 計算量理論 部分 連続系アルゴリズム部分は全 8 回を予定 前半 2 回 高性能計算 後半 6 回 数値計算 4 回以上の課題提出 ( プログラム + 考察レポート ) で単位

演習 II 2 つの講義の演習 奇数回 : 連続系アルゴリズム 部分 偶数回 : 計算量理論 部分 連続系アルゴリズム部分は全 8 回を予定 前半 2 回 高性能計算 後半 6 回 数値計算 4 回以上の課題提出 ( プログラム + 考察レポート ) で単位 演習 II ( 連続系アルゴリズム ) 第 1 回 : MPI 須田研究室 M2 本谷徹 motoya@is.s.u-tokyo.ac.jp 2012/10/05 2012/10/18 補足 訂正 演習 II 2 つの講義の演習 奇数回 : 連続系アルゴリズム 部分 偶数回 : 計算量理論 部分 連続系アルゴリズム部分は全 8 回を予定 前半 2 回 高性能計算 後半 6 回 数値計算 4 回以上の課題提出

More information

2012 6 1 MPI 1995 8 2002 2003 ( 2) MPI http://accc.riken.jp/hpc/training.html iii 1 1 1-1.......................................... 2 1-2........................................... 4 2 9 2-1...............................................

More information

MPI () MPIMessage Passing Interface MPI MPI OpenMP 7 ( ) 1

MPI () MPIMessage Passing Interface MPI MPI OpenMP 7 ( ) 1 7 MPI / 7 (2014 05 21 ) MPI () MPIMessage Passing Interface MPI MPI OpenMP 7 (2014 05 21 ) 1 (MPI) 7 (2014 05 21 ) 2 (OpenMP) 7 (2014 05 21 ) 3 (MPI + OpenMP) 7 (2014 05 21 ) 4 MPI (1) MPI1 OpenMP 1 pragma

More information

C/C++ FORTRAN FORTRAN MPI MPI MPI UNIX Windows (SIMD Single Instruction Multipule Data) SMP(Symmetric Multi Processor) MPI (thread) OpenMP[5]

C/C++ FORTRAN FORTRAN MPI MPI MPI UNIX Windows (SIMD Single Instruction Multipule Data) SMP(Symmetric Multi Processor) MPI (thread) OpenMP[5] MPI ( ) snozawa@env.sci.ibaraki.ac.jp 1 ( ) MPI MPI Message Passing Interface[2] MPI MPICH[3],LAM/MPI[4] (MIMDMultiple Instruction Multipule Data) Message Passing ( ) (MPI (rank) PE(Processing Element)

More information

Microsoft PowerPoint _MPI-03.pptx

Microsoft PowerPoint _MPI-03.pptx 計算科学演習 Ⅰ ( 第 11 回 ) MPI を いた並列計算 (III) 神戸大学大学院システム情報学研究科横川三津夫 yokokawa@port.kobe-u.ac.jp 2014/07/03 計算科学演習 Ⅰ:MPI を用いた並列計算 (III) 1 2014/07/03 計算科学演習 Ⅰ:MPI を用いた並列計算 (III) 2 今週の講義の概要 1. 前回課題の解説 2. 部分配列とローカルインデックス

More information

untitled

untitled RIKEN AICS Summer School 3 4 MPI 2012 8 8 1 6 MPI MPI 2 allocatable 2 Fox mpi_sendrecv 3 3 FFT mpi_alltoall MPI_PROC_NULL 4 FX10 /home/guest/guest07/school/ 5 1 A (i, j) i+j x i i y = Ax A x y y 1 y i

More information

目 目 用方 用 用 方

目 目 用方 用 用 方 大 生 大 工 目 目 用方 用 用 方 用 方 MS-MPI MPI.NET MPICH MPICH2 LAM/MPI Ver. 2 2 1 2 1 C C++ Fortan.NET C# C C++ Fortan 用 行 用 用 用 行 用 言 言 言 行 生 方 方 一 行 高 行 行 文 用 行 If ( rank == 0 ) { // 0 } else if (rank == 1) {

More information

演習準備 2014 年 3 月 5 日神戸大学大学院システム情報学研究科森下浩二 1 RIKEN AICS HPC Spring School /3/5

演習準備 2014 年 3 月 5 日神戸大学大学院システム情報学研究科森下浩二 1 RIKEN AICS HPC Spring School /3/5 演習準備 2014 年 3 月 5 日神戸大学大学院システム情報学研究科森下浩二 1 演習準備の内容 神戸大 FX10(π-Computer) 利用準備 システム概要 ログイン方法 コンパイルとジョブ実行方法 MPI 復習 1. MPIプログラムの基本構成 2. 並列実行 3. 1 対 1 通信 集団通信 4. データ 処理分割 5. 計算時間計測 2 神戸大 FX10(π-Computer) 利用準備

More information

コードのチューニング

コードのチューニング ハイブリッド並列 八木学 ( 理化学研究所計算科学研究機構 ) 謝辞 松本洋介氏 ( 千葉大学 ) KOBE HPC Spring School 2017 2017 年 3 月 14 日神戸大学計算科学教育センター MPI とは Message Passing Interface 分散メモリのプロセス間の通信規格(API) SPMD(Single Program Multi Data) が基本 -

More information

Microsoft PowerPoint - 演習2:MPI初歩.pptx

Microsoft PowerPoint - 演習2:MPI初歩.pptx 演習 2:MPI 初歩 - 並列に計算する - 2013 年 8 月 6 日 神戸大学大学院システム情報学研究科計算科学専攻横川三津夫 MPI( メッセージ パッシング インターフェース ) を使おう! [ 演習 2 の内容 ] はじめの一歩課題 1: Hello, world を並列に出力する. 課題 2: プロセス 0 からのメッセージを受け取る (1 対 1 通信 ). 部分に分けて計算しよう課題

More information

<4D F736F F F696E74202D C097F B A E B93C782DD8EE682E890EA97705D>

<4D F736F F F696E74202D C097F B A E B93C782DD8EE682E890EA97705D> 並列アルゴリズム 2005 年後期火曜 2 限青柳睦 Aoyagi@cc.kyushu-u.ac.jp http//server-500.cc.kyushu-u.ac.jp/ 11 月 29( 火 ) 7. 集団通信 (Collective Communication) 8. 領域分割 (Domain Decomposition) 1 もくじ 1. 序並列計算機の現状 2. 計算方式およびアーキテクチュアの分類

More information

MPI usage

MPI usage MPI (Version 0.99 2006 11 8 ) 1 1 MPI ( Message Passing Interface ) 1 1.1 MPI................................. 1 1.2............................... 2 1.2.1 MPI GATHER.......................... 2 1.2.2

More information

スライド 1

スライド 1 Parallel Programming in MPI part 2 1 1 Today's Topic ノンブロッキング通信 Non-Blocking Communication 通信の完了を待つ間に他の処理を行う Execute other instructions while waiting for the completion of a communication. 集団通信関数の実装 Implementation

More information

2007年度 計算機システム演習 第3回

2007年度 計算機システム演習 第3回 2014 年度 実践的並列コンピューティング 第 10 回 MPI による分散メモリ並列プログラミング (3) 遠藤敏夫 endo@is.titech.ac.jp 1 MPI プログラムの性能を考える 前回までは MPI プログラムの挙動の正しさを議論 今回は速度性能に注目 MPIプログラムの実行時間 = プロセス内計算時間 + プロセス間通信時間 計算量 ( プロセス内 ) ボトルネック有無メモリアクセス量

More information

Microsoft PowerPoint - 第10回講義(2015年12月22日)-1 .pptx

Microsoft PowerPoint - 第10回講義(2015年12月22日)-1 .pptx 非同期通信 東京大学情報基盤センター准教授片桐孝洋 1 2015 年 12 月 22 日 ( 火 )10:25-12:10 講義日程 ( 工学部共通科目 ) 10 月 6 日 : ガイダンス 1. 10 月 13 日 並列数値処理の基本演算 ( 座学 ) 2. 10 月 20 日 : スパコン利用開始 ログイン作業 テストプログラム実行 3. 10 月 27 日 高性能演算技法 1 ( ループアンローリング

More information

演習準備

演習準備 演習準備 2014 年 3 月 5 日神戸大学大学院システム情報学研究科森下浩二 1 演習準備の内容 神戸大 FX10(π-Computer) 利用準備 システム概要 ログイン方法 コンパイルとジョブ実行方法 MPI 復習 1. MPIプログラムの基本構成 2. 並列実行 3. 1 対 1 通信 集団通信 4. データ 処理分割 5. 計算時間計測 2 神戸大 FX10(π-Computer) 利用準備

More information

chap2.ppt

chap2.ppt 2. メッセージ通信計算 2.1 メッセージ通信プログラミングの基本 プログラミングの選択肢 特別な並列プログラミング言語を設計する occam (Inmos, 1984, 1986) 既存の逐次言語の文法 / 予約語をメッセージ通信を処理できるように拡張する 既存の逐次言語を用い メッセージ通信のための拡張手続のライブラリを用意する どのプロセスを実行するのか メッセージ通信のタイミング 中身を明示的に指定する必要がある

More information

講義の流れ 並列プログラムの概要 通常のプログラムと並列プログラムの違い 並列プログラム作成手段と並列計算機の構造 OpenMP による並列プログラム作成 処理を複数コアに分割して並列実行する方法 MPI による並列プログラム作成 ( 午後 ) プロセス間通信による並列処理 処理の分割 + データの

講義の流れ 並列プログラムの概要 通常のプログラムと並列プログラムの違い 並列プログラム作成手段と並列計算機の構造 OpenMP による並列プログラム作成 処理を複数コアに分割して並列実行する方法 MPI による並列プログラム作成 ( 午後 ) プロセス間通信による並列処理 処理の分割 + データの ( 財 ) 計算科学振興財団 大学院 GP 大学連合による計算科学の最先端人材育成 第 1 回社会人向けスパコン実践セミナー資料 29 年 2 月 17 日 13:15~14:45 九州大学情報基盤研究開発センター 南里豪志 1 講義の流れ 並列プログラムの概要 通常のプログラムと並列プログラムの違い 並列プログラム作成手段と並列計算機の構造 OpenMP による並列プログラム作成 処理を複数コアに分割して並列実行する方法

More information

±é½¬£²¡§£Í£Ð£É½éÊâ

±é½¬£²¡§£Í£Ð£É½éÊâ 2012 8 7 1 / 52 MPI Hello World I ( ) Hello World II ( ) I ( ) II ( ) ( sendrecv) π ( ) MPI fortran C wget http://www.na.scitec.kobe-u.ac.jp/ yaguchi/riken2012/enshu2.zip unzip enshu2.zip 2 / 52 FORTRAN

More information

スライド 1

スライド 1 計算科学演習 MPI 基礎 学術情報メディアセンター情報学研究科 システム科学専攻中島浩 目次 プログラミングモデル SPMD 同期通信 / 非同期通信 MPI 概論 プログラム構造 Communicator & rank データ型 タグ 一対一通信関数 1 次元分割並列化 : 基本 基本的考え方 配列宣言 割付 部分領域交換 結果出力 1 次元分割並列化 : 高速化 通信 計算のオーバーラップ 通信回数削減

More information

スライド 1

スライド 1 計算科学演習 MPI 基礎 学術情報メディアセンター 情報学研究科 システム科学専攻 中島浩 目次 プログラミングモデル SPMD 同期通信 / 非同期通信 MPI 概論 プログラム構造 Communicator & rank データ型 タグ 一対一通信関数 1 次元分割並列化 : 基本 基本的考え方 配列宣言 割付 部分領域交換 結果出力 1 次元分割並列化 : 高速化 通信 計算のオーバーラップ

More information

スライド 1

スライド 1 本日 (4/25) の内容 1 並列計算の概要 並列化計算の目的 並列コンピュータ環境 並列プログラミングの方法 MPI を用いた並列プログラミング 並列化効率 2 並列計算の実行方法 Hello world モンテカルロ法による円周率計算 並列計算のはじまり 並列計算の最初の構想を イギリスの科学者リチャードソンが 1922 年に発表 < リチャードソンの夢 > 64000 人を円形の劇場に集めて

More information

Microsoft PowerPoint _MPI-01.pptx

Microsoft PowerPoint _MPI-01.pptx 計算科学演習 Ⅰ MPI を いた並列計算 (I) 神戸大学大学院システム情報学研究科谷口隆晴 yaguchi@pearl.kobe-u.ac.jp この資料は昨年度担当の横川先生の資料を参考にさせて頂いています. 2016/06/23 MPI を用いた並列計算 (I) 1 講義概要 分散メモリ型計算機上のプログラミング メッセージ パシング インターフェイス (Message Passing Interface,MPI)

More information

コードのチューニング

コードのチューニング MPI による並列化実装 ~ ハイブリッド並列 ~ 八木学 ( 理化学研究所計算科学研究センター ) KOBE HPC Spring School 2019 2019 年 3 月 14 日 MPI とは Message Passing Interface 分散メモリのプロセス間の通信規格(API) SPMD(Single Program Multi Data) が基本 - 各プロセスが 同じことをやる

More information

かし, 異なったプロセス間でデータを共有するためには, プロセス間通信や特殊な共有メモリ領域を 利用する必要がある. このためマルチプロセッサマシンの利点を最大に引き出すことができない. こ の問題はマルチスレッドを用いることで解決できる. マルチスレッドとは,1 つのプロセスの中に複 数のスレッド

かし, 異なったプロセス間でデータを共有するためには, プロセス間通信や特殊な共有メモリ領域を 利用する必要がある. このためマルチプロセッサマシンの利点を最大に引き出すことができない. こ の問題はマルチスレッドを用いることで解決できる. マルチスレッドとは,1 つのプロセスの中に複 数のスレッド 0 並列計算について 0.1 並列プログラミングライブラリのメッセージパッシングモデル並列プログラムにはメモリモデルで分類すると, 共有メモリモデルと分散メモリモデルの 2 つに分けられる. それぞれ次のような特徴がある. 共有メモリモデル複数のプロセスやスレッドが事項する主体となり, 互いに通信や同期を取りながら計算が継続される. スレッド間の実行順序をプログラマが保証してやらないと, 思った結果が得られない.

More information

Microsoft PowerPoint - S1-ref-F.ppt [互換モード]

Microsoft PowerPoint - S1-ref-F.ppt [互換モード] 課題 S1 解説 Fortran 言語編 RIKEN AICS HPC Summer School 2014 中島研吾 ( 東大 情報基盤センター ) 横川三津夫 ( 神戸大 計算科学教育センター ) MPI Programming 課題 S1 (1/2) /a1.0~a1.3, /a2.0~a2.3 から局所ベクトル情報を読み込み, 全体ベクトルのノルム ( x ) を求めるプログラムを作成する

More information

MPI MPI MPI.NET C# MPI Version2

MPI MPI MPI.NET C# MPI Version2 MPI.NET C# 2 2009 2 27 MPI MPI MPI.NET C# MPI Version2 MPI (Message Passing Interface) MPI MPI Version 1 1994 1 1 1 1 ID MPI MPI_Send MPI_Recv if(rank == 0){ // 0 MPI_Send(); } else if(rank == 1){ // 1

More information

05-opt-system.ppt

05-opt-system.ppt 筑波大学計算科学研究センター HPC サマーセミナー 最適化 II ( 通信最適化 ) 建部修見 tatebe@cs.tsukuba.ac.jp 筑波大学大学院システム情報系計算科学研究センター 講義内容 基本通信性能 1 対 1 通信 集団通信 プロファイラ 通信最適化 通信の削減 通信遅延隠蔽 通信ブロック 負荷分散 基本通信性能 通信最適化のためには基本通信性能を押さえておくことが重要! 各種通信パターンにおける通信性能の把握

More information

WinHPC ppt

WinHPC ppt MPI.NET C# 2 2009 1 20 MPI.NET MPI.NET C# MPI.NET C# MPI MPI.NET 1 1 MPI.NET C# Hello World MPI.NET.NET Framework.NET C# API C# Microsoft.NET java.net (Visual Basic.NET Visual C++) C# class Helloworld

More information

untitled

untitled OS 2007/4/27 1 Uni-processor system revisited Memory disk controller frame buffer network interface various devices bus 2 1 Uni-processor system today Intel i850 chipset block diagram Source: intel web

More information

Microsoft PowerPoint - 高速化WS富山.pptx

Microsoft PowerPoint - 高速化WS富山.pptx 京 における 高速化ワークショップ 性能分析 チューニングの手順について 登録施設利用促進機関 一般財団法人高度情報科学技術研究機構富山栄治 一般財団法人高度情報科学技術研究機構 2 性能分析 チューニング手順 どの程度の並列数が実現可能か把握する インバランスの懸念があるか把握する タイムステップループ I/O 処理など注目すべき箇所を把握する 並列数 並列化率などの目標を設定し チューニング時の指針とする

More information

並列計算導入.pptx

並列計算導入.pptx 並列計算の基礎 MPI を用いた並列計算 並列計算の環境 並列計算 複数の計算ユニット(PU, ore, Pなど を使用して 一つの問題 計算 を行わせる 近年 並列計算を手軽に使用できる環境が急速に整いつつある >通常のP PU(entral Processing Unit)上に計算装置であるoreが 複数含まれている Intel ore i7 シリーズ: 4つの計算装置(ore) 通常のプログラム

More information

Microsoft PowerPoint - CproNt02.ppt [互換モード]

Microsoft PowerPoint - CproNt02.ppt [互換モード] 第 2 章 C プログラムの書き方 CPro:02-01 概要 C プログラムの構成要素は関数 ( プログラム = 関数の集まり ) 関数は, ヘッダと本体からなる 使用する関数は, プログラムの先頭 ( 厳密には, 使用場所より前 ) で型宣言 ( プロトタイプ宣言 ) する 関数は仮引数を用いることができる ( なくてもよい ) 関数には戻り値がある ( なくてもよい void 型 ) コメント

More information

MPI

MPI 筑波大学計算科学研究センター CCS HPC サマーセミナー MPI 建部修見 tatebe@cs.tsukuba.ac.jp 筑波大学大学院システム情報工学研究科計算科学研究センター 分散メモリ型並列計算機 (PC クラスタ ) 計算ノードはプロセッサとメモリで構成され, 相互結合網で接続 ノード内のメモリは直接アクセス 他ノードとはネットワーク通信により情報交換 いわゆるPCクラスタ 相互結合網

More information

120802_MPI.ppt

120802_MPI.ppt CPU CPU CPU CPU CPU SMP Symmetric MultiProcessing CPU CPU CPU CPU CPU CPU CPU CPU CPU CPU CPU CPU CP OpenMP MPI MPI CPU CPU CPU CPU CPU CPU CPU CPU CPU CPU MPI MPI+OpenMP CPU CPU CPU CPU CPU CPU CPU CP

More information

PowerPoint プレゼンテーション

PowerPoint プレゼンテーション 計算科学演習 I 第 8 回講義 MPI を用いた並列計算 (I) 2013 年 6 月 6 日 システム情報学研究科計算科学専攻 山本有作 今回の講義の概要 1. MPI とは 2. 簡単な MPI プログラムの例 (1) 3. 簡単な MPI プログラムの例 (2):1 対 1 通信 4. 簡単な MPI プログラムの例 (3): 集団通信 共有メモリ型並列計算機 ( 復習 ) 共有メモリ型並列計算機

More information

Microsoft PowerPoint 並列アルゴリズム04.ppt

Microsoft PowerPoint 並列アルゴリズム04.ppt 並列アルゴリズム 2005 年後期火曜 2 限 青柳睦 Aoyagi@cc.kyushu-u.ac.jp http://server-500.cc.kyushu-u.ac.jp/ 11 月 8 日 ( 火 ) 5. MPI の基礎 6. 並列処理の性能評価 1 もくじ 1. 序並列計算機の現状 2. 計算方式およびアーキテクチュアの分類 3. 並列計算の目的と課題 4. 数値計算における各種の並列化

More information

PowerPoint プレゼンテーション

PowerPoint プレゼンテーション 講座準備 講座資料は次の URL から DL 可能 https://goo.gl/jnrfth 1 ポインタ講座 2017/01/06,09 fumi 2 はじめに ポインタはC 言語において理解が難しいとされる そのポインタを理解することを目的とする 講座は1 日で行うので 詳しいことは調べること 3 はじめに みなさん復習はしましたか? 4 & 演算子 & 演算子を使うと 変数のアドレスが得られる

More information

MPI 通信ライブラリ規格化最前線 東京大学石川裕 目次 MPI 通信ライブラリとは? MPI 通信ライブラリ規格化の歴史 MPI 通信ライブラリ規格化の最近の動き 2008/12/11 2

MPI 通信ライブラリ規格化最前線 東京大学石川裕 目次 MPI 通信ライブラリとは? MPI 通信ライブラリ規格化の歴史 MPI 通信ライブラリ規格化の最近の動き 2008/12/11 2 MPI 通信ライブラリ規格化最前線 東京大学石川裕 目次 MPI 通信ライブラリとは? MPI 通信ライブラリ規格化の歴史 MPI 通信ライブラリ規格化の最近の動き 2008/12/11 2 MPI 通信ライブラリの概要 背景 1990 年初頭 各コンピュータベンダは独自の通信ライブラリを提供 ユーザプログラムのポータビリティ問題が深刻化 あるマシン上で開発したアプリケーションが他のベンダのマシンで動かず

More information

第8回講義(2016年12月6日)

第8回講義(2016年12月6日) 2016/12/6 スパコンプログラミング (1) (Ⅰ) 1 行列 - 行列積 (2) 東京大学情報基盤センター准教授塙敏博 2016 年 12 月 6 日 ( 火 ) 10:25-12:10 2016/11/29 講義日程 ( 工学部共通科目 ) 1. 9 月 27 日 ( 今日 ): ガイダンス 2. 10 月 4 日 l 並列数値処理の基本演算 ( 座学 ) 3. 10 月 11 日 : スパコン利用開始

More information

理化学研究所計算科学研究機構研究部門量子系分子科学研究チーム殿 hp170163: 有機半導体 有機分子発光材料の全自動探索シミュレーションシステムの開発 高度化支援作業 2017 年 9 6 ( R405 般財団法 度情報科学技術研究機構利 援部 1

理化学研究所計算科学研究機構研究部門量子系分子科学研究チーム殿 hp170163: 有機半導体 有機分子発光材料の全自動探索シミュレーションシステムの開発 高度化支援作業 2017 年 9 6 ( R405 般財団法 度情報科学技術研究機構利 援部 1 理化学研究所計算科学研究機構研究部門量子系分子科学研究チーム殿 hp170163: 有機半導体 有機分子発光材料の全自動探索シミュレーションシステムの開発 高度化支援作業 2017 年 9 6 ( )@AICS R405 般財団法 度情報科学技術研究機構利 援部 1 Outline 高度化支援の依頼内容 実行環境と計算条件 PWscf フロー図 各ライブラリを使用した場合のプログラム全体の実行時間の比較

More information

情報処理概論(第二日目)

情報処理概論(第二日目) 1 並列プログラミング超入門講習会 九州大学情報基盤研究開発センター MPI コース 2 並列計算機の構成 計算ノード ネットワーク CPU コア メモリ アクセラレータ (GPU 等 ) 例 : スーパーコンピュータシステム ITO サブシステム B ノード数 CPU 数 / ノードコア数 / CPU GPU 数 / ノード 128 2 18 4 MPI (Message Passing Interface)

More information

about MPI

about MPI 本日 (4/16) の内容 1 並列計算の概要 並列化計算の目的 並列コンピュータ環境 並列プログラミングの方法 MPI を用いた並列プログラミング 並列化効率 2 並列計算の実行方法 Hello world モンテカルロ法による円周率計算 並列計算のはじまり 並列計算の最初の構想を イギリスの科学者リチャードソンが 1922 年に発表 < リチャードソンの夢 > 64000 人を円形の劇場に集めて

More information

バイオプログラミング第 1 榊原康文 佐藤健吾 慶應義塾大学理工学部生命情報学科

バイオプログラミング第 1 榊原康文 佐藤健吾 慶應義塾大学理工学部生命情報学科 バイオプログラミング第 1 榊原康文 佐藤健吾 慶應義塾大学理工学部生命情報学科 ポインタ変数の扱い方 1 ポインタ変数の宣言 int *p; double *q; 2 ポインタ変数へのアドレスの代入 int *p; と宣言した時,p がポインタ変数 int x; と普通に宣言した変数に対して, p = &x; は x のアドレスのポインタ変数 p への代入 ポインタ変数の扱い方 3 間接参照 (

More information

Microsoft PowerPoint - exp2-02_intro.ppt [互換モード]

Microsoft PowerPoint - exp2-02_intro.ppt [互換モード] 情報工学実験 II 実験 2 アルゴリズム ( リスト構造とハッシュ ) 実験を始める前に... C 言語を復習しよう 0. プログラム書ける? 1. アドレスとポインタ 2. 構造体 3. 構造体とポインタ 0. プログラム書ける? 講義を聴いているだけで OK? 言語の要素技術を覚えれば OK? 目的のプログラム? 要素技術 データ型 配列 文字列 関数 オブジェクト クラス ポインタ 2 0.

More information

CS

CS 性能並列計算法特論 第 10 回 情報基盤研究開発センター 野謙 2017 年 7 11 ( ) 成績評価 その他の連絡事項 出席点 5 割 + 期末試験 ( レポート作成 )5 割 講義資料は毎回配布予定です 席した場合, 各 でダウンロードしてください http://mercury.cc.kyushu-u.ac.jp/lecture_2017/ PDF 版をその週の 曜の朝までには公開予定 講義開始後約

More information

プログラミングI第10回

プログラミングI第10回 プログラミング 1 第 10 回 構造体 (3) 応用 リスト操作 この資料にあるサンプルプログラムは /home/course/prog1/public_html/2007/hw/lec/sources/ 下に置いてありますから 各自自分のディレクトリにコピーして コンパイル 実行してみてください Prog1 2007 Lec 101 Programming1 Group 19992007 データ構造

More information

PowerPoint プレゼンテーション

PowerPoint プレゼンテーション 高性能計算基盤 第 7 回 CA1003: 主記憶共有型システム http://arch.naist.jp/htdocs-arch3/ppt/ca1003/ca1003j.pdf Copyright 2019 奈良先端大中島康彦 1 2 3 4 マルチスレッディングとマルチコア 5 6 7 主記憶空間の数が 複数 か 1 つ か 8 ただしプログラムは容易 9 1 つの主記憶空間を共有する場合 10

More information

program7app.ppt

program7app.ppt プログラム理論と言語第 7 回 ポインタと配列, 高階関数, まとめ 有村博紀 吉岡真治 公開スライド PDF( 情報知識ネットワーク研 HP/ 授業 ) http://www-ikn.ist.hokudai.ac.jp/~arim/pub/proriron/ 本スライドは,2015 北海道大学吉岡真治 プログラム理論と言語, に基づいて, 現著者の承諾のもとに, 改訂者 ( 有村 ) が加筆修正しています.

More information

untitled

untitled OpenMP MPI OpenMPI 1 2 http://www.es.jamstec.go.jp/ 3 4 http://www.top500.org/ CPU 3GHz, 10GHz 90nm 65nm, 45nm VLIW L3 Intel Hyperthreading CPU Pentium 5 6 7 8 Cell 23400 90nm 221mm2 SPU 1.52Moore s Law

More information

C プログラミング演習 1( 再 ) 2 講義では C プログラミングの基本を学び 演習では やや実践的なプログラミングを通して学ぶ

C プログラミング演習 1( 再 ) 2 講義では C プログラミングの基本を学び 演習では やや実践的なプログラミングを通して学ぶ C プログラミング演習 1( 再 ) 2 講義では C プログラミングの基本を学び 演習では やや実践的なプログラミングを通して学ぶ 今回のプログラミングの課題 次のステップによって 徐々に難易度の高いプログラムを作成する ( 参照用の番号は よくわかる C 言語 のページ番号 ) 1. キーボード入力された整数 10 個の中から最大のものを答える 2. 整数を要素とする配列 (p.57-59) に初期値を与えておき

More information

Prog1_10th

Prog1_10th 2012 年 6 月 20 日 ( 木 ) 実施ポインタ変数と文字列前回は, ポインタ演算が用いられる典型的な例として, ポインタ変数が 1 次元配列を指す場合を挙げたが, 特に,char 型の配列に格納された文字列に対し, ポインタ変数に配列の 0 番の要素の先頭アドレスを代入して文字列を指すことで, 配列そのものを操作するよりも便利な利用法が存在する なお, 文字列リテラルは, その文字列が格納されている領域の先頭アドレスを表すので,

More information

gengo1-11

gengo1-11 関数の再帰定義 自然数 n の階乗 n! を計算する関数を定義してみる 引数は整数 返却値も整数 n! = 1*2*3*... * (n 1)*n である ただし 0! = 1 とする int factorial(int n) int i, tmp=1; if( n>0 ) for(i=1; i

More information

Microsoft PowerPoint - scls_biogrid_lecture_v2.pptx

Microsoft PowerPoint - scls_biogrid_lecture_v2.pptx スパコン コース並列プログラミング編 善之 E-mail:yoshiyuki.kido@riken.jp 理化学研究所 HPCI 計算 命科学推進プログラム企画調整グループ企画調整チームチーム員 次 1. Message Passing Interface (MPI) 2. Open MP 3. ハイブリッド並列 4. 列計算の並列化 計算機ってなんだ? 計算機 計算に いる機械 ( デジタル 辞泉

More information

(Microsoft PowerPoint \211\211\217K3_4\201i\216R\226{_\211\272\215\342\201j.ppt [\214\335\212\267\203\202\201[\203h])

(Microsoft PowerPoint \211\211\217K3_4\201i\216R\226{_\211\272\215\342\201j.ppt [\214\335\212\267\203\202\201[\203h]) RIKEN AICS Summer School 演習 3 4 MPI による並列計算 2012 年 8 月 8 日 神戸大学大学院システム情報学研究科山本有作理化学研究所計算科学研究機構下坂健則 1 演習の目標 講義 6 並列アルゴリズム基礎 で学んだアルゴリズムのいくつかを,MPI を用いて並列化してみる これを通じて, 基本的な並列化手法と,MPI 通信関数の使い方を身に付ける 2 取り上げる例題と学習項目

More information

PowerPoint プレゼンテーション

PowerPoint プレゼンテーション プログラミング応用演習 第 4 回再帰的構造体 プログラミングを 余談 : 教えることの難しさ 丁寧に説明しないと分かってもらえない 説明すると 小難しくなる学生が目指すべきところプログラム例を説明されて理解できる違うやり方でも良いので自力で解決できる おっけー 動けば良い という意識でプログラミング 正しく動くことのチェックは必要 解答例と自分のやり方との比較が勉強になる 今日のお題 再帰的構造体

More information

Microsoft PowerPoint - MPIprog-C1.ppt [互換モード]

Microsoft PowerPoint - MPIprog-C1.ppt [互換モード] MPI によるプログラミング概要 ( その 1) C 言語編 RIKEN AICS HPC Summer School 2015 中島研吾 ( 東大 情報基盤センター ) 横川三津夫 ( 神戸大 計算科学教育センター ) 1 本 school の目的 並列計算機の使用によって, より大規模で詳細なシミュレーションを高速に実施することが可能になり, 新しい科学の開拓が期待される 並列計算の目的 高速

More information

memo

memo 数理情報工学演習第一 C プログラミング演習 ( 第 5 回 ) 2015/05/11 DEPARTMENT OF MATHEMATICAL INFORMATICS 1 今日の内容 : プロトタイプ宣言 ヘッダーファイル, プログラムの分割 課題 : 疎行列 2 プロトタイプ宣言 3 C 言語では, 関数や変数は使用する前 ( ソースの上のほう ) に定義されている必要がある. double sub(int

More information

PowerPoint プレゼンテーション

PowerPoint プレゼンテーション プログラミング応用演習 第 4 回再帰的構造体 前回の出席確認演習 #include int main() { FILE *fp; int c, linecount, length, maxlength; fp=fopen("/usr/share/dict/words","r"); if (fp == NULL) return 1; linecount=0; length=0;

More information

Microsoft PowerPoint - OpenMP入門.pptx

Microsoft PowerPoint - OpenMP入門.pptx OpenMP 入門 須田礼仁 2009/10/30 初版 OpenMP 共有メモリ並列処理の標準化 API http://openmp.org/ 最新版は 30 3.0 バージョンによる違いはあまり大きくない サポートしているバージョンはともかく csp で動きます gcc も対応しています やっぱり SPMD Single Program Multiple Data プログラム #pragma omp

More information

Microsoft PowerPoint - MPIprog-F1.ppt [互換モード]

Microsoft PowerPoint - MPIprog-F1.ppt [互換モード] MPI によるプログラミング概要 ( その 1) Fortran 言語編 RIKEN AICS HPC Summer School 2015 中島研吾 ( 東大 情報基盤センター ) 横川三津夫 ( 神戸大 計算科学教育センター ) 1 本 school の目的 並列計算機の使用によって, より大規模で詳細なシミュレーションを高速に実施することが可能になり, 新しい科学の開拓が期待される 並列計算の目的

More information

Microsoft PowerPoint - 11.pptx

Microsoft PowerPoint - 11.pptx ポインタと配列 ポインタと配列 配列を関数に渡す 法 課題 : 配列によるスタックの実現 ポインタと配列 (1/2) a が配列であるとき, 変数の場合と同様に, &a[0] [] の値は配列要素 a[0] のアドレス. C 言語では, 配列は主記憶上の連続領域に割り当てられるようになっていて, 配列名 a はその配列に割り当てられた領域の先頭番地となる. したがって,&a[0] と a は同じ値.

More information

株式会社アルウィン C 言語コーディング規約 ver.0.1

株式会社アルウィン C 言語コーディング規約 ver.0.1 C 言語コーディング規約 ver.0.1 1. はじめに本コーディング規約は ( 株 ) アルウィン社内で作成する C 言語ソースコードの可読性 メンテナンス性の向上 丌具合の混入を防ぎやすくするための記述方法及び 推奨する記述方法を記述した文書である 2. 目的 本コーディング規約は ソースコードの可読性 メンテナンス性の向上 丌具合の混入 を可能な限り防ぎ 品質の高いソースコードを作成する一助とすることを目的とする

More information

課題 S1 解説 Fortran 編 中島研吾 東京大学情報基盤センター

課題 S1 解説 Fortran 編 中島研吾 東京大学情報基盤センター 課題 S1 解説 Fortran 編 中島研吾 東京大学情報基盤センター 内容 課題 S1 /a1.0~a1.3, /a2.0~a2.3 から局所ベクトル情報を読み込み, 全体ベクトルのノルム ( x ) を求めるプログラムを作成する (S1-1) file.f,file2.f をそれぞれ参考にする 下記の数値積分の結果を台形公式によって求めるプログラムを作成する

More information

課題 S1 解説 C 言語編 中島研吾 東京大学情報基盤センター

課題 S1 解説 C 言語編 中島研吾 東京大学情報基盤センター 課題 S1 解説 C 言語編 中島研吾 東京大学情報基盤センター 内容 課題 S1 /a1.0~a1.3, /a2.0~a2.3 から局所ベクトル情報を読み込み, 全体ベクトルのノルム ( x ) を求めるプログラムを作成する (S1-1) file.f,file2.f をそれぞれ参考にする 下記の数値積分の結果を台形公式によって求めるプログラムを作成する

More information

memo

memo 計数工学プログラミング演習 ( 第 3 回 ) 2016/04/26 DEPARTMENT OF MATHEMATICAL INFORMATICS 1 内容 ポインタ malloc 構造体 2 ポインタ あるメモリ領域 ( アドレス ) を代入できる変数 型は一致している必要がある 定義時には値は不定 ( 何も指していない ) 実際にはどこかのメモリを指しているので, #include

More information

10-vm1.ppt

10-vm1.ppt オペレーティングシステム ~ 仮想記憶 (1) ~ 山田浩史 hiroshiy @ cc.tuat.ac.jp 2015/06/19 OS の目的 裸のコンピュータを抽象化 (abstraction) し より使いやすく安全なコンピュータとして見せること OS はハードウェアを制御し アプリケーションの効率的な動作や容易な開発を支援する OS がないと メモリをアプリケーション自身が管理しなければならない

More information

情報処理演習 II

情報処理演習 II 2004 年 6 月 15 日 長谷川秀彦 情報処理演習 II Parallel Computing on Distributed Memory Machine 1. 分散メモリ方式並列計算の基礎 複数の CPU がそれぞれのメモリを持ち 独立に動作するコンピュータを分散メモリ方式並列コンピュータ 正確には Distributed Memory Parallel Computer という これには複数の

More information

Taro-ポインタ変数Ⅰ(公開版).j

Taro-ポインタ変数Ⅰ(公開版).j 0. 目次 1. ポインタ変数と変数 2. ポインタ変数と配列 3. ポインタ変数と構造体 4. ポインタ変数と線形リスト 5. 問題 問題 1 問題 2-1 - 1. ポインタ変数と変数 ポインタ変数には 記憶領域の番地が格納されている 通常の変数にはデータが格納されている 宣言 int *a; float *b; char *c; 意味ポインタ変数 aは 整数型データが保存されている番地を格納している

More information

44 6 MPI 4 : #LIB=-lmpich -lm 5 : LIB=-lmpi -lm 7 : mpi1: mpi1.c 8 : $(CC) -o mpi1 mpi1.c $(LIB) 9 : 10 : clean: 11 : -$(DEL) mpi1 make mpi1 1 % mpiru

44 6 MPI 4 : #LIB=-lmpich -lm 5 : LIB=-lmpi -lm 7 : mpi1: mpi1.c 8 : $(CC) -o mpi1 mpi1.c $(LIB) 9 : 10 : clean: 11 : -$(DEL) mpi1 make mpi1 1 % mpiru 43 6 MPI MPI(Message Passing Interface) MPI 1CPU/1 PC Cluster MPICH[5] 6.1 MPI MPI MPI 1 : #include 2 : #include 3 : #include 4 : 5 : #include "mpi.h" 7 : int main(int argc,

More information

Fundamental MPI 1 概要 MPI とは MPI の基礎 :Hello World 全体データと局所データ グループ通信 (Collective Communication) 1 対 1 通信 (Point-to-Point Communication)

Fundamental MPI 1 概要 MPI とは MPI の基礎 :Hello World 全体データと局所データ グループ通信 (Collective Communication) 1 対 1 通信 (Point-to-Point Communication) MPI 超 入門 (C 言語編 ) 東京大学情報基盤センター FORTRAN 編は以下 http://www.cspp.cc.u-tokyo.ac.jp /ohshima/seminars/t2k201111/ (MPI による並列アプリケーション開発入門 2) Fundamental MPI 1 概要 MPI とは MPI の基礎 :Hello World 全体データと局所データ グループ通信 (Collective

More information

Fundamental MPI 1 概要 MPI とは MPI の基礎 :Hello World 全体データと局所データタ グループ通信 (Collective Communication) 1 対 1 通信 (Point-to-Point Communication)

Fundamental MPI 1 概要 MPI とは MPI の基礎 :Hello World 全体データと局所データタ グループ通信 (Collective Communication) 1 対 1 通信 (Point-to-Point Communication) MPI 超 入門 (FORTRAN 編 ) 東京大学情報基盤センター Fundamental MPI 1 概要 MPI とは MPI の基礎 :Hello World 全体データと局所データタ グループ通信 (Collective Communication) 1 対 1 通信 (Point-to-Point Communication) Fundamental MPI 2 MPI とは (1/2)

More information

Microsoft PowerPoint - MPIprog-C1.ppt [互換モード]

Microsoft PowerPoint - MPIprog-C1.ppt [互換モード] MPI によるプログラミング概要 ( その 1) C 言語編 RIKEN AICS HPC Summer School 2014 中島研吾 ( 東大 情報基盤センター ) 横川三津夫 ( 神戸大 計算科学教育センター ) 1 本 school の目的 並列計算機の使用によって, より大規模で詳細なシミュレーションを高速に実施することが可能になり, 新しい科学の開拓が期待される 並列計算の目的 高速

More information

Microsoft PowerPoint - 09.pptx

Microsoft PowerPoint - 09.pptx 情報処理 Ⅱ 第 9 回 2014 年 12 月 22 日 ( 月 ) 関数とは なぜ関数 関数の分類 自作関数 : 自分で定義する. ユーザ関数 ユーザ定義関数 などともいう. 本日のテーマ ライブラリ関数 : 出来合いのもの.printf など. なぜ関数を定義するのか? 処理を共通化 ( 一般化 ) する プログラムの見通しをよくする 機能分割 ( モジュール化, 再利用 ) 責任 ( あるいは不具合の発生源

More information

スレッド

スレッド POSIX スレッド システムプログラミング 2007 年 10 月 22 日 建部修見 スレッドとは? プロセス内の独立したプログラム実行 メモリは共有 ファイルディスクリプタなどプロセス資源は共有 一般にスレッド生成はプロセス生成より軽い プロセス vs スレッド 生成 実行オーバヘッド スレッド小 プロセス大 メモリ 共有 別々 プロセス資源 共有 別々 データ共有 メモリのポインタ渡し (

More information

情報処理 Ⅱ 2007 年 11 月 26 日 ( 月 )

情報処理 Ⅱ 2007 年 11 月 26 日 ( 月 ) 情報処理 Ⅱ 2007 年 11 月 26 日 ( 月 ) 本日学ぶこと 関数と変数 目的 関数を自分で定義し, 変数の利用方法 範囲を明示的に制限することで, 適切な機能分割 ( モジュール化, 再利用 ) を図る. してはいけないこと main 関数のみで 100 行以上のプログラム グローバル変数を駆使するプログラム プログラムを読みやすくする 保守性向上 入 p.109 2 関数 (Function)

More information

Gfarm/MPI-IOの 概要と使い方

Gfarm/MPI-IOの 概要と使い方 MPI-IO/Gfarm のご紹介と現在の開発状況 鷹津冬将 2018/3/2 Gfarm ワークショップ 2018 1 目次 MPI-IO/Gfarm 概要 MPI-IO/Gfarm の開発状況 MVAPICH2 向け MPI-IO/Gfarm MPI-IO/Gfarm の使い方 かんたんなサンプルプログラムと動作確認の方法 既知の不具合 まとめと今後の展望 2018/3/2 Gfarm ワークショップ

More information

プログラミング実習I

プログラミング実習I プログラミング実習 I 05 関数 (1) 人間システム工学科井村誠孝 m.imura@kwansei.ac.jp 関数とは p.162 数学的には入力に対して出力が決まるもの C 言語では入出力が定まったひとまとまりの処理 入力や出力はあるときもないときもある main() も関数の一種 何かの仕事をこなしてくれる魔法のブラックボックス 例 : printf() 関数中で行われている処理の詳細を使う側は知らないが,

More information

MPI 超 入門 (FORTRAN 編 ) 東京大学情報基盤センター C 言語編は以下 /ohshima/seminars/t2k201111/ (MPI による並列アプリケーション開発入門 2)

MPI 超 入門 (FORTRAN 編 ) 東京大学情報基盤センター C 言語編は以下   /ohshima/seminars/t2k201111/ (MPI による並列アプリケーション開発入門 2) MPI 超 入門 (FORTRAN 編 ) 東京大学情報基盤センター C 言語編は以下 http://www.cspp.cc.u-tokyo.ac.jp /ohshima/seminars/t2k201111/ (MPI による並列アプリケーション開発入門 2) Fundamental MPI 1 概要 MPI とは MPI の基礎 :Hello World 全体データと局所データ グループ通信 (Collective

More information

Microsoft PowerPoint - 計算機言語 第7回.ppt

Microsoft PowerPoint - 計算機言語 第7回.ppt 計算機言語第 7 回 長宗高樹 目的 関数について理解する. 入力 X 関数 f 出力 Y Y=f(X) 関数の例 関数の型 #include int tasu(int a, int b); main(void) int x1, x2, y; x1 = 2; x2 = 3; y = tasu(x1,x2); 実引数 printf( %d + %d = %d, x1, x2, y);

More information

memo

memo 計数工学プログラミング演習 ( 第 3 回 ) 2017/04/25 DEPARTMENT OF MATHEMATICAL INFORMATICS 1 内容 ポインタの続き 引数の値渡しと参照渡し 構造体 2 ポインタで指されるメモリへのアクセス double **R; 型 R[i] と *(R+i) は同じ意味 意味 R double ** ポインタの配列 ( の先頭 ) へのポインタ R[i]

More information

Microsoft Word - no202.docx

Microsoft Word - no202.docx 1.4 ポインタと配列 ポインタ変数は前回説明したように 値の入っているアドレスを示す変数です では 配列はどの ようにメモリ上に格納されるか調べてみましょう ex07.c /* ポインタと配列の関係 */ int a[3]={1, 2, 3; /* int 型の大きさ 3 の配列として宣言 */ int *i; /* int 型へのポインタとして宣言 */ double x[3] = {1.0,

More information

Microsoft PowerPoint - MPIprog-C [互換モード]

Microsoft PowerPoint - MPIprog-C [互換モード] MPI によるプログラミング概要 課題 S1 S2 出題 C 言語編 2012 年夏季集中講義中島研吾 並列計算プログラミング (616-2057) 先端計算機演習 (616-4009) 1 本授業の理念 より 並列計算機の使用によって, より大規模で詳細なシミュレーションを高速に実施することが可能になり, 新しい科学の開拓が期待される 並列計算の目的 高速 大規模 大規模 の方が 新しい科学 という観点からのウェイトとしては高い

More information

研究背景 大規模な演算を行うためには 分散メモリ型システムの利用が必須 Message Passing Interface MPI 並列プログラムの大半はMPIを利用 様々な実装 OpenMPI, MPICH, MVAPICH, MPI.NET プログラミングコストが高いため 生産性が悪い 新しい並

研究背景 大規模な演算を行うためには 分散メモリ型システムの利用が必須 Message Passing Interface MPI 並列プログラムの大半はMPIを利用 様々な実装 OpenMPI, MPICH, MVAPICH, MPI.NET プログラミングコストが高いため 生産性が悪い 新しい並 XcalableMPによる NAS Parallel Benchmarksの実装と評価 中尾 昌広 李 珍泌 朴 泰祐 佐藤 三久 筑波大学 計算科学研究センター 筑波大学大学院 システム情報工学研究科 研究背景 大規模な演算を行うためには 分散メモリ型システムの利用が必須 Message Passing Interface MPI 並列プログラムの大半はMPIを利用 様々な実装 OpenMPI,

More information

Microsoft PowerPoint - ishikawa.ppt

Microsoft PowerPoint - ishikawa.ppt 並列処理と MPI 通信ライブラリ入門 東京大学石川裕 目次 並列プログラムの分類 MPI 通信ライブラリの概要 MPI 通信ライブラリを使った簡単なプログラム例 性能指標 様々なMPI 通信ライブラリ性能 Point to Point 遅延 & バンド幅 NASA 並列ベンチマーク結果 2006/3/3 2 並列プログラムの分類 データ並列 気象予測 原子炉シミュレーション 車 飛行機の設計 天体

More information

RX ファミリ用 C/C++ コンパイラ V.1.00 Release 02 ご使用上のお願い RX ファミリ用 C/C++ コンパイラの使用上の注意事項 4 件を連絡します #pragma option 使用時の 1 または 2 バイトの整数型の関数戻り値に関する注意事項 (RXC#012) 共用

RX ファミリ用 C/C++ コンパイラ V.1.00 Release 02 ご使用上のお願い RX ファミリ用 C/C++ コンパイラの使用上の注意事項 4 件を連絡します #pragma option 使用時の 1 または 2 バイトの整数型の関数戻り値に関する注意事項 (RXC#012) 共用 RX ファミリ用 C/C++ コンパイラ V.1.00 Release 02 ご使用上のお願い RX ファミリ用 C/C++ コンパイラの使用上の注意事項 4 件を連絡します #pragma option 使用時の 1 または 2 バイトの整数型の関数戻り値に関する注意事項 (RXC#012) 共用体型のローカル変数を文字列操作関数で操作する場合の注意事項 (RXC#013) 配列型構造体または共用体の配列型メンバから読み出した値を動的初期化に用いる場合の注意事項

More information