正如标题所述,我想使用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)当然我可以计算一个新的数组(并行化),最后总结一下......
提示如何做到最好?
答案 0 :(得分:2)
根据您共享的代码量,我猜“但我不会2”“意味着循环版本会给出不正确的(不同的?)结果。如果您在求和循环之前省略了P_pump_t
到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
已经在循环之后提取了常见的乘法 - 它非常擅长执行这样的优化。
另请注意,在英特尔的OpenMP实现中,WORKSHARE
指令简单地转换为SINGLE
,即代码实际上是串行运行的,而且在使用x87 FPU指令的32位机器上可能会产生不同的结果从串行版本而不是多线程版本,因为x87 FPU的内部精度更高。