20.08.2015 Views

高 性 能 並 列 プログラミング 環 境

高性能並列プログラミング環境

高性能並列プログラミング環境

SHOW MORE
SHOW LESS

Create successful ePaper yourself

Turn your PDF publications into a flip-book with our unique Google optimized e-Paper software.

<strong>高</strong> <strong>性</strong> <strong>能</strong> <strong>並</strong> <strong>列</strong> <strong>プログラミング</strong> <strong>環</strong> <strong>境</strong><strong>プログラミング</strong> <strong>環</strong> <strong>境</strong> 特 論2010 年 1 月 21 日建 部 修 見


分 散 メモリ 型 計 算 機CPUCPUCPUとメモリという 一 つの 計算 機 システムが、ネットワークで 結 合 されているシステムMEMCPUNetworkMEMCPUそれぞれの 計 算 機 で 実 行されているプログラムはネットワークを 通 じて、データ(メッセージ)を 交 換 し、 動 作 するMEMMEM 超 <strong>並</strong> <strong>列</strong> (MPP:MassivelyParallel Processing)コンピュータクラスタ 計 算 機


共 有 メモリ 型 計 算 機CPU CPU CPU CPUMEMBUS 複 数 のCPUが 一 つのメモリにアクセスするシステムそれぞれのCPUで 実 行 されているプログラム(スレッド)は、メモリ 上 のデータにお互 いにアクセスすることで、データを 交 換 し、 動 作 する 大 規 模 サーバ,マルチコアUMAとNUMA


<strong>並</strong> <strong>列</strong> 処 理 の 利 点• 計 算 <strong>能</strong> 力 が 増 える– 1つのCPUよりも 多 数 のCPU• メモリの 読 出 し <strong>能</strong> 力 (バンド 幅 )が 増 える– それぞれのCPUが 個 々のメモリを 読 出 すことができる• ディスク 等 、 入 出 力 のバンド 幅 が 増 える– それぞれのCPUが <strong>並</strong> <strong>列</strong> にディスクを 読 み 出 すことができる• キャッシュメモリが 効 果 的 に 利 用 できる– 単 一 のプロセッサではキャッシュにのらないデータでも、 処理 単 位 が 小 さくなることによって、キャッシュを 効 果 的 に 使うことができる• 低 コスト– マイクロプロセッサをつかえばCPU CPU CPU CPUBUSMEMCPU CPUMEM MEMNetworkクラスタ 技 術CPUMEMCPUMEM


<strong>並</strong> <strong>列</strong> <strong>プログラミング</strong>• メッセージ 通 信 (Message Passing)– 分 散 メモリシステム( 共 有 メモリでも 可 )– <strong>プログラミング</strong>が 面 倒 、 難 しい– プログラマがデータの 移 動 を 制 御– プロセッサ 数 に 対 してスケーラブル• 共 有 メモリ (shared memory)– 共 有 メモリシステム(DSMシステムon 分 散 メモリ)– <strong>プログラミング</strong>しやすい( 逐 次 プログラムから)– システムがデータの 移 動 を 行 ってくれる– プロセッサ 数 に 対 してスケーラブルではないことが 多 い


POSIXスレッドによる<strong>プログラミング</strong>• スレッドの 生 成Pthread, Solaris threadfor (t = 1; t < n_thd; t++){r = pthread_create(thd_main, t)}thd_main(0);for (t = 1; t < n_thd; t++)pthread_join();• ループの 担 当 部 分 の 分 割• 足 し 合 わせの 同 期double s; /* global */int n_thd; /* number of threads */int thd_main(int id){ int c, b, e, i; double ss;c = 1000 / n_thd;b = c * id;e = b + c;ss = 0.0;for (i = b; i < e; i++) ss += a[i];pthread_lock();s += ss;pthread_unlock();return (0);}


