【入門編】コ配列の宣言と添字アクセス([ ]演算子) – モダンFortran言語仕様と実践実践マスター

「並列処理の常識が覆る」― Fortranコ配列(Coarray)で、メモリの壁を軽やかに飛び越えよう

こんにちは。元宇宙航空研究機関で、数千コアをぶん回して流体解析をしていた者です。

C言語やPythonで並列処理を学んできた皆さんが初めてFortranの「コ配列(Coarray)」を見たとき、おそらくこう感じるはずです。「なぜ、わざわざ角括弧 `[]` なんて特殊な構文があるのか?」と。

MPI(Message Passing Interface)のように、明示的な「送受信」のコードを書くことに疲れ果てたあなたへ。Fortranのコ配列は、「メモリがグローバルに繋がっている」という驚くべき世界観を提示します。今日は、その魔法のような仕組みを泥臭い現場の視点で紐解いていきましょう。

1. コ配列の「角括弧」は、隣の部屋へ繋がる魔法の扉

Fortranにおいて、配列の添字が `( )` であることはご存知ですよね。では、その後ろにある `[ ]` は何でしょう?

結論から言うと、`[ ]` は「他イメージ(別プロセス)へのポータル」です。

! コ配列の宣言例
real, codimension[] :: my_val

この `codimension[]` という記述が「ここから先は分散メモリ空間ですよ」という宣言になります。これだけで、コンパイラは「この変数は他の計算ノードからもアクセスされる可能性がある」と認識し、適切な通信レイヤーを裏で構築し始めます。

添字アクセスの直感的なイメージ

  • `my_val` : 今、自分がいる部屋の冷蔵庫にある値。
  • `my_val[i]` : 隣の部屋(イメージ番号 `i`)の冷蔵庫にある値。

C言語でいうところの「ポインタを飛ばしてネットワーク越しにメモリを読み書きする」という難解な作業が、Fortranでは単なる変数の読み書きに見えてしまう。これがコ配列の恐ろしいまでの強力さなのです。

2. 実践:リモートアクセスを書いてみよう

まずは、最もシンプルな「他イメージから値をもらってくる」コードを見てみましょう。

program hello_coarray
implicit none
! イメージ全体で共有される変数を宣言
integer, codimension[] :: val
integer :: me, np

! 自分のイメージ番号と合計イメージ数を取得
me = this_image()
np = num_images()

! イメージ1が値を初期化し、他のイメージがそれを見に行く
if (me == 1) then
val = 999
end if

! 「同期(Sync)」の重要性:全員がここまで来るのを待つ
sync all

! イメージ2以降が、イメージ1のvalを読み取る
if (me /= 1) then
print , “イメージ”, me, “が取得した値: “, val[1]
end if
end program

なぜ `sync all` が必要なのか?

ここで初心者が最も陥りやすい罠が「通信のタイミング」です。
Pythonの `requests` やMPIのように「送る側」と「受ける側」が握手する必要はありませんが、ハードウェアレベルでは物理的な通信が発生しています。`sync all` は「全員、ここまで処理を終えるまで進むな!」という強力なバリアです。これを忘れると、まだ値が書き込まれていないメモリを読みに行ってしまう「データ競合」が発生します。

3. 現場で生き残るための「非同期アクセス」の極意

`sync all` は便利ですが、計算全体を止めてしまうため、パフォーマンスの観点からは諸刃の剣です。大規模シミュレーションでは、通信を計算と重ね合わせる(オーバーラップ)ことが不可欠になります。

ここで登場するのが `sync images` です。

! 全体同期ではなく、特定のイメージとの同期だけを行う
sync images(1)

! これにより、イメージ1との通信が終われば、
! 他のイメージを待たずに次の計算へ進める

現場の最適化エンジニアは、この「同期の粒度」を極限まで絞り込みます。`sync all` で止まる時間を1ミリ秒でも減らすことが、数万時間かかる計算の実行時間を数日短縮させる鍵になるからです。

4. コンパイラ最適化とメモリ配置の泥臭い話

最後に一つだけ、教科書には載っていない「肌感覚」を伝えます。

Fortranの配列は「列優先(Column-major)」です。これは、多次元配列をメモリ上に敷き詰めるとき、第一添字が一番速く変化するように並べるという伝統的なルールです。コ配列を扱う際も、このメモリの物理的な連続性を意識してください。

  • 連続アクセスを意識せよ: `val[i]` と書いたとき、それが大きな配列の一部分であれば、アクセスするデータがメモリ上で連続しているか確認しましょう。キャッシュミスが起きると、通信速度以前に計算速度が劇的に落ちます。
  • コンパイルフラグの魔術: `gfortran` や `ifort` (現 `ifx`) を使う際は、必ず `-fcoarray=lib` や `-coarray=shared` などのオプションを確認してください。これらは通信ライブラリ(OpenSHMEMなど)を裏で叩くためのスイッチです。これがないと、コ配列はただの「変な記法」に成り下がります。

最後に:まずは「動く」を体験しよう

コ配列は、現代の並列計算において最もエレガントな解の一つです。「MPIの複雑さに疲れた」というエンジニアこそ、Fortranのこの美しい抽象化に触れてみてください。

まずは、お使いの環境で `codimension` を含んだコードを書いて、`num_images()` の値を増やして実行してみてください。自分のPCの中で、複数の「自分」が協力して一つの答えを出す瞬間。その感動が、あなたのエンジニア人生を大きく変えるはずです。

もしビルドで躓いたら、いつでも聞いてくださいね。コンパイラの吐く不可解なエラーメッセージほど、愛おしいものはありませんから。応援しています!

コメント

タイトルとURLをコピーしました