1

タイトルにあるように、OpenMPを使用して合計を並列化したいと思います。私はさまざまなアプローチを探しましたが、それらが何をするのか理解していないか、機能しませんでした。これが私が見つけたものです:

1)

!$OMP PARALLEL WORKSHARE
P_pump_t = 0.5d0 * dcv / pi**2 * sum( k * p_pump_k * dk )
!$OMP END PARALLEL WORKSHARE

動作しますが、何が起こり、どのようなメリットが得られるのかわかりません。

2)

!$OMP PARALLEL DO REDUCTION(+:P_pump_t)
do l = 1, n
P_pump_t = P_pump_t + 0.5d0 * dcv / pi**2 * k(l) * p_pump_k(l) * dk(l)
end do
!$OMP END PARALLEL DO

間違った(1)または3))結果を出します。

3)もちろん、新しい配列(並列化)を計算して、これを最終的に合計することもできます...

それを最もよく行う方法のヒント?

4

1 に答える 1

2

あなたが共有するコードの量に基づいて、私は「しかし私はしません2)」はループバージョンが間違った(異なる?)結果を与えることを意味すると思います。これは、合計ループの前にP_pump_ttoの初期化を省略した場合に発生する可能性があります。0.0また、浮動小数点演算の非結合性のために、両方のコードがわずかに異なる結果を生成する可能性があることに注意してください。たとえば、各演算の後に適用される丸めと正規化のために(a+b)+c、わずかに異なる結果を生成する可能性があります。a+(b+c)このようなものは、コードのベクトル化されたバージョンとよりよく一致します。

P_pump_t = 0.0
!$OMP PARALLEL DO REDUCTION(+:P_pump_t)
do l = 1, n
  P_pump_t = P_pump_t + k(l) * p_pump_k(l) * dk(l)
end do
!$OMP END PARALLEL DO
P_pump_t = 0.5d0 * dcv / pi**2 * P_pump_t

ループの後にすでに一般的な乗算を抽出している可能性ifortは十分にあります。そのような最適化を実行するのはかなり得意です。

また、IntelのOpenMP実装では、WORKSHAREディレクティブは単純に変換されSINGLEます。つまり、コードは実際にはシリアルで実行され、x87 FPU命令を使用する32ビットマシンでは、マルチスレッドバージョンとは異なる結果が期待できます。 x87FPUの内部精度。

于 2013-01-04T14:51:25.410 に答える