MPIによる<strong>プログラミング</strong>• MPI (Message Passing Interface)• 現 在 、 分 散 メモリシステムにおける 標 準 的 な<strong>プログラミング</strong>ライブラリ– 100ノード 以 上 では 必 須– 面 倒 だが、 <strong>性</strong> <strong>能</strong> は 出 る• アセンブラで<strong>プログラミング</strong>と 同 じ• メッセージをやり 取 りして 通 信 を 行 う– Send/Receive• コレクティブ 通 信– 総 和 など


MPI – The Message PassingInterface• メッセージ 通 信 インターフェースの 標 準• 1992 年 より 標 準 化 活 動 開 始• 1994 年 ,MPI-1.0リリース– ポータブルな <strong>並</strong> <strong>列</strong> ライブラリ,アプリケーション– 8つの 通 信 モード,コレクティブ 操 作 , 通 信 ドメイン,プロセストポロジ– 100 以 上 の 関 数 が 定 義– C, C++, Fortran– 仕 様 書 http://www.mpi-forum.org/• MPI-2.1が2008 年 9 月 にリリース– 翻 訳 http://phase.hpcc.jp/phase/mpi-j/ml/


SPMD – Single Program, MultipleData• 異 なるプロセッサで 同 一 プログラムを 独 立 に実 行 (cf. SIMD)• 同 一 プログラムで 異 なるデータを 処 理• メッセージ 通 信 でプログラム 間 の 相 互 作 用 を行 うプログラムPMプログラム相 互 結 合 網PMプログラムPMプログラムPMA[0:49] A[50:99] A[100:149] A[150:199]


MPI 実 行 モデル• ( 同 一 の)プロセスを 複 数 のプロセッサで 起 動– プロセス 間 は( 通 信 がなければ) 同 期 しない• 各 プロセスは 固 有 のプロセス 番 号 をもつ• MPIによりプロセス 間 の 通 信 を 行 う(ラプンログクPラ0ム)(ラプンログクPラ1ム)相 互 結 合 網(ラプンログクPラ2ム)(ラプンログクPラ3ム)MMMM


コミュニケータ(1)• 通 信 ドメイン– プロセスの 集 合– プロセス 数 ,プロセス 番 号 (ランク)– プロセストポロジ• 一 次 元 リング, 二 次 元 メッシュ,トーラス,グラフ• MPI_COMM_WORLD– 全 プロセスを 含 む 初 期 コミュニケータ


コミュニケータ(2)• 集 団 通 信 の“スコープ”( 通 信 ドメイン)を 自 由に 作 成 可 <strong>能</strong>• プロセスの 分 割– 2/3のプロセスで 天 気 予 報 ,1/3のプロセスで 次 の初 期 値 計 算• イントラコミュニケータとインターコミュニケータ


集 団 通 信• コミュニケータで 指 定 される 全 プロセス 間 でのメッセージ 通 信• バリア 同 期 (データ 転 送 なし)• 大 域 データ 通 信– 放 送 (broadcast),ギャザ(gather),スキャタ(scatter),全 プロセスへのギャザ(allgather), 転 置 (alltoall)• 縮 約 通 信 (リダクション)– 縮 約 ( 総 和 , 最 大 値 など),スキャン(プレフィックス 計 算 )


• 放 送– ルートプロセスのA[*]を 全 プロセスに 転 送• ギャザ– プロセス 間 で 分 散 した 部 分 配 <strong>列</strong> を 特 定 プロセスに 集 める– allgatherは 全 プロセスに 集 める• スキャタ– ルートプロセスのA[*]をプロセス 間 で 分 散 させる• Alltoall大 域 データ 通 信P0 P1 P2 P3– 二 次 元 配 <strong>列</strong> A[ 分 散 ][*]→A T [ 分 散 ][*]


allgather• 各 プロセスの 部 分 配 <strong>列</strong> を 集 めて 全 プロセスで全 体 配 <strong>列</strong> とするP0P1P2P3


alltoall• ( 行 方 向 に) 分 散 した2 次 元 配 <strong>列</strong> を 転 置 するP0P1P2P3P0P1P2P3


