OpenMP 経由で fortran ループを並列化しようとしています。ループは本質的に 2 つのコマンドのみで構成されます。
do i=1,LSample
calcSslice(Vpot(:,:,i), Sslice)
rpold = rp
combine_rp_matrices (rpold, Sslice, rp)
end do
calcSslice サブルーチンは Vpot(:,:,i) を読み取り、いくつかの計算を実行し、結果を行列 Sslice に格納します。Combine_rp_matrices は rpold と Sslice を使用して rp を更新します。rp は実行変数として機能し、プログラムの目的の出力です。異なる反復からの Sslice 行列が rp と結合される順序は関係ありません。このループを並列化する最初の試みは次のようになりました。
!$OMP PARALLEL DO DEFAULT(SHARED), PRIVATE(Sslice), SCHEDULE(DYNAMIC)
do i=1,LSample
calcSslice(Vpot(:,:,i), Sslice)
!$OMP CRITICAL
rpold = rp
combine_rp_matrices (rpold, Sslice, rp)
!$OMP END CRITICAL
end do
!$OMP END PARALLEL DO
これはコンパイルおよび実行されますが、間違った結果が生成されます。次のコードを使用すると、正しい結果が得られますが、実行がはるかに遅くなります (シリアル化されたコードよりも高速ですが)。
!$OMP PARALLEL DO DEFAULT(SHARED), PRIVATE(Sslice), SCHEDULE(DYNAMIC)
do i=1,LSample
!$OMP CRITICAL(Crit2)
calcSslice(Vpot(:,:,i), Sslice)
!$OMP END CRITICAL(Crit2)
!$OMP CRITICAL
rpold = rp
combine_rp_matrices (rpold, Sslice, rp)
!$OMP END CRITICAL
end do
!$OMP END PARALLEL DO
そのため、calcSslice との同期に問題があるようです。ただし、これがどこで発生するかはよくわかりません。Vpot は calcSslice から読み取られるだけで書き込まれず、Sslice は threadprivate 変数です。calcSslice で使用されるグローバル変数も読み取り専用です。変数 rpold と rp は、DO ループが含まれるサブルーチンのスコープ内で宣言されているため、calcSslice からアクセスすることはできません。calcSslice で宣言された変数は、intent(in)、intent(out)、target、pointer の属性を使用します。
これはどこが間違っていますか?
編集:問題は解決されました。原因は、属性calcSslice
を意味する宣言中の変数の初期化でした。save