近況: Phoenixモデル上の データ並列プログラム (副題: Top500@homeへの第一歩?) 遠藤敏夫 背景: Grid Gridツールが徐々に一般的に(Globus, Nimrod…) でも、ちょっと複雑な並列プログラムが書きにくい 古典的な並列計算研究ではGridに対応しきれない 多数のノード、ノード増減 ヘテロ性 セキュリティ Gridの特徴に対応しつつ、古典的並列に迫る性能 は可能か? TOP500(www.top500.org)とは 速いスーパーコンピュータ上位500位 古典的並列の祭典? Linpack(密行列連立一次方程式)のGflopsにより決定 データ依存関係が多いので、seti@homeよりは難しい ちなみに2002/6現在、 1位: 地球シミュレータ (35,860GFlops) 2位: ASCI White (7,226GFlops) 47位: 松岡研480CPUクラスタ (716GFlops) 現状 Phoenixモデル上でLinpackも どきを記述 LU分解のみ、pivotingなし 記述を楽にするために以下の モジュール作成 分散行列 集団通信 性能はまだヘボヘボ Ultra SPARC 750MHz ×16上で、 0.50GFlops アプリケーション 分散行列 モジュール 集団通信 モジュール Phoenix通信 モジュール 発表の概要 普通のモデルとPhoenixモデル LU分解と、単純な並列化 集団通信 ブロードキャストを用いた場合 部分ブロードキャストを用いた場合 まとめ 普通の メッセージパッシングモデル MPI (www.mpi-forum.org) 汎用メッセージパッシングAPI仕様 物理ノードがそのまま見えるモデル ノードIDは0~P-1 ノード数増減への対応はプログラマの責任 API MPI_Send: 送信 MPI_Recv: 受信 MPI_Comm_Rank: ノードID取得 集団通信(broadcastなど) など Phoenixモデル [田浦01] 仮想ノード空間([0,264)など)を物理ノードに分配 物理ノード増減 = 仮想ノードのやりとり バケツリレーによりメッセージを配送 [0000,3FFF] [8000,BFFF] [8000,FFFF] [C000,FFFF] [4000,7FFF] 仮想ノード数が莫大な点が、のちのち話題に Phoenix通信API P_send(dest, msg) 仮想ノードdestにmsgを送信 (dest, msg) = P_recv() 自分あてのメッセージを一つ受信 vpset = P_get_assigned_vps() 自分の担当する仮想ノード集合を取得 P_set_assigned_vps(vpset) ~を設定 その他、ノード集合演算 etc. 発表の概要 普通のモデルとPhoenixモデル LU分解と、単純な並列化 集団通信 ブロードキャストを用いた場合 部分ブロードキャストを用いた場合 まとめ LU分解 for( i = 0; i < n; i++ ) for( j = i+1; j < n; j++ ){ A[j][i] /= A[i][i]; for( k = i+1; k < n; k++) A[j][k] -= A[i][k] * A[j][i]; } U L A (i) A 全体の計算量はO(n3) 右下ほど計算量が多い → ブロック分割よりサイクリック分割が望ましい 普通のモデルでの並列化 「ノード数<<要素数」なので、要素を分担 ブロック分割 P0 P1 P2 P3 P4 P5 サイクリック分割 (実際にはブロック-サイクリック分割 が使われる) Phoenixモデルでの並列化 「仮想ノード数>>要素数」 に注意 ブロック分割 サイクリック分割 ノード 0000 ノード FFFF 仮想ノード空間に均一に 割り当てる 行列を適当な数に分割し、 左と同様 並列LU分解の実装(単純版) LUアプリケーション P_send/P_recvにより記述 分散行列モジュール ブロック分割・サイクリック分割に対応 仮想ノード移送時にデータも移送(詳細略) Phoenix通信モジュール TCP/IP上に(てきとうに)実装 ノード増・リーフノード減に対応(詳細略) 実験環境 Sun Bladeクラスタ Ultra SPARC 750MHz × 2 × 16ノード (各ノード1CPUのみ使用) gcc –O4 各ノードに均等に仮想ノード割り当て パラメータ 行列サイズ=2048×2048 ブロックサイズ=64×64 サイクリック分割数=8×8 単純版LUの性能 LU 実行時間(s) 60 50 40 30 no bcast 20 10 0 0 4 8 12 ノード数 16 20 no bcast 速度(Gflops) 1CPU peak 0.114 0.225 (4CPU) 4CPUで性能頭打ち 原因の一つは無駄な通信の多さ → ブロードキャストが必要 2n以外で特に遅いのは分割の不規則性のためか? 発表の概要 普通のモデルとPhoenixモデル LU分解と、単純な並列化 グループ通信 ブロードキャストを用いた場合 部分ブロードキャストを用いた場合 まとめ LU分解の通信パターン 第iループ for( j = i+1; j < n; j++ ){ A[j][i] /= A[i][i]; ← 真上の要素を使って更新 for( k = i+1; k < n; k++) A[j][k] -= A[i][k] * A[j][i]; ↑ 真左と真上の要素を使って更新 } 1つの要素を、複数の要素の計算に用いる 近くの要素たちは、おそらく同CPUが担当 → 相手ごとにメッセージを送るのはムダ → ブロードキャストしたい Phoenix上での ブロードキャスト メッセージを仮想ノード空間全体に送信したい 実際のメッセージ数が、O(仮想ノード数)やO(行列要素 数)では困る O(物理ノード数)にしたい 物理ノードグラフを知っていることにする? モデルが複雑に 送信とほぼ同時にノード増減が起こると微妙 → 空間のDivide&conquerで手軽に実現 ブロードキャストアルゴリズム メッセージにあて先ノード 範囲を添付 範囲中の任意の1ノードへ 送信 受信メッセージのあて先が すべて自分→受信 それ以外→2分してやり直し 物理ノード アプリ 集団通信モジュール Phoenixモジュール ブロードキャスト版LUの性能 LU 実行時間(s) 200 150 no bcast all bcast 100 50 0 0 4 8 12 ノード数 16 20 no bcast all bcast 速度(Gflops) 1CPU peak 0.114 0.225 0.115 0.300 2, 4, 8CPU以外で悪化 さすがに仮想ノード全部に送るのはムダ 2n以外でメッセージが増加 (4CPU) (4CPU) 発表の概要 普通のモデルとPhoenixモデル LU分解と、単純な並列化 グループ通信 ブロードキャストを用いた場合 部分ブロードキャストを用いた場合 まとめ 一部へのブロードキャスト MPIの場合 任意のノード集合を設定可能 (ex. CPU0と2と6にブロードキャスト) Phoenixの場合 任意の仮想ノード集合 任意の行列要素 メモリ・時間コスト大 どんな部分集合を考えるか 同じ行・列へのブロードキャストの出番は多 → { p | p0 s i, (0 i c)} のノード集合へ送ればよい これもDivide&conquerでok これ以外の集合については検討課題 部分ブロードキャスト版LUの 性能 LU 60 実行時間(s) 50 40 no bcast all bcast part bcast 30 20 10 0 0 5 10 ノード数 15 20 速度(Gflops) 1CPU no bcast 0.114 all bcast 0.115 part bcast 0.129 これまでより圧倒的に性能向上 ただし8CPUで頭打ち 2n以外ではやはり悪い peak 0.225 0.300 0.516 (4CPU) (4CPU) (8CPU) 関連研究 MPICH-V [Bosilcaら 02] (SC02) Grid上でMPIプログラムが無変更で動作 ノード故障に対応 (checkpointingによる) ノード増減、負荷分散はユーザ責任 HPF2.0仕様 任意の幅のBLOCK分割に対応 [荒木ら 02] (JSPP02) 性能ヘテロに対応した動的負荷分散 (HPF2.0使用) プログラマが性能計測フェーズを記述し、その後処理系が配列 マッピングし直し 負荷分散時に全プロセッサが協調 関連研究 Space filling curve [Peano 1890] d次元から1次元へのマッピング 非均一な並列プログラムの負荷 分散方法として利用される 本研究の文脈では、行・列の部分 集合をどう表現? まとめ Phoenixは高性能計算に向いているか? → 実装がヘボいので結論はまだ出せない 現状では、最高0.516GFlops (台数効果4.0倍) TCP/IP tips 小さいメッセージの到着が遅れる → setsockopt()でTCP_NODELAYを設定 通信量が増えるとデッドロックする read()だけでなくwrite()もブロックする → fcntl()でO_NONBLOCKを設定
© Copyright 2024 ExpyDoc