1 対 1 通 信• Point-to-Point 通 信 とも 呼 ばれる• プロセスのペア 間 でのデータ 転 送– プロセスAはプロセスBにデータを 送 信 (send)– プロセスBは(プロセスAから)データを 受 信 (recv)• 型 の 付 いたデータを 転 送– 基 本 データ 型 , 配 <strong>列</strong> , 構 造 体 ,ベクタ,ユーザ 定 義 データ型• コミュニケータ,メッセージタグ, 送 受 信 プロセスランクでsendとrecvの 対 応 を 決 定


1 対 1 通 信 (2)• ブロック 型 通 信– 送 信 バッファが 再 利 用 可 <strong>能</strong> となったら 送 信 終 了– 受 信 バッファが 利 用 可 <strong>能</strong> となったら 受 信 終 了• MPI_Send(A, . . .)が 戻 ってきたらAを 変 更 しても 良 い– 同 一 プロセスの 通 信 用 のバッファにコピーされただけかも– メッセージの 送 信 は 保 証 されない


1 対 1 通 信 の 注 意 点 (1)• メッセージ 到 着 順– (2 者 間 では)メッセージは 追 い 越 されない– 3 者 間 以 上 では 追 い 越 される 可 <strong>能</strong> <strong>性</strong> がある到 着 順 は保 証 される到 着 順 は保 証 されないP0 P1 P0 P1 P2P2は 送 信 元 かタグを 指 定 する必 要 がある


1 対 1 通 信 の 注 意 点 (2)• 公 平 <strong>性</strong>– 通 信 処 理 において 公 平 <strong>性</strong> は 保 証 されない– P1とP2がP0にメッセージ 送 信– P0は 送 信 元 を 指 定 しないで 受 信 を 複 数 発 行• P0はP2からのメッセージばかり 受 信 し,P1からのメッセージがstarvationを 引 き 起 こす 可 <strong>能</strong> <strong>性</strong> がある


非 ブロック 型 1 対 1 通 信• 非 ブロック 型 通 信– post-send, complete-send– post-receive, complete-receive• Post-{send,recv}で 送 信 受 信 操 作 を 開 始• Complete-{send,recv}で 完 了 待 ち• 計 算 と 通 信 のオーバラップを 可 <strong>能</strong> に– マルチスレッドでも 可 <strong>能</strong> だが,しばしばより 効 率 的


1 対 1 通 信 の 通 信 モード• ブロック 型 , 非 ブロック 型 通 信 のそれぞれに 以 下 の通 信 モードがある– 標 準 モード• 実 装 依 存– バッファモード• 送 信 メッセージはバッファリングされる• 送 信 はローカルに 終 了– 同 期 モード• ランデブー– Readyモード• 受 信 が 既 に 発 行 されていることが 保 証 されている 場 合


<strong>並</strong> <strong>列</strong> 処 理 の 例 (1):ホスト 名 表 示#include #include intmain(int argc, char *argv[]){int rank, len;char name[MPI_MAX_PROCESSOR_NAME];}MPI_Init(&argc, &argv);MPI_Comm_rank(MPI_COMM_WORLD, &rank);MPI_Get_processor_name(name, &len);printf("%03d %s¥n", rank, name);MPI_Finalize();return (0);


解 説• mpi.hをインクルード• 各 プロセスはmainからプログラムが 実 行• SPMD (single program, multiple data)– 単 一 のプログラムを 各 ノードで 実 行– 各 プログラムは 違 うデータ(つまり、 実 行 されているプロセスのデータ)をアクセスする• 初 期 化– MPI_Init


解 説 ( 続 き)• プロセスランク 番 号 の 取 得– MPI_Comm_rank(MPI_COMM_WORLD, &rank);– コミュニケータMPI_COMM_WORLDに 対 し, 自 ランクを 取 得– コミュニケータはopaqueオブジェクト, 内 容 は 関 数 でアクセス• ノード 名 を 取 得– MPI_Get_processor_name(name, &len);• 最 後 にexitの 前 で、 全 プロセッサで!MPI_Finalize();


