我有几个循环遵循这种模式:
do j = ms,mst
ic = ic + 1
df = mm(j)*data(ic)
dff(1:3)= vec(1:3)*df*qm
end do
如您所见,变量ic
在每个周期都会更新
变量j
使用ic
和df
的结果。如果我使用
OpenMP的原子操作我可能会降低OpenMP的性能。
你知道一种处理这种循环的有效方法吗?
OpenMP的?
答案 0 :(得分:3)
如果ic
除了增量之外没有改变(即data
是一个数组或没有副作用的函数),j
和{之间存在固定关系{1}}:
ic
这可以很容易地并行化,icStart = ic
delta = icStart - ms + 1
do j = ms,mst
ic = delta + j
df = mm(j)*data(ic)
dff(1:3)= vec(1:3)*df*qm
end do
和ic
是线程私有的。你仍然需要注意df
,因为你现在会得到一个竞争条件......
答案 1 :(得分:2)
在您编写代码时,ic
的值在每次迭代时增加1
,就像ms
的值一样。循环的简单并行化,如
!$OMP PARALLEL DO
do j = ms,mst
...
将跨线程分配工作,为每个线程分配j
所需的一组离散值。跨越4个线程的64跳循环(具有ms==1
和mst==64
)的简单静态调度将意味着线程0获得j = 1..16
,线程1获得j = 17..32
,依此类推。
但是,您不必担心ic
的值不会以这种方式整齐划分。从我们提供的示例中可以看出,您想要的行为是ic
的值块与j
的相应数据块一起 - 它们都会增加{{ 1}}在环路的每次旅行中。
也许在您未向我们展示的代码部分中,1
设置为ic
,其中ms+k
是某个整数。在这种情况下,您可以简单地从循环内部删除k
并写入
ic
如果不了解!$OMP PARALLEL DO
do j = ms,mst
df = mm(j)*data(j+k)
dff(1:3)= vec(1:3)*df*qm
end do
和j
之间的关系,就很难提供比这更有针对性的建议。但原则仍然是,如果能够并且避免在并行化循环中出现困难,则将ic
重写为ic
的函数。