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被简单地转换为SINGLEx87 FPU 的内部精度。

于 2013-01-04T14:51:25.410 回答