【问题标题】:OpenMP over Summation基于求和的 OpenMP
【发布时间】:2015-08-06 03:41:45
【问题描述】:

我一直在尝试将 OpenMP 应用于两个嵌套循环内的简单求和运算,但到目前为止它产生了不正确的结果。我一直在查看herehere,也在here。所有人都建议使用reduction 子句,但它不适用于我的情况,因为它会产生非常大的数字,导致segmentation fault

我也试过这种方式张贴在here 和我自己的问题here 已解决。两者都不使用reduction,只是将求和变量设置为shared,但它也会产生不正确的结果。有什么我想念的吗?什么时候使用reduction而不是在面临求和运算时使用?

使用reduction 子句的代码

index = 0
!$OMP PARALLEL DO PRIVATE(iy,ix) REDUCTION(:+index)
do iy = 1, number(2)
    do ix = 1, number(1)
        index = index + 1
        xoutput(index)=xinput(ix)
        youtput(index)=yinput(iy)
    end do
end do
!$OMP END PARALLEL DO

不使用reduction 子句的代码

index = 0
!$OMP PARALLEL DO PRIVATE(iy,ix) SHARED(index)
do iy = 1, number(2)
    do ix = 1, number(1)
        index = index + 1
        xoutput(index)=xinput(ix)
        youtput(index)=yinput(iy)
    end do
end do
!$OMP END PARALLEL DO

【问题讨论】:

  • 应该是REDUCTION(+:index)...
  • 在第二个版本中,index 在线程之间共享,index = index + 1 行会导致竞争条件!

标签: parallel-processing fortran openmp fortran90 gfortran


【解决方案1】:

我认为您对 reduction 子句的作用有误解...

REDUCTION(+:index)

意味着,你将得到正确的总和index最终。在迭代的每一步中,每一个胎面都会有不同的版本,不同的数值!所以减少不适用于在并行部分管理数组索引。

让我试着说明这一点......

下面的循环

!$OMP PARALLEL DO PRIVATE(iy) REDUCTION(+:index)
do iy = 1, number(2)
  index = index + 1
end do
!$OMP END PARALLEL DO

(或多或少)等价于

!$OMP PARALLEL PRIVATE(iy, privIndex) SHARED(index)
!$OMP DO
do iy = 1, number(2)
  privIndex = privIndex + 1
end do
!$OMP END DO

!$OMP CRITICAL
index = index + privIndex
!$OMP END CRITICAL
!$OMP END PARALLEL

您可以看到,在循环期间,所有线程都在不同的变量 privIndex 上工作,这些变量是该线程私有的,并计算局部(部分)总和。最后,使用critical 部分来获取总和以避免竞争条件。

这可能不是编译器所做的,但它让您了解缩减是如何工作的:在第一个循环中,privIndex 不会与您在串行版本中期望的正确索引相对应。


正如 Vladimir 在他的评论中建议的那样,您可以直接计算索引,因为您只是在内部循环中递增它:

!$OMP PARALLEL DO PRIVATE(iy,ix, index)
do iy = 1, number(2)
    do ix = 1, number(1)
        index = (iy-1)*number(1) + ix
        xoutput(index)=xinput(ix)
        youtput(index)=yinput(iy)
    end do
end do
!$OMP END PARALLEL DO

【讨论】:

  • 所以reduction 作为某种同步来确保循环结束时的求和值是正确的?我只是想确定一下,将index 放在私密位置也是不正确的,不是吗?因为求和的值应该按顺序而不是分布在线程上?
  • Reduction 的工作方式与@AlexanderVogt 描述的完全一样,变量的私有副本在构造结束时被减少。私有也无济于事,您将没有同步,并且您会得到一些 index 重复的值。
  • @FrankyDjutanta 为什么不从ixiy 计算index
  • 哦,我只是拿了最简单的一个,因为代码最初是为串行开发的,以前没有想到。非常感谢你们俩。非常感谢。
  • @AlexanderVogt,您忘记在 private 中设置 number(1),因为它在循环内被重复使用。
猜你喜欢
  • 2014-09-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-06-04
  • 2017-08-31
相关资源
最近更新 更多