導入:なぜ動的な共配列が必要なのか?
並列計算を行う際、計算に必要なデータサイズが事前に決まっているとは限りません。例えば、シミュレーション対象の物理的な規模が実行時に読み込む入力ファイルによって変わる場合などです。固定サイズの配列ではメモリの無駄が生じたり、あるいはメモリ不足でプログラムが落ちたりします。Fortranの「共配列(Coarray)」において、動的なメモリ割り当てを活用することで、各並列プロセス(イメージ)が必要な分だけメモリを確保し、かつ相互にデータを参照し合う柔軟な計算環境を実現できます。
基礎知識:共配列と動的割り当ての仕組み
共配列は、Fortran 2008から標準化された並列プログラミング機能です。通常の配列変数に「コディメンション」と呼ばれる「[:]」という構文を追加することで、その変数が他のプロセスからもアクセス可能な「共有領域」として定義されます。
通常、ALLOCATE文でメモリを確保しますが、共配列の場合は「同期」が重要です。あるプロセスだけがメモリを確保して、他のプロセスが確保できていない状態では通信エラーが発生するため、実行時に各イメージが必要なサイズを決定し、全員で足並みを揃えてメモリを確保する仕組みが不可欠です。
実装:動的な共配列の割り当て手順
動的な共配列を利用する際は、以下のステップを踏みます。
1. 変数宣言時に「allocatable」属性と「[:]」を付与する。
2. 実行時に必要なサイズを計算または入力する。
3. ALLOCATE文の末尾に「[]」を記述し、全イメージで同期してメモリを確保する。
4. 計算が終わったら必ずDEALLOCATEで解放する。
サンプルプログラム:動的な共配列の確保と通信
以下のコードは、各プロセスで異なる(あるいは同じ)サイズを指定してメモリを確保し、別のイメージへデータを渡す簡単な例です。
program dynamic_coarray_example
use iso_fortran_env
implicit none
! 1. 共配列として動的割り当て可能な配列を宣言
real, allocatable :: my_data(:)[:]
integer :: n, i, status
! 2. 各プロセスで確保するサイズを決定(今回は例として全プロセスで10とする)
n = 10
! 3. 動的にメモリを確保([]を記述することで共配列として確保される)
allocate(my_data(n)[], stat=status)
if (status /= 0) stop "メモリ確保に失敗しました"
! 4. 自イメージのデータに値を代入
my_data = real(this_image()) 1.0
! 5. 全イメージでメモリ確保と代入が終わるまで待機(必須)
sync all
! 6. 他のイメージ(例えばイメージ1)のデータを参照する
if (this_image() == 2) then
print , "イメージ2から見たイメージ1のデータ値:", my_data(1)[1]
end if
! 7. 後始末
deallocate(my_data)
end program dynamic_coarray_example
応用・注意点:現場で陥りやすい罠
同期の重要性:
最も多いバグは「同期不足」です。ALLOCATEを実行する前や、他のイメージのデータを参照する直前には、必ず「sync all」や「sync images()」を入れてください。これを怠ると、相手側のメモリがまだ確保されていない状態でアクセスしようとして、セグメンテーションフォールト(強制終了)の原因になります。
メモリの断片化と解放:
大規模な計算で何度もALLOCATEとDEALLOCATEを繰り返すと、メモリの断片化が発生する可能性があります。また、DEALLOCATEを忘れるとメモリリークとなり、長時間の計算でシステムが不安定になります。終了処理は必ず記述する癖をつけましょう。
コンパイル時の注意:
共配列を使用するには、コンパイラに対して並列実行用のフラグが必要です(例:gfortranなら -fcoarray=single または -fcoarray=lib)。環境に合わせて適切なビルド設定を行ってください。

コメント