「並列計算の指揮者になろう」:FortranのCoarrayと`THIS_IMAGE()`の魔法
こんにちは。元宇宙航空研究機関で、数十年もの間、スパコンの唸り声と共に生きてきた数値計算屋です。
C言語での`MPI_Comm_rank`や、Pythonの`multiprocessing`に慣れた方にとって、Fortranの並列プログラミングは少し奇妙に見えるかもしれません。しかし、一度その本質を理解すれば、これほど計算機資源のパワーを「無駄なく、かつ直感的」に引き出せる言語は他にありません。
今日は、Fortran並列計算の心臓部である`THIS_IMAGE()`と`NUM_IMAGES()`について、現場の泥臭い知見を交えてお話しします。
—
1. そもそも「イメージ」とは何か?
Fortranの並列モデル(Coarray)では、実行単位を「イメージ(Image)」と呼びます。
他の言語で言う「プロセス」に近い概念ですが、Fortranでは言語仕様レベルで「このプログラムを並列で動かす」ことが組み込まれています。あなたが作成した1つのソースコードが、実行時に「何個のコピーに分身して、それぞれが別のメモリ空間で動くか」を管理するのが、このイメージの役割です。
翻訳で例えると…
- NUM_IMAGES(): 「今、全部で何人の翻訳者が働いているか?」という人数。
- THIS_IMAGE(): 「自分は今、何番目の翻訳者なのか?」というIDカード。
これがあることで、1つのプログラムの中で「君はデータの左端を計算して」「君は右端を計算して」という役割分担が、非常に明快に書けるようになります。
—
2. まずはここから:IDを確認するコード
まずは、自分のイメージ番号と、全体の人数を出力するだけのシンプルなコードを書いてみましょう。
program hello_parallel
implicit none
! 現在のイメージ番号と全イメージ数を取得
integer :: me, total
me = this_image()
total = num_images()
! 書き出しは各イメージから並行して行われる
print , “Hello! 私はイメージ番号:”, me, ” / 全体:”, total
end program hello_parallel
コンパイルと実行のヒント
モダンFortranのコンパイラ(GNU Fortran/gfortranなど)で実行する場合、並列数を指定する必要があります。
コンパイル
gfortran -fcoarray=single hello.f90 -o hello # 単一イメージ用
gfortran -fcoarray=lib -lcaf_mpi hello.f90 -o hello # MPI版(本番用)
実行(例:4プロセスで動かす)
./hello
—
3. 実践:境界条件と負荷分散の泥臭い話
なぜ`THIS_IMAGE()`が重要なのか。それは「配列の領域分割」において、メモリの局所性を守るためです。
例えば、1000個の要素を持つ配列を4つのイメージで計算するとします。このとき、単に「偶数番目はAさん、奇数番目はBさん」とバラバラに計算させてはいけません。キャッシュミスが多発し、メモリ帯域がボトルネックになって計算速度が激減するからです。
「自分の担当分だけを連続領域として持つ」のが、Fortranの鉄則です。
! 各イメージが担当する配列のサイズを計算する例
integer :: my_start, my_end
integer :: total_size, chunk
total_size = 1000
chunk = total_size / num_images()
! 自分の担当範囲を決定する
my_start = (this_image() – 1) chunk + 1
my_end = this_image() chunk
! 最後のイメージは余りを引き受ける処理が必要(現場では必須のテクニック)
if (this_image() == num_images()) my_end = total_size
print , “イメージ”, this_image(), “の担当範囲:”, my_start, “〜”, my_end
—
4. プロの現場からのアドバイス:なぜFortranを選ぶのか?
C言語やPythonで並列化する際、ライブラリの初期化や複雑な通信APIの管理に頭を悩ませたことはありませんか?
FortranのCoarrayは、「言語仕様の中に並列化が埋め込まれている」ため、コンパイラが「どこで通信が発生し、どこでメモリ同期が必要か」を静的に解析できます。これにより、C言語で手動で通信制御を行うよりも、結果として最適化されたバイナリが生成されやすいのです。
最後に、若手エンジニアの皆さんへ
まずは`THIS_IMAGE()`を使って、自分のプログラムの「分身」たちに挨拶をさせることから始めてみてください。
「自分は何番目か?」を知ることは、複雑な数値シミュレーションにおいて、「どこまでが自分の責任範囲か」を定義することと同義です。この責任範囲が明確になった瞬間、あなたの書くコードはスパコン上で最高速で走り出す準備が整ったと言えます。
行き詰まったら、いつでもコンパイラのレポート出力を見てください。Fortranは、あなたが論理的に正しいコードを書けば、必ずそれを最高速度の機械語に翻訳してくれます。
さあ、次はどんな境界条件を計算してみますか?

コメント