私の問題は、説明した問題と関連しているか、または同一であると思います。hereしかし、私は実際に何が起こっているのか分かりません。並列環境でサブルーチンを呼び出す
私のgfortranコンパイラでのOpenMPを使用していると私は実行する次のタスクを持っている:私は、x座標X
及びy座標Y
有する2次元表面上で濃度分布F(X, Y)
を有します。行列F
は、サイズがNx
x Ny
です。
私は座標Xp(i)
とYp(i)
のセットを持っており、これらのポイントに密度F
を補間する必要があります。この問題は、並列化のために行われます。
!$OMP PARALLEL DO DEFAULT(SHARED) PRIVATE(i)
do i=1, Nmax
! Some stuff to be done here
Fint(i) = interp2d(Xp(i), Yp(i), X, Y, F, Nx, Ny)
! Some other stuff to be done here
end do
!$OMP END PARALLEL DO
i
を除くすべてが共有されています。関数interp2d
は、単純な線形補間を行っています。
これは1つのスレッドで正常に動作しますが、マルチスレッドでは失敗します。私はinterp2d
によって呼び出されるNumerical Recipesから取られたhunt
サブルーチンに問題を追跡しました。 hunt
サブルーチンは、基本的にのようなインデックスix
を計算します。これは補間の開始点を得るために必要です。それをマルチスレッドで
は、1つのスレッドがXp(i)
が、その時点までにも近接していないにも関わらず、まったく同じインデックスを取得し、次のhunt
を呼び出しhunt
から正しいインデックスix
と糸を、取得することを、すべての今して起こります。
!$OMP PARALLEL DO DEFAULT(SHARED) PRIVATE(i)
do i=1, Nmax
! Some stuff to be done here
!$OMP CRITICAL
Fint(i) = interp2d(Xp(i), Yp(i), X, Y, F, Nx, Ny)
!$OMP END CRITICAL
! Some other stuff to be done here
end do
!$OMP END PARALLEL DO
をしかし、これは効率を低下させる:
私はCRITICAL
環境を使用してこれを防ぐことができます。たとえば3つのスレッドを使用すると、CRITICAL
環境では平均負荷が1.5になります。私は2.75の負荷平均を持っていませんが、間違った結果、時にはSIGSEGV
ランタイムエラーがあります。
ここでは正確に何が起こっていますか?すべてのスレッドが同じhunt
-subroutineを呼び出しているように見えますが、同時に実行すると競合が発生します。それは理にかなっていますか?
どうすればこの問題を防ぐことができますか?
'hunt'サブルーチンはスレッドセーフではないようです。あなたの 'critical'ディレクティブを' interp2d'の呼び出しから 'interp2d'の' hunt'への呼び出しまで(あるいはできるだけ低いところまで)移動してください。 – Gilles
'interp2d'と' hunt'ルーチンのコードを投稿できますか? 通常、コードを動作させるために 'critical 'が必要なのは、同時に複数のスレッドによって読み書きされる共有リソース(変数など)があるからです。 – smateo
ここで数値レシピからサブルーチンを投稿できるかどうか分かりません。しかし、私は後で簡単なものを投稿します。 これまでのところ、すべてのスレッドが同じスタックにアクセスしていると思いますが、ルーチンの実行時間によってはスタックから正しい順序でダミー変数を読み込んでいないことがあります。それは意味をなさないでしょうか? すべてのスレッドに自分のプライベートスタックを強制的に適用できますか? – Sebastian