4

私は次のようにネストされたforループを呼び出しています:

do ir = 1,Nr
    do iom = iom1, iom2
       xyz(1) = xo(1) + xom(iom)*r
       xyz(2) = xo(2) + yom(iom)*r
       xyz(3) = xo(3) + zom(iom)*r
       call FUNSUB(xyz,Nprop,PropXYZ)
    enddo
enddo

ここFUNSUBで、次の方法でプロパティを評価します。

id = 1
do l=0,lmax
    do m=-l,l
        id = id + 1
        Prop(id) = RHO * Ylm(l,m,xl(1),xl(2),xl(3))
    enddo
enddo

今、私はこれを何かの形で並列化しようとしています

!$OMP parallel do reduction(+:Prop) private(ir, l, m, j, iom, r, wrad, xyz, PropOm, PropOm1, PropXYZ)

ここで見られる他のプライベート変数のいくつかは、簡潔にするために私のサンプルコードから除外されています。ループ内でプロパティが独立して評価されるように、意図的にプライベートにしようとしてlいます。ただし、スレッド間で共有されていることがわかりました。私はいくつかのデバッグオプションを入力し、継続的にの範囲を超えていることを発見し、それもまた、の範囲外にあることを発見しました。mFUNSUBidPropllmaxm(-l,l)

私の質問は、どうすればそれを確認しlmプライベートに保ち、メインルーチンから共有しないようにするのですか?問題は、これらの値を保持するのはまったく異なるサブルーチンであり、どういうわけか、これらの変数のプライベート宣言が引き継がれないことです。

4

2 に答える 2

3

あなたの問題は、Fortran では、ローカル サブルーチン変数が静的になる可能性があり!$OMP、呼び出された関数に伝播しないことだと思います。

呼び出しループにコピー アンド ペーストFUNSUBする場合、つまり手動でインライン化する場合、コードは期待どおりに動作するはずです。

アップデート

FUNSUBローカル変数がコンパイラによってどのように実装されているか、または実装されていないかについて少し読んだ後、最善の選択肢はとして宣言することだと思いますRECURSIVE。これにより、すべてのローカル変数が強制的にスタックに置かれます。つまり、呼び出す各 OpenMP スレッドFUNSUBは、独自のプライベートなローカル変数のセットを持つことになります。

于 2012-06-23T16:30:36.490 に答える
1

FUNSUB の完全なコードを調査する必要があります。OpenMP 領域で外部関数を正しく使用することは問題になりません。外部関数のスコープ内の変数をプライベートとして宣言することはできません。

最新の Fortran コンパイラは、静的な関数のローカル変数を作成しないように指示しない限り、作成しません。これは、コンパイラ スイッチ (並列コードでは大きな NO NO) を使用するか、変数を保存済みとして SAVE として宣言することによって行うことができます。初期化された変数はすべて暗黙的に SAVE されることに注意してください。つまり、次のことを意味します。

   integer :: local = 0

SAVE キーワードがなくても SAVE であり、スレッド間で共有されます。

並行して呼び出されるすべての関数を として宣言することをお勧めしPUREます。私は、すべての非再帰関数を少なくとも効果的に持つことにも賛成PUREです。

于 2012-06-23T19:21:27.003 に答える