220 likes | 288 Views
クラスタコンピューティングの 並列環境と性能. 建部修見 電子技術総合研究所 tatebe@etl.go.jp. クラスタコンピューティング. ETL-Wiz (電子技術総合研究所). ETL-Wiz (1). http://ninf.etl.go.jp/wiz/. ETL-Wiz (2). UPS による自動ブートとシャットダウン 共有コンソール ネットワークスイッチによる完全結合ネットワーク ロードモニタ http://ninf.etl.go.jp/wiz/load-monitor/ ロックファイルによるプロセッサ自動選択. MPI.
E N D
クラスタコンピューティングの並列環境と性能クラスタコンピューティングの並列環境と性能 建部修見 電子技術総合研究所 tatebe@etl.go.jp
クラスタコンピューティング ETL-Wiz(電子技術総合研究所)
ETL-Wiz(1) http://ninf.etl.go.jp/wiz/
ETL-Wiz(2) • UPSによる自動ブートとシャットダウン • 共有コンソール • ネットワークスイッチによる完全結合ネットワーク • ロードモニタ • http://ninf.etl.go.jp/wiz/load-monitor/ • ロックファイルによるプロセッサ自動選択
MPI • メッセージパッシングの標準 [1992-] • 実用性、高効率、ポータビリティ、柔軟性 • 大多数の MPP, NOW 上に実装 • AP1000/1000+/3000, Cenju-3/4, SR-2201/8000, SP-1/2/3, T3D/E, 大多数のWS/PCクラスタ, SMP
MPIの特徴 • SPMDの通信ライブラリインターフェースの標準 • ポータビリティ • コミュニケータ (ライブラリ、集合演算、トポロジ) • FORTRAN77, C(, Fortran90, C++) • 基本データ型のデータサイズに非依存 • 実装方式を規定しない • 抽象度の高いインターフェース • 効率的な実装の余地 • 柔軟性
並列プログラムにおける主要なオーバヘッド • 負荷バランス • アルゴリズム、ランタイムで解決すべき? • SPMDなので規則的な問題であればあまり問題にならない? • 通信遅延
通信遅延隠蔽 • 通信遅延 • 並列、分散環境の主要なオーバヘッド 計算と通信のオーバラップ • ノンブロッキング通信 (MPI) • マルチスレッド実行 (pthread 等)
オーバラップの例 ヤコビ法 jacobi() { int i, j; forall(i = 1; i < N - 1; ++i) forall(j = 1; j < N - 1; ++j) b[i][j] = .25 * (a[i - 1][j] + a[i][j - 1] + a[i][j + 1] + a[i + 1][j]); }
データ依存関係とデータ分散 ヤコビ法のデータ依存関係 2次元ブロックデータ分散
プロセストポロジ 2次元メッシュ #define FALSE (0); MPI_Comm comm2d; static int np[2] = { npy, npx }; static int periods[2] = { FALSE, FALSE }; int reorder = FALSE; MPI_Cart_create(MPI_COMM_WORLD, 2, np, periods, reorder, &comm2d); 次元数 周期的か? 各次元のプロセス数 ランクの変更可?
Naïve code /* 送受信先のプロセスランクの計算 */ MPI_Cart_shift(comm2d, 0, 1, &north, &south); MPI_Cart_shift(comm2d, 1, 1, &west, &east); /* 南北のプロセスとの通信 */ MPI_Sendrecv(&a[1][1], L_N-2, MPI_DOUBLE, north, NORTHTAG, &a[L_N-1][1], L_N-2, MPI_DOUBLE, south, NORTHTAG, comm2d, &st[0]); … /* 東西のプロセスとの通信 */ for(i = 0; i < L_N - 2; ++i) send_buf[i] = a[i + 1][1]; MPI_Sendrecv(send_buf, L_N-2, MPI_DOUBLE, west, WESTTAG, recv_buf, L_N-2, MPI_DOUBLE, east, WESTTAG, comm2d, &st[2]); MPI_Get_count(&st[2], MPI_DOUBLE, &count); for(i = 0; i < L_N - 2; ++i) a[i + 1][L_N - 1] = recv_buf[i]; … /* 計算 */ for(i = 1; i < L_N - 1; ++i) for (j = 1; j < L_N - 1; ++j) b[i][j] = .25 * (a[i-1][j] + a[i][j-1] + a[i][j+1] + a[i+1][j]);
ブロッキング通信 int MPI_Send(buf, count, datatype, dest, tag, comm); void *buf; int count, dest, tag; MPI_Datatype datatype; MPI_Comm comm; int MPI_Recv(buf, count, datatype, source, tag, comm, status); void *buf; int count, source, tag; MPI_Datatype datatype; MPI_Comm comm; MPI_Status *status; buf の内容を読み書きできるようになるまでブロック
ブロッキング送受信の注意点 • バッファリングの有無は規定外 • バッファリングがない場合、 • MPI_Send()は対応する MPI_Recv()の発行が確認され、送信終了までブロック (= MPI_Ssend()) • バッファリングが必要な場合、MPI_Bsend()を利用
ノンブロッキング通信 int MPI_Isend(buf, count, datatype, dest, tag, comm, req); void *buf; int count, dest, tag; MPI_Datatype datatype; MPI_Comm comm; MPI_Request *req; int MPI_Irecv(buf, count, datatype, source, tag, comm, req); void *buf; int count, source, tag; MPI_Datatype datatype; MPI_Comm comm; MPI_Request *req; int MPI_Wait(req, status); int MPI_Test(req, flag, st); MPI_Request *req; MPI_Request req; MPI_Status *status; int *flag; MPI_Status *st;
計算と通信のオーバラップ /* 送受信リクエストの発行 */ MPI_Irecv(…, &req[1]); MPI_Isend(…, &req[0]); /* ローカル計算 */ for(i = 2; i < L_N - 2; ++i) for(j = 2; j < L_N - 2; ++j) b[i][j] = .25 * (a[i-1][j] + a[i][j-1] + a[i][j+1] + a[i+1][j]); /* 送信リクエスト完了待ち */ MPI_Wait(&req[0], &st[0]); /* ローカルデータによる境界点の更新 (略) */ /* 受信リクエスト完了待ち */ MPI_Wait(&req[1], &st[1]); /* リモートデータによる境界点の更新 (略) */
ETL-Wiz による評価(1) N = 200
ETL-Wiz による評価(2) N = 400
ETL-Wiz による評価(3) N = 200
ETL-Wiz による評価(4) N = 400
通信遅延隠蔽のまとめ • N=200(L3キャッシュ以下、計算<通信) • 35%程度性能向上 • N=400(L3キャッシュ以上、計算>通信) • 8%程度性能向上 • 計算順序変更によるキャッシュミス増大 2次元隣接通信では、プロセッサあたり N=400以上は必要