在OpenMP中分解循环

时间:2015-05-22 13:51:59

标签: loops fortran openmp fortran90 gfortran

我有几个循环遵循这种模式:

do j = ms,mst    
   ic    = ic + 1                                                                                                                        
   df    = mm(j)*data(ic)
   dff(1:3)= vec(1:3)*df*qm
end do

如您所见,变量ic在每个周期都会更新 变量j使用icdf的结果。如果我使用 OpenMP的原子操作我可能会降低OpenMP的性能。 你知道一种处理这种循环的有效方法吗? OpenMP的?

2 个答案:

答案 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==1mst==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的函数。