「並列化のラスボス」を味方にせよ:Coarray Fortranで拓く分散メモリの深淵
こんにちは。かつて宇宙の深淵を数値計算で追いかけていた、元・特任最高数値計算アーキテクトです。
CやPythonで育ったエンジニアの皆さんがFortranの扉を叩くとき、真っ先に立ちはだかるのが「Coarray Fortran (CAF)」という壁でしょう。「なぜ今さらMPIじゃないのか?」「言語仕様に並列処理が組み込まれているとはどういうことか?」と疑問に思うのは当然です。
今日は、その「コ配列(Coarray)」という一見不可解な仕組みを、現場で叩き込まれた血と汗の知見を交えて解き明かしていきます。
—
1. 「イメージ」とは何者か?
まず、Fortranにおける並列の単位である「イメージ(Image)」を理解しましょう。
他の言語では「プロセス」や「スレッド」という言葉が飛び交いますが、Fortranにおけるイメージは「プログラムがコピーされ、それぞれが独立したメモリ空間を持って動き出す、分身のような存在」と考えてください。
- Pythonとの違い: Pythonの`multiprocessing`のように後付けで並列化するのではなく、Fortranはプログラム全体が複数のイメージとして同時にスタートします。
- メモリの考え方: 各イメージは自分の庭(ローカルメモリ)を持っています。隣のイメージの庭を覗くには、この後説明する「コ配列」という特殊なパスポートが必要になるのです。
—
2. コ配列(Coarray)で「隣の庭」にアクセスする
コ配列とは、変数に`[]`(コ添字)をつけたものです。配列がメモリ上の「位置」を指すのに対し、コ配列は「どのイメージの、どこにあるか」という物理的な場所を指し示します。
! 配列Aは、自分のイメージ内でのローカルな箱
! 配列A[:]は、全イメージが持つ「コ配列」としての箱
real, dimension(100), codimension[] :: A
! 自分のイメージのAに値を代入
A = 1.0
! image_index=2のイメージのAに対して、自分のAの値を送る(リモート書き込み)
if (this_image() == 1) then
A[2] = 100.0 ! これだけでネットワーク越しにデータが飛ぶ!
end if
ここで重要なのは、「代入文を書くだけで、コンパイラとランタイムが裏で通信(MPI等)を生成している」という点です。MPIで死ぬほど書いた`MPI_Isend`や`MPI_Recv`の苦労は、ここではもう過去の話なのです。
—
3. 実践:イメージごとの計算と同期
現場で最も注意すべきは「同期(Synchronization)」です。各イメージは独立して走っているため、計算の順序がバラバラだと、まだ計算が終わっていないデータを読み取ってしまう「データ競合」が発生します。
program coarray_sample
use iso_fortran_env
implicit none
! 各イメージで独立して持つ変数
real :: local_val
real, codimension[] :: shared_val
local_val = real(this_image()) 10.0
shared_val = local_val
! 全員がここに到達するまで待機(バリア同期)
sync all
! 他のイメージの値を読み出す(リモート読み出し)
if (this_image() == 1) then
print , “イメージ2の計算結果は: “, shared_val[2]
end if
end program
—
4. 現場の最適化:ここが「泥沼」のポイント
私が長年、スーパーコンピュータのチューニングをしてきて痛感したのは、「コ配列は便利だが、使いすぎるとネットワークがパンクする」ということです。
- 粒度の最適化: リモートアクセス(`A[2] = …`)を何度も繰り返すと、通信オーバーヘッドで計算効率が劇的に落ちます。一度の同期で、大きな塊(チャンク)をまとめて送受信する設計を心がけてください。
- コンパイラの最適化フラグ: `gfortran`であれば `-fcoarray=lib` と `-lcaf_mpi` を忘れずにリンクしましょう。これで裏側がMPIで動くようになります。Intel Fortran (`ifort`/`ifx`) の場合は `-coarray` オプション一つで、最適化された通信ライブラリが自動的に選択されます。
最後に:若手エンジニアへのエール
Fortranのコ配列は、最初は「何を言っているのかわからない」と感じるかもしれません。しかし、これは「データがどこにあるか」をコード上で明確に意識させる、非常に誠実な並列モデルです。
まずは、自分のPCで `num_images=4` のように小規模に動かして、`this_image()` の値をプリントアウトしてみてください。4つの分身が協調して動く様子が見えたとき、数値計算の新しい景色が見えてくるはずです。
泥臭いデバッグの先にこそ、極限のパフォーマンスが待っています。壁にぶつかったら、いつでもここに戻ってきてください。皆さんのコードが、次世代の科学を支える力になることを信じています。

コメント