2016-08-28 11 views
1

私の問題は、説明した問題と関連しているか、または同一であると思います。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を呼び出しているように見えますが、同時に実行すると競合が発生します。それは理にかなっていますか?

どうすればこの問題を防ぐことができますか?

+1

'hunt'サブルーチンはスレッドセーフではないようです。あなたの 'critical'ディレクティブを' interp2d'の呼び出しから 'interp2d'の' hunt'への呼び出しまで(あるいはできるだけ低いところまで)移動してください。 – Gilles

+1

'interp2d'と' hunt'ルーチンのコードを投稿できますか? 通常、コードを動作させるために 'critical 'が必要なのは、同時に複数のスレッドによって読み書きされる共有リソース(変数など)があるからです。 – smateo

+0

ここで数値レシピからサブルーチンを投稿できるかどうか分かりません。しかし、私は後で簡単なものを投稿します。 これまでのところ、すべてのスレッドが同じスタックにアクセスしていると思いますが、ルーチンの実行時間によってはスタックから正しい順序でダミー変数を読み込んでいないことがあります。それは意味をなさないでしょうか? すべてのスレッドに自分のプライベートスタックを強制的に適用できますか? – Sebastian

答えて

1

Fortran 90+で変数の宣言と初期化を組み合わせると、変数にSAVE属性を付けるという副作用があります。

integer, save :: i 

if (first_invocation) then 
    i = 0 
end if 

SAVE「D変数はルーチンの複数の呼び出しの間に、それらの値を保持し、従ってしばしば静的変数として実装される。

integer :: i = 0 

はほぼ同等です。 OpenMPの暗黙的なデータ共有クラスを管理するルールによって、threadprivateディレクティブにリストされていない限り、そのような変数は共有されます。

OpenMPは、基礎となる言語がFortran 77であっても、上記のセマンティクスを適用する必要があります。

関連する問題