1. 導入:なぜ像選択子の制限が重要なのか
Fortranの共配列(Coarray)を用いた並列プログラミングにおいて、最も直感的にやりたくなるのが「範囲指定による複数像への同時アクセス」です。しかし、これを許してしまうと、通信のタイミングやメモリの整合性が複雑化し、並列計算のバグを誘発する温床となります。本記事では、なぜ像選択子には単一の整数しか許されないのか、そしてどのように実装すべきかを解説します。
2. 基礎知識:像選択子(Image Selector)とは
共配列とは、プログラムの複数のインスタンス(像:Image)が同じ変数名で異なるメモリ領域を保持する仕組みです。ある像から別の像のデータを参照するには、変数名の後ろに角括弧 `[]` をつけ、その中に像番号を記述します。これを「像選択子」と呼びます。
重要なルールとして、像選択子は常にスカラ値(単一の整数)でなければなりません。`A[1:5]` のような配列形式の指定は、言語仕様として禁止されています。
3. 実装と解決策:集合演算の活用
複数の像に対して一括でデータを送受信したい場合、個別の像選択子をループで回すのは非効率的です。このようなケースでは、Fortran 2008以降で導入された集合演算(Cooperative Collective Subroutines)を利用するのが正攻法です。
データのブロードキャストには `CO_BROADCAST` を、データの集約には `CO_SUM` や `CO_REDUCE` を使用することで、通信の最適化をコンパイラやランタイムライブラリに任せることができます。
4. サンプルプログラム
以下のコードは、誤った実装(禁止事項)と、集合演算を用いた正しい実装の対比です。
program coarray_example
implicit none
integer :: val
integer :: image_id
image_id = this_image()
val = image_id 10
! — 誤った実装 —
! val = val[1:num_images()] ! コンパイルエラー:範囲指定は不可
! — 正しい実装:CO_BROADCASTによる一括配信 —
! 像1の値を全像へコピーする
call co_broadcast(val, source_image=1)
print , “像”, image_id, “の受け取った値:”, val
end program coarray_example
5. 応用・注意点:現場でのバグ回避
現場でよくあるミスは、ループ内で個別に `A[i] = B` と記述してしまい、意図しない「同期の不整合」が発生することです。
注意点として、集合演算(CO_系ルーチン)は呼び出し元の像すべてがその行に到達しなければデッドロックを引き起こします。
また、通信回数を減らすために、可能な限りデータをパックしてから集合演算を行うのが性能向上(スループットの最大化)の鍵となります。像選択子で無理に複雑な通信を書こうとせず、標準ライブラリの集合演算に任せるという役割分担を徹底しましょう。

コメント