コミュニケータに 対 する 操 作• int MPI_Comm_size(MPI_Comm comm, int*size);• コミュニケータcommのプロセスグループの 総数 をsizeに 返 す• int MPI_Comm_rank(MPI_Comm comm, int*rank);• コミュニケータcommのプロセスグループにおける 自 プロセスのランク 番 号 をrankに 返 す


<strong>並</strong> <strong>列</strong> 処 理 の 例 (2): 総 和 計 算逐 次 計 算for (i = 0; i < 1000; i++)S += A[i]1 2 3 4 1000<strong>並</strong> <strong>列</strong> 計 算+ S1 2 250 251 500 501 750 751 1000+ + + +プロセッサ1 プロセッサ2 プロセッサ3 プロセッサ4+S


#include double A[1000 / N_PE];int main(int argc, char *argv[]){double sum, mysum;}MPI_Init(&argc,&argv);mysum = 0.0;for (i = 0; i < 1000 / N_PE; i++)mysum += A[i];MPI_Reduce(&mysum, &sum, 1, MPI_DOUBLE,MPI_SUM, 0, MPI_COMM_WORLD);MPI_Finalize();return (0);


解 説• 宣 言 されたデータは 各 プロセッサで 重 複 して 取 られる– 1プロセスではプロセス 数 N_PEで 割 った 分 を 確 保• 計 算 ・ 通 信– 各 プロセッサで 部 分 和 を 計 算 して、 集 計– コレクティブ 通 信– MPI_Reduce(&mysum, &sum, 1, MPI_DOUBLE,– MPI_SUM, 0, MPI_COMM_WORLD);– コミュニケータはMPI_COMM_WORLDを 指 定– 各 プロセスのMPI_DOUBLEの 要 素 数 1のmysumに 対 し– リダクションのタイプはMPI_SUM, 結 果 はランク0のsumに


<strong>並</strong> <strong>列</strong> 処 理 の 例 (3):Cpi• 積 分 して、 円 周 率 を 求 めるプログラム• MPICHのテストプログラム– 変 数 nの 値 をBcast– 最 後 にreduction– 計 算 は、プロセスごとに 飛 び 飛 びにやっている


