Ele*_*ltz 2 fortran openmp gfortran
我在以下简单代码中遇到了问题。我正在尝试将OpenMP与GFortran一起使用。代码波纹管的结果x应该是具有和不具有相同的!$OMP语句,因为并行码和序列代码应该输出相同的结果。
program test
implicit none
!INCLUDE 'omp_lib.h'
integer i,j
Real(8) :: x,t1,t2
x=0.0d0
!$OMP PARALLEL DO PRIVATE(i,j) shared(X)
Do i=1,3
Write(*,*) I
!pause
Do j=1,10000000
!$OMP ATOMIC
X=X+2.d0*Cos(i*j*1.0d0)
end do
end do
!$OMP END PARALLEL Do
write(*,*) x
end program test
Run Code Online (Sandbox Code Playgroud)
但是奇怪的是我得到以下结果x:
平行:-3.17822355415XXXXX
序列号: -3.1782235541569084
哪里XXXXX是一些随机数字。每次运行串行代码,都会得到相同的结果(-3.1782235541569084)。我该如何解决?这是由于某些OpenMP工作精度选项引起的吗?
浮点算术不是严格关联的。在FP算术既不a+(b+c)==(a+b)+c也不a*(b*c)==(a*b)*c总是正确的,因为他们都是在实际运算。这是众所周知的,并在SO和网络上其他著名地方的其他问题的答案中得到了广泛解释。在这里,我将不作进一步阐述。
在编写程序后,X计算最终值所依据的操作顺序是不确定的,也就是说,执行之间可能(也可能确实)有所不同。该atomic指令只允许一个线程一次更新X,但它不会对线程到达指令的任何排序约束。
考虑到程序中计算的性质,我相信您在串行和并行执行之间看到的差异可能完全由这种不确定性来解释。
在考虑“修复”之前,您首先应该确定这是一个问题。是什么让您认为串行码的答案是一个真实的答案?如果要向后运行循环(仍然是串行运行)并获得其他答案(很有可能),那么您正在寻找哪个答案?在许多科学计算中(可能是OpenMP的核心领域),可用的数据和所使用的数值方法根本不支持对程序结果准确性的断言,而只有少数重要数字。
如果您仍然认为这是一个必须解决的问题,那么最简单的方法是简单地取出OpenMP指令。