GPU化の前に、CPUだけで約19.3倍高速化:近畿大学の研究用Fortranコード最適化事例

近畿大学の研究用Fortranコードを、Intel oneAPI MKL、OpenMP、計算条件間の依存関係を保った並列分割、CPUコアとメモリの配置、出力統合の改善により、同一40コア環境で399.60秒から20.73秒へ、約19.3倍高速化した事例です。

Share

近畿大学 核反応エネルギー研究室の弓倉 陽様、有友先生のご協力のもと、確率的ダイナミクスを支配する力学パラメータを計算する研究用Fortranコードの高速化に取り組みました。

今回の成果はGPUによるものではありません。GPU化へ進む前にCPUコードを計測し、Intel oneAPI MKLとOpenMPによるループ高速化に加え、計算条件間の依存関係を保った並列分割、CPUコアの割り当て、メモリ配置、分割結果の統合方法を見直した結果、近畿大学の同一40コア環境で399.60秒から20.73秒へ短縮しました。高速化率は約19.3倍です。

結論

比較対象 条件 実行時間
同一環境の基準 vostok26、40物理コア、同一ソース、計算条件の外側分割なし 399.60秒
最終採用構成 vostok26、40物理コア、依存関係を保った28分割 20.73秒

20.73秒は3回測定の中央値です。同一ノード・同一ソースの399.60秒を基準にすると、約19.3倍の高速化になります。

最も効いたのは、計算条件ごとの外側並列化

今回の高速化で最も大きな効果をもたらしたのは、29通りの計算条件を、複数のCPUプロセスで同時に実行する外側並列化です。

同じ最適化ソースを使い、計算条件を分割せず40スレッドで実行した場合は399.60秒でした。これに対し、条件間の依存関係を保った28分割構成では20.73秒となりました。同一ノード・同一ソースの比較で約19.3倍です。この比較から、全体時間を大きく変えた中心的な工夫は、個々のルーチン内部だけでなく、より外側にある計算条件単位の並列性を利用したことだと判断できます。

ただし、29条件をすべて独立させることはできませんでした。先頭の2条件には内部状態の引き継ぎが必要だったため、この2条件は同じプロセスで連続して処理し、残りの27条件を独立して実行しています。

また、28分割は単独で成立するテクニックではありません。28個のワーカーを40物理コアへ重複なく割り当て、NUMAを考慮してメモリを配置し、MKL内部スレッドを1に固定し、分割結果を元の順序へ戻してから後処理する仕組みを組み合わせています。Intel oneAPI MKLやOpenMPによるルーチン内部の高速化も、各ワーカーを短時間で終わらせるために有効でした。

最初に見直したのは、GPUではなく計算構造

対象コードは、多数の形状点と、29通りの計算条件について計算を繰り返します。40スレッドで実行しても、スレッド数を増やすだけでは十分に速くなりませんでした。

プロファイルとソースコードを照合すると、繰り返される固有値計算、固有状態ペアごとの内積、後段処理、そして計算条件を順番に処理する外側ループに、大きな改善余地がありました。

HPCコードでは、CPU使用率が高いことと、CPUが効率よく計算していることは同じではありません。どの処理を数値ライブラリへ任せるか、どこを並列化できるか、どの依存関係を残す必要があるかを分けて考えることが重要です。

改善1:大量の内積計算をMKLの行列積へまとめる

計算の中核部では、固有状態の組み合わせごとに小さな内積が大量に繰り返されていました。これらを数学的に等価な行列積として整理し、Intel oneAPI MKLで一括評価する構成へ変更しました。

細かなループを多数回呼び出す構造から、CPUが効率よく処理できるBLAS-3行列演算へまとめることで、演算器とメモリ階層を使いやすくしました。置き換えは小さな単位で計算結果を比較してから本体へ組み込んでいます。

改善2:固有値計算と後段処理をOpenMP並列化

多数回実行される固有値計算には、Intel oneAPI MKL/LAPACKの数値計算ルーチンを使用しました。OpenMP領域では、固有値ソルバの作業領域をスレッドごとに分離し、共有配列の競合を避けています。

後段処理も、互いに独立して実行できる単位へ分けてOpenMP並列化しました。元の検索処理には共有状態があったため、並列領域ではスレッドごとのローカル検索へ変更し、各計算単位の加算順序は維持しました。

研究コードの並列化では、ループへOpenMP指示文を加えるだけでは不十分です。共有変数、作業配列、加算順序、数値ライブラリ内部のスレッド動作まで確認する必要があります。

改善3:計算条件間の依存関係を保った28分割

29通りの計算条件には大きな外側並列化余地がありました。ただし、すべてを独立させると、先頭の一部条件間で引き継ぐ必要がある内部状態が失われます。

