我一直在尝试在两个嵌套循环内的简单求和操作上应用OpenMP,但到目前为止它产生的结果不正确。我一直在herehere以及here中环顾四周。所有人都建议使用reduction子句,但是对于我的情况,它不能产生很大的数量,从而导致segmentation fault,因此不适用于我的情况。

我也尝试过用这种方式发布在here和我自己的问题here中,该问题已解决。两者都不使用reduction,而只是将sumsum变量设置为shared,但这也会产生错误的结果。有什么我想念的吗?何时使用reduction而在面对求和操作时不使用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

不使用ojit_code子句的代码
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子句的功能有误解...

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

关于parallel-processing - OpenMP求和,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/30425117/

10-09 12:32