我一直在尝试在两个嵌套循环内的简单求和操作上应用OpenMP,但到目前为止它产生的结果不正确。我一直在here和here以及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/