そこで、依存関係を持つ先頭の2条件を同じプロセスに残し、残りの27条件を独立させる28分割構成を採用しました。完全に独立させた方が実行時間だけは短くなりましたが、出力が基準を満たさなかったため採用していません。

速い構成をそのまま採用するのではなく、計算上の依存関係を保てる最速構成を選ぶことが、研究コードでは欠かせません。

改善4:40物理コアを重複なく割り当てる

採用版では28個のワーカープロセスを40物理コアへ割り当てました。処理量に応じて1または2スレッドを割り当て、合計40スレッドとしています。

CPU affinityで各ワーカーのCPU集合を分離し、同じコアを複数ワーカーが奪い合わないようにしました。NUMA配置ではローカルメモリを優先し、外側プロセス並列とOpenMPを使用するため、MKL内部スレッドは1に固定しました。

これにより、プロセス、OpenMP、MKLがそれぞれ勝手にスレッドを増やすオーバーサブスクリプションを防ぎました。

改善5:分割した出力を、元の計算順序へ戻してから統合

計算本体を分割して速くしても、各ワーカーの出力を単純に連結しただけでは、元の処理を再現できない場合があります。

今回は、各ワーカーが後処理前の中間結果を保存し、全ワーカーの終了後に29通りの計算条件を元の順序へ戻し、全体に対して後処理を一度だけ適用する構造へ変更しました。

これにより、並列計算の分割方法と、研究で使用する最終出力の生成方法を分離しました。

近畿大学Vostokの40コア環境で実測

Vostokには、同じ40物理コアでもCPU世代が異なる計算ノードがあります。全ノードで同じ入力、40コア排他使用、同じ28分割構成を用いて測定しました。GPUは使用していません。

計算ノード CPU 実行時間
vostok21-vostok25 Xeon Silver 4316、2ソケット、40物理コア 26.41-26.87秒
vostok26 Xeon Silver 4416+、2ソケット、40物理コア 21.06、20.73、20.24秒
vostok27 Xeon Silver 4416+、2ソケット、40物理コア 21.18、21.03、20.20秒

代表値には、vostok26の3回測定の中央値20.73秒を採用しました。新しいXeon Silver 4416+ノードは、Xeon Silver 4316ノード群より約1.29倍高速でした。

性能だけでなく、計算結果も検証

28分割版は、同じVostokビルドの分割なし40スレッド版を基準として比較しました。最終出力は設定した数値判定をすべて通過しています。

また、研究側が比較に使用する3種類の出力ファイルについても、全29条件を統合して生成し直し、同一ソースの分割なし基準と数値およびファイル単位で一致することを確認しました。

最適化版は既存版を上書きせず、別ディレクトリへ配置しています。性能評価と出力確認を終えるまでは、旧版と並行して利用できる構成です。

この結果がGPU化に与える意味

今回の事例から分かるのは、「HPCコードはGPUへ移植すれば自動的に速くなる」とは限らないということです。

CPU側に直列処理、細かなループ、スレッド競合、NUMA配置の問題、非効率な入出力が残ったままでは、GPUへ移した一部分が速くなっても、プログラム全体では十分な効果が得られない可能性があります。

一方、CPU側の構造を整理したことで、今後GPU化を検討する場合の基準も明確になりました。このコードでは、GPU版はCPUオンリーの20.73秒を十分に下回ることが、次の性能目標になります。

GPUを買うことを先に決めるのではなく、まず実コードを測り、CPU最適化で解決できる部分と、GPUへ移す価値がある部分を分ける。この順序が、研究予算を有効に使ううえでも重要です。

まとめ

今回の約19.3倍高速化は、一つの特別な手法だけで得られたものではありません。

  1. プロファイルから支配的な処理を特定
  2. 大量の内積計算をMKLの行列積へ変更
  3. 固有値計算と後段処理をOpenMP並列化
  4. 計算条件間の依存関係を保った28分割
  5. CPU affinityとNUMA配置による40物理コアの明示的な割り当て
  6. 全29条件を元の順序へ戻してから最終出力を生成
  7. 性能測定と数値検証を同じサイクルで実施

これらを組み合わせることで、GPUを使用せず、同一40コア環境で399.60秒から20.73秒へ短縮できました。

ServerGearの「AI × HPCコード GPU高速化 無料診断」では、Fortran、C、C++、MPI、OpenMPなどの実コード、ビルドログ、実行ログ、プロファイル結果を確認し、CPU最適化、GPU化、または両者の組み合わせから、対象コードに適した次の一手を整理します。

AI × HPCコード GPU高速化 無料診断を見る


本記事は、近畿大学 核反応エネルギー研究室の弓倉 陽様、有友先生に内容をご確認いただいたうえで公開する予定です。