OpenFOAM並列計算
理論:分割して並べて解く仕組み
概要
コアを増やせば増やすほど、OpenFOAMの計算は速くなるのですか?
ある所までは速くなるが、そこから先はほとんど速くならず、かえって遅くなることもある。OpenFOAMの並列計算は、メッシュを複数の小領域に分け(decomposePar)、各コアが自分の領域を解きながら、領域の境界のセルの値をMPIで隣と交換する仕組みだ。コアを増やすと1コアの担当セルは減るが、境界で交換するデータの割合は増え、さらに線形ソルバーの全体での足し合わせ(内積など)のように全コアがそろうのを待つ処理の時間は減らない。そのため、1コアあたりのセル数がある程度より少なくなると、計算より通信と待ち時間が支配的になる。目安は1コアあたり数万〜十数万セルだが、ネットワーク(InfiniBandか普通のEthernetか)や、ソルバー(圧力の方程式の解き方)で大きく変わる。
Amdahlの法則と境界の割合
S は速度向上率、f は並列化できない処理の割合、N はコア数、E は並列効率、n は1コアあたりのセル数。境界の割合は立方体の領域の6面すべてが他の領域と接すると仮定した上限の目安。
1967年のAmdahlの指摘
並列化の限界を示すAmdahlの法則は、IBMの技術者Gene Amdahlが1967年の学会で述べた議論に由来する。どれだけプロセッサを増やしても、並列にできない部分が残れば速度向上には上限がある、という単純だが重要な指摘だ。のちに1988年、Gustafsonが「問題を大きくすれば並列化できる部分の割合が増える」と反論し、大きな問題ほど多くのコアが活きるという見方も広まった。CFDでは両方が当てはまり、メッシュを大きくするほど多くのコアを効率よく使える。
計算例
速度向上は直列率2%を仮定したAmdahlモデルで、OpenFOAMのベンチマークではない。境界セルの比率は近似的な上限尺度。最適なコア数や費用は実行環境で実測し、物理コア・論理コアの違いも比較する。
例:400万セルの計算(並列化できない割合2%と仮定)
| コア数 | 1コアあたりのセル | 速度向上(Amdahl) | 並列効率 | 境界セルの割合(目安) |
|---|---|---|---|---|
| 8 | 500,000 | 7.0 | 88% | 8% |
| 32 | 125,000 | 19.8 | 62% | 12% |
| 128 | 31,250 | 36.2 | 28% | 19% |
| 512 | 7,812 | 45.6 | 9% | 30% |
並列化できない割合が2%でも、512コアでは効率9%まで下がる。実際には通信の時間も加わるので、効率はさらに低くなりやすい。速度とコア時間(費用)のバランスでは、この例なら32〜128コアあたりが現実的な範囲になる。
64コアで計算したら、32コアより遅くなりました。何が起きているのでしょうか?
いくつか疑う点がある。まず、コアが複数のノード(計算機)にまたがったかどうか。32コアが1台に収まり、64コアで2台になったなら、ノード間の通信が一気に遅くなる。ネットワークが普通のEthernetだと特にその影響が大きい。次に、分割のバランス。scotchで分けても、セル数がそろっていても境界の面の数が領域ごとに大きく違うと、遅い領域を全員が待つことになる。decomposeParの出力に各領域のセル数と境界の面の数が出るので確かめる。3つ目は圧力の線形ソルバーで、GAMG(代数マルチグリッド)は粗いレベルで全体の通信が増えるので、コアが多いときは設定(nCellsInCoarsestLevelなど)を見直す。最後に、ハイパースレッディングの論理コアを数えていないかも確認しよう。物理コア数を超えて走らせても速くはならない。
実務での進め方
- 1コアあたり数万〜十数万セルを目安に、分割数の候補を決める。
- decomposeParDictでscotchを指定して分割し、各領域のセル数と境界の面の数を確かめる。
- 短い計算(数十ステップ)で、分割数を変えて1ステップあたりの時間を測る。
- 効率がおよそ50〜70%を下回らない範囲で、最も速い分割数を選ぶ。
- 結果はreconstructParで結合するか、分割したままParaViewで開く。
「結合しないで後処理する」
大きな計算では、reconstructParで全時刻を結合すると時間もディスクも大きく食う。必要な時刻だけを -time で指定して結合するか、ParaViewで「Decomposed Case」として開けば結合は要らない。関数オブジェクトで力や平均値を計算中に出しておけば、そもそも場のデータを結合する必要がない場合も多い。並列計算では、後処理まで含めて「どのデータをどこで作るか」を最初に決めておくと効率がよい。
よくある間違い
間違いと対策
| 間違い | 起きること | 対策 |
|---|---|---|
| コアを増やしすぎる | 通信で遅くなる | 分割数を実測で決める |
| ノードをまたぐ | 急に遅くなる | ノード内で効率を確認 |
| 分割が偏る | 遅い領域を全員が待つ | scotchと境界面数の確認 |
| 論理コアで数える | 速くならない | 物理コア数で |
| 全時刻を結合 | 時間とディスクを浪費 | 必要時刻のみ・分割のまま表示 |
関連する内容も知りたいです。
関連するページはOpenFOAM入門、OpenFOAMメッシュ生成、OpenFOAM後処理、OpenFOAM燃焼解析が参考になる。
よくある質問
OpenFOAMで並列計算するには?
system/decomposeParDictで分割数(numberOfSubdomains)と分割方法(scotchなど)を指定してdecomposeParを実行し、mpirun -np N ソルバー名 -parallel で計算します。結果は processor0、processor1… のフォルダに分かれて保存されるので、reconstructParで結合するか、ParaViewで分割したまま開きます。
何コアに分ければよいですか?
1コアあたり数万〜十数万セルが目安です。400万セルの例で、並列化できない部分を2%とすると、32コア(1コア12.5万セル)で19.8倍、128コア(3.1万セル)で36倍、512コア(7,800セル)では45.6倍にとどまり、効率は9%まで下がります。実際の速さはネットワークやソルバーで変わるので、少ない分割数から順に測るのが確実です。
分割方法はどれを選べばよいですか?
通常はscotchが無難です。セル数を均等にしつつ、領域の境界の面の数(通信量)が少なくなるように自動で分けます。simpleやhierarchicalは方向ごとの分割数を指定する方法で、単純な形では効率的ですが、複雑な形では境界が増えやすくなります。境界の面の割合は、1コアあたりのセル数が少ないほど大きくなります。
参考資料・検算の位置づけ
掲載値は本文の仮定に基づく教育用の参考計算。資料は理論・設定の参照先であり、本記事の数値を各ソフトで再現した証明ではない。設計・製造の判断には対象条件での検証が必要。
関連トピック
なった
詳しく
報告