自動的に行うのはそれほど簡単ではありません。DO CONCURRENT
コンストラクトにはforall-headerがあります。これは、複数のループ、インデックス変数の定義、およびマスクを受け入れることができることを意味します。基本的に、次のものを交換する必要があります。
DO CONCURRENT([<type-spec> :: ]<forall-triplet-spec 1>, <forall-triplet-spec 2>, ...[, <scalar-mask-expression>])
<block>
END DO
と:
[BLOCK
<type-spec> :: <indexes>]
!$omp parallel do
DO <forall-triplet-spec 1>
DO <forall-triplet-spec 2>
...
[IF (<scalar-mask-expression>) THEN]
<block>
[END IF]
...
END DO
END DO
!$omp end parallel do
[END BLOCK]
(角括弧内のものは、 forall-header内の対応するパーツの存在に基づいて、オプションです)
<iters 1>*<iters 2>*...
これは、1つの大きなループを独立した反復で並列化するほど効果的ではないことに注意してください。これは、DO CONCURRENT
期待されることです。forall-headerは、ヘッダー内でループインデックスを定義できるtype-specを許可していることにも注意してくださいBLOCK ... END BLOCK
。セマンティクスを保持するには、構成内で全体を囲む必要があります。また、 forall-headerの最後にscalar-mask-exprが存在するかどうかを確認する必要があります。存在する場合は、それを最も内側のループ内に配置する必要があります。IF ... END IF
本体内に配列の割り当てしかない場合は、それをOpenMPディレクティブDO CONCURRENT
に変換してFORALL
使用することもできます。workshare
上記よりもはるかに簡単です。
DO CONCURRENT <forall-header>
<block>
END DO
次のようになります:
!$omp parallel workshare
FORALL <forall-header>
<block>
END FORALL
!$omp end parallel workshare
上記のすべてを考えると、私が考えることができる唯一の体系的な方法は、ソースコードを体系的に調べ、forall-headerとループ本体のコンテンツに基づいて上記の変換された構造の1つを検索し、体系的に置き換えることDO CONCURRENT
です。
編集: OpenMPworkshare
ディレクティブの使用は現在推奨されていません。少なくともIntelFortranコンパイラとGCCは、コンパイル中にOpenMPディレクティブでそれらを囲むことにより、FORALL
OpenMPディレクティブ内のステートメントとコンストラクトをシリアル化し、スピードアップをまったくもたらさないことがわかりました。他のコンパイラはそれを異なる方法で実装するかもしれませんが、移植可能なパフォーマンスを達成するためには、その使用を避ける方が良いでしょう。workshare
single