…MPI_Bcast(&n, 1, MPI_INT, 0, MPI_COMM_WORLD);h = 1.0 / n;sum = 0.0;for (i = myid + 1; i


集 団 通 信 : ブロードキャストMPI_Bcast(void *data_buffer, // ブロードキャスト 用 送 受 信 バッファのアドレスint count, // ブロードキャストデータの 個 数MPI_Datatype data_type, // ブロードキャストデータの 型 (*1)int source, // ブロードキャスト 元 プロセスのランクMPI_Comm communicator // 送 受 信 を 行 うグループ);source全 プロセスで 実 行 されなくてはならない


集 団 通 信 : リダクションMPI_Reduce(void *partial_result, // 各 ノードの 処 理 結 果 が 格 納 されているアドレスvoid *result, // 集 計 結 果 を 格 納 するアドレスint count, // データの 個 数MPI_Datatype data_type, // データの 型 (*1)MPI_Op operator, // リデュースオペレーションの 指 定 (*2)int destination, // 集 計 結 果 を 得 るプロセスMPI_Comm communicator // 送 受 信 を 行 うグループ);partial_resultresultdestination全 プロセスで 実 行 されなくてはならないResultを 全 プロセスで 受 け 取 る 場 合 は、MPI_Allreduce


* cpi mpi version */#include #include #include #include doublef(double a){return (4.0 / (1.0 + a * a));}intmain(int argc, char *argv[]){int n = 0, myid, numprocs, i;double PI25DT = 3.141592653589793238462643;double mypi, pi, h, sum, x;double startwtime = 0.0, endwtime;int namelen;char processor_name[MPI_MAX_PROCESSOR_NAME];


MPI_Init(&argc, &argv);MPI_Comm_size(MPI_COMM_WORLD, &numprocs);MPI_Comm_rank(MPI_COMM_WORLD, &myid);MPI_Get_processor_name(processor_name, &namelen);fprintf(stderr, "Process %d on %s¥n", myid, processor_name);if (argc > 1)n = atoi(argv[1]);startwtime = MPI_Wtime();/* broadcast 'n' */MPI_Bcast(&n, 1, MPI_INT, 0, MPI_COMM_WORLD);if (n


}/* calculate each part of pi */h = 1.0 / n;sum = 0.0;for (i = myid + 1; i


<strong>並</strong> <strong>列</strong> 処 理 の 例 (4):laplace• Laplace 方 程 式 の 陽 的 解 法– 上 下 左 右 の4 点 の 平 均 で、updateしていくプログラム– Oldとnewを 用 意 して 直 前 の 値 をコピー– 典 型 的 な 領 域 分 割– 最 後 に 残 差 をとる


行 <strong>列</strong> 分 割 と 隣 接 通 信• 二 次 元 領 域 をブロック 分 割• <strong>境</strong> 界 の 要 素 は 隣 のプロセスが 更 新• <strong>境</strong> 界 データを 隣 接プロセスに 転 送P0P1P2P3


• Send/Receiveブロック 型 1 対 1 通 信MPI_Send(void*send_data_buffer, // 送 信 データが 格 納 されているメモリのアドレスint count, // 送 信 データの 個 数MPI_Datatype data_type, // 送 信 データの 型 (*1)int destination, // 送 信 先 プロセスのランクint tag, // 送 信 データの 識 別 を 行 うタグMPI_Comm communicator // 送 受 信 を 行 うグループ.);MPI_Recv(void*recv_data_buffer, // 受 信 データが 格 納 されるメモリのアドレスint count, // 受 信 データの 個 数MPI_Datatype data_type, // 受 信 データの 型 (*1)int source, // 送 信 元 プロセスのランクint tag, // 受 信 データの 識 別 を 行 うためのタグ.MPI_Comm communicator, // 送 受 信 を 行 うグループ.MPI_Status *status // 受 信 に 関 する 情 報 を 格 納 する 変 数 のアドレス);


メッセージ 通 信• メッセージはデータアドレスとサイズ– 型 がある MPI_INT,MPI_DOUBLE,…– Binaryの 場 合 は、MPI_BYTEで、サイズにbyte 数 を 指 定• Source/destinationは、プロセス 番 号 (rank)とタグを 指 定– 送 信 元 を 指 定 しない 場 合 はMPI_ANY_SOURCEを 指 定– 同 じタグを 持 っているSendとRecvがマッチ– どのようなタグでもRecvしたい 場 合 はMPI_ANY_TAGを指 定• Statusで, 実 際 に 受 信 したメッセージサイズ,タグ,送 信 元 などが 分 かる


非 ブロック 型 通 信• Send/recvを 実 行 して、 後 で 終 了 をチェックする 通 信 方 法– 通 信 処 理 が 裏 で 行 える 場 合 は 計 算 と 通 信 処 理 のオーバラップが 可 <strong>能</strong>int MPI_Isend( void *buf, int count, MPI_Datatype datatype,int dest, int tag, MPI_Comm comm, MPI_Request *request )int MPI_Irecv( void *buf, int count, MPI_Datatype datatype,int source, int tag, MPI_Comm comm, MPI_Request *request )int MPI_Wait ( MPI_Request *request, MPI_Status *status)


プロセストポロジ• int MPI_Cart_create(MPI_Comm comm_old,int ndims, int *dims, int *periods, int reorder,MPI_Comm *comm_cart);• ndims 次 元 のハイパーキューブのトポロジをもつコミュニケータcomm_cartを 作 成• dimsはそれぞれの 次 元 のプロセス 数• periodsはそれぞれの 次 元 が 周 期 的 かどうか• reorderは 新 旧 のコミュニケータでrankの 順 番を 変 更 するかどうか


シフト 通 信 の 相 手 先• int MPI_Cart_shift(MPI_Comm comm, intdirection, int disp, int *rank_source, int*rank_dest);• directionはシフトする 次 元– ndims 次 元 であれば0~ndims-1• dispだけシフトしたとき, 受 け 取 り 先 がrank_source, 送 信 先 がrank_destに 返 る• 周 期 的 ではない 場 合 , <strong>境</strong> 界 を 超 えるとMPI_PROC_NULLが 返 される


* calculate process ranks for ‘down’ and ‘up’ */MPI_Cart_shift(comm, 0, 1, &down, &up);/* recv from down */MPI_Irecv(&uu[x_start-1][1], YSIZE, MPI_DOUBLE, down, TAG_1,comm, &req1);/* recv from up */MPI_Irecv(&uu[x_end][1], YSIZE, MPI_DOUBLE, up, TAG_2,comm, &req2);/* send to down */MPI_Send(&u[x_start][1], YSIZE, MPI_DOUBLE, down, TAG_2, comm);/* send to up */MPI_Send(&u[x_end-1][1], YSIZE, MPI_DOUBLE, up, TAG_1, comm);MPI_Wait(&req1, &status1);MPI_Wait(&req2, &status2);端 (0とnumprocs-1)のプロセッサについてはMPI_PROC_NULLが 指 定 され特 別 な 処 理 は 必 要 ない


** Laplace equation with explict method*/#include #include #include #include /* square region */#define XSIZE 256#define YSIZE 256#define PI 3.1415927#define NITER 10000double u[XSIZE + 2][YSIZE + 2], uu[XSIZE + 2][YSIZE + 2];double time1, time2;void lap_solve(MPI_Comm);int myid, numprocs;int namelen;char processor_name[MPI_MAX_PROCESSOR_NAME];int xsize;二 次 元 対 象 領 域uuは 更 新 用 配 <strong>列</strong>


voidinitialize(){int x, y;}/* 初 期 値 を 設 定 */for (x = 1; x < XSIZE + 1; x++)for (y = 1; y < YSIZE + 1; y++)u[x][y] = sin((x - 1.0) / XSIZE * PI) +cos((y - 1.0) / YSIZE * PI);/* <strong>境</strong> 界 をゼロクリア */for (x = 0; x < XSIZE + 2; x++) {u [x][0] = u [x][YSIZE + 1] = 0.0;uu[x][0] = uu[x][YSIZE + 1] = 0.0;}for (y = 0; y < YSIZE + 2; y++) {u [0][y] = u [XSIZE + 1][y] = 0.0;uu[0][y] = uu[XSIZE + 1][y] = 0.0;}


#define TAG_1 100#define TAG_2 101#ifndef FALSE#define FALSE 0#endifvoid lap_solve(MPI_Comm comm){int x, y, k;double sum;double t_sum;int x_start, x_end;MPI_Request req1, req2;MPI_Status status1, status2;MPI_Comm comm1d;int down, up;int periods[1] = { FALSE };


** Create one dimensional cartesian topology with* nonperiodical boundary*/MPI_Cart_create(comm, 1, &numprocs, periods, FALSE, &comm1d);/* calculate process ranks for 'down' and 'up' */MPI_Cart_shift(comm1d, 0, 1, &down, &up);x_start = 1 + xsize * myid;x_end = 1 + xsize * (myid + 1);• Comm1dを1 次 元 トポロジで 作 成– <strong>境</strong> 界 は 周 期 的 ではない• 上 下 のプロセス 番 号 をup, downに 取 得– <strong>境</strong> 界 ではMPI_PROC_NULLとなる


for (k = 0; k < NITER; k++){/* old


}/* update */for (x = x_start; x < x_end; x++)for (y = 1; y < YSIZE + 1; y++)u[x][y] = .25 * (uu[x - 1][y] + uu[x + 1][y] +uu[x][y - 1] + uu[x][y + 1]);}/* check sum */sum = 0.0;for (x = x_start; x < x_end; x++)for (y = 1; y < YSIZE + 1; y++)sum += uu[x][y] - u[x][y];MPI_Reduce(&sum, &t_sum, 1, MPI_DOUBLE, MPI_SUM, 0, comm1d);if (myid == 0)printf("sum = %g¥n", t_sum);MPI_Comm_free(&comm1d);


intmain(int argc, char *argv[]){MPI_Init(&argc, &argv);MPI_Comm_size(MPI_COMM_WORLD, &numprocs);MPI_Comm_rank(MPI_COMM_WORLD, &myid);MPI_Get_processor_name(processor_name, &namelen);fprintf(stderr, "Process %d on %s¥n", myid, processor_name);}xsize = XSIZE / numprocs;if ((XSIZE % numprocs) != 0)MPI_Abort(MPI_COMM_WORLD, 1);initialize();MPI_Barrier(MPI_COMM_WORLD);time1 = MPI_Wtime();lap_solve(MPI_COMM_WORLD);MPI_Barrier(MPI_COMM_WORLD);time2 = MPI_Wtime();if (myid == 0)printf("time = %g¥n", time2 - time1);MPI_Finalize();return (0);


改 善 すべき 点• 配 <strong>列</strong> の 一 部 しか 使 っていないので、 使 うところだけにする– 配 <strong>列</strong> のindexの 計 算 が 面 倒 になる– 大 規 模 計 算 では 本 質 的 な 点• 1 次 元 分 割 だけだが、2 次 元 分 割 したほうが効 率 がよい– 通 信 量 が 減 る– 多 くのプロセッサが 使 える


MPIとOpenMPの 混 在 <strong>プログラミング</strong>• 分 散 メモリはMPIで、 中 のSMPはOpenMPで• MPI+OpenMP– はじめにMPIのプログラムを 作 る– <strong>並</strong> <strong>列</strong> にできるループを <strong>並</strong> <strong>列</strong> 実 行 指 示 文 を 入 れる• <strong>並</strong> <strong>列</strong> 部 分 はSMP 上 で <strong>並</strong> <strong>列</strong> に 実 行 される。• OpenMP+MPI– OpenMPによるマルチスレッドプログラム– single 構 文 ・master 構 文 ・critical 構 文 内 で、メッセージ 通 信 を 行 う。• Thread-safeなMPIが 必 要• いくつかの 点 で、 動 作 の 定 義 が 不 明 な 点 がある– マルチスレッド <strong>環</strong> <strong>境</strong> でのMPI– OpenMPのthreadprivate 変 数 の 定 義 ?• SMP 内 でデータを 共 用 することができるときに 効 果 がある。– 必 ずしもそうならないことがある(メモリバス 容 量 の 問 題 ?)


おわりに• これからの <strong>高</strong> 速 化 には、 <strong>並</strong> <strong>列</strong> 化 は 必 須• 16プロセッサぐらいでよければ、OpenMP• それ 以 上 になれば、MPIが 必 須– だだし、<strong>プログラミング</strong>のコストと 実 行 時 間 のトレードオフか– 長 期 的 には、MPIに 変 わる<strong>プログラミング</strong> 言 語 が 待 たれる• 科 学 技 術 計 算 の <strong>並</strong> <strong>列</strong> 化 はそれほど 難 しくない– 内 在 する <strong>並</strong> <strong>列</strong> <strong>性</strong> がある– 大 体 のパターンが 決 まっている– <strong>並</strong> <strong>列</strong> プログラムの「デザインパターン」– <strong>性</strong> <strong>能</strong> も…


Coins <strong>環</strong> <strong>境</strong> における <strong>並</strong> <strong>列</strong> 処 理• viola0[1-6].coins.tsukuba.ac.jp– 8コア/ノード、6ノード• 2.93GHz Nehalem×2ソケット– 12GBメモリ/ノード• 1333MHz 2GB DDR3×3チャネル×2– ネットワークバンド 幅 4GB/s• 4x QDR Infiniband– ソフトウェア• CentOS5.4• OpenMPI*、MVAPICH1、MVAPICH2– デフォルトはOpenMPI、mpi-selector-menuで 切 替• gcc, gfortran, Sun JDK6• BLAS, LAPACK, ScaLAPACK


<strong>環</strong> <strong>境</strong> 設 定• sshでログイン 可 <strong>能</strong> に% ssh-keygen –t rsa% cat .ssh/id_rsa.pub >> .ssh/authorized_keys• Known hostsの 作 成 (viola01-ib0などIB 側 のホスト 名 にも)% echo StrictHostKeyChecking no >> .ssh/config% ssh viola01-ib0 hostnameviola01.coins.tsukuba.ac.jp% ssh viola02-ib0 hostnameviola02.coins.tsukuba.ac.jp…% ssh viola06-ib0 hostnameviola06.coins.tsukuba.ac.jp


MPIの 選 択• MPIの 選 択– デフォルトはOpenMPI– 選 択 はmpi-selector-menuコマンドで$ mpi-selector-menuCurrent system default: openmpi-1.3.2-gcc-x86_64Current user default: システムデフォルトはOpenMPI、ユーザデフォルトはなし"u" and "s" modifiers can be added to numeric and "U"commands to specify "user" or "system-wide".1. mvapich-1.1.0-gcc-x86_642. mvapich2-1.2-gcc-x86_643. openmpi-1.3.2-gcc-i3864. openmpi-1.3.2-gcc-x86_64U. Unset defaultQ. QuitMVAPICH2を 選 択Selection (1-4[us], U[us], Q): 2u


コンパイル• MPIプログラムのコンパイル% mpicc –O2 a.c• MPIを 選 択 し 直 した 後 は、 再 コンパイルが 必要 !!!


OpenMPIでの 実 行• ホストファイルの 作 成% cat hosts-openmpiviola01-ib0 slots=8viola02-ib0 slots=8…viola06-ib0 slots=8• 実 行 (OpenMPI)% mpirun –hostfile hosts-openmpi –np 48 a.out


MVAPICHでの 実 行• ホストファイルの 作 成% cat hostsviola01-ib0viola02-ib0…viola06-ib0% cat hosts hosts hosts hosts hosts hosts hosts hosts >hosts-mvapich• 実 行% mpirun_rsh –hostfile hosts-mvapich –np 48 a.out– MVAPICHは 実 行 コマンドがmpirun_rshであることに 注 意 !!


Open Sourceな 処 理 系OpenMP• GNU GCC 4.2 以 降% cc -fopenmp . . .• Omni OpenMPCompiler– http://phase.hpcc.jp/Omni/– 佐 藤 ( 三 ) 先 生MPI• OpenMPI– http://www.openmpi.org/• MPICH2– http://wwwunix.mcs.anl.gov/mpi/mpich2/• YAMPII– http://www.il.is.s.utokyo.ac.jp/yampii/


コンパイル・ 実 行 の 仕 方• コンパイル% mpicc … test.c …– MPI 用 のコンパイルコマンドがある– 手 動 で-lmpiをリンクすることもできる• 実 行% mpiexec –n #procs a.out …– a.outが#procsプロセスで 実 行 される– 以 前 の 処 理 系 ではmpirunが 利 用 され,de factoとなっているが,ポータブルではない% mpirun –np #procs a.out …– 実 行 されるプロセス 群 はマシン 構 成 ファイルなどで 指 定 する– あらかじめデーモンプロセスを 立 ち 上 げる 必 要 があるものも

Hooray! Your file is uploaded and ready to be published.

Saved successfully!

Ooh no, something went wrong!