线程间的数字差异(cygwin上的openMP)

Cal*_*lon 5 windows multithreading cygwin fortran openmp

我希望以下fortran代码为所有线程生成相同的结果.我正在使用最新的cygwin处理32位Windows 7.Gfortran版本是4.8.3

program strange
    use omp_lib
    implicit none


    real(kind=8) :: X(3)
    real(kind=8) :: R
    real(kind=8) :: R3

    !$omp parallel private(X,R,R3) default(none)

       X(1)=7.d0
       X(2)=5.3d0
       X(3)=0.d0

       R = dsqrt(X(1)**2 + X(2)**2 +X(3)**2)
       R3 = R*R*R

       write(*,*) "Thread ", omp_get_thread_num(), " results: ", R, R3


    !$omp end parallel

end program
Run Code Online (Sandbox Code Playgroud)

在我的机器上我得到了

radg@pc_radg ~/morralla/terror
$ gfortran terror.f90 -fopenmp

radg@pc_radg ~/morralla/terror
$ ./a.exe
 Thread            1  results:    8.7800911157003387        676.85722410933931
 Thread            0  results:    8.7800911157003370        676.85722410933886
 Thread            2  results:    8.7800911157003387        676.85722410933931
 Thread            3  results:    8.7800911157003387        676.85722410933931
Run Code Online (Sandbox Code Playgroud)

运行几次之后,我看到线程0始终显示相同的结果,与所有其他线程不同.我还观察到,当更改要生成的线程数(导出OMP_NUM_THREADS = x)时,我仍然从线程0得到相同的错误结果

在更改优化级别时,我会得到很好的结果

radg@pc_radg ~/morralla/terror
$ gfortran -O3 terror.f90 -fopenmp

radg@pc_radg ~/morralla/terror
$ ./a.exe
 Thread            0  results:    8.7800911157003387        676.85722410933931
 Thread            1  results:    8.7800911157003387        676.85722410933931
 Thread            3  results:    8.7800911157003387        676.85722410933931
 Thread            2  results:    8.7800911157003387        676.85722410933931
Run Code Online (Sandbox Code Playgroud)

相同的程序在Linux 64位机器(32位和64位二进制文​​件)上正常工作.这种输出的一个例子

 Thread            3  results:    8.7800911157003387        676.85722410933931
 Thread            0  results:    8.7800911157003387        676.85722410933931
 Thread            1  results:    8.7800911157003387        676.85722410933931
 Thread            2  results:    8.7800911157003387        676.85722410933931
Run Code Online (Sandbox Code Playgroud)

知道为什么会在我的特定环境中发生这种情况?

Max*_*ser 1

您是否考虑过,Fortran 双精度通常只有15 个有效数字

\n\n
Thread            1  results:    8.7800911157003387        676.85722410933931\nThread            0  results:    8.7800911157003370        676.85722410933886\nDigits                      :    1 23456789012345--        123 456789012345--\n
Run Code Online (Sandbox Code Playgroud)\n\n

一般来说,这意味着,由于浮点运算的复杂性,第 15 位数字之后的所有内容都不可信。

\n\n

您可能想在这里阅读相关内容。

\n\n

特别是本系列中关于精度的这篇文章,解释了为什么只要不重新编译,就总是在线程 0 上得到相同的结果:

\n\n
\n

...\n 这个保证大多是简单的(如果你还没有重新编译\xe2\x80\x99t,那么你\xe2\x80\x99将得到相同的结果),但精确地确定它是很棘手的。

\n\n

...

\n\n

因此,只要您不做一些古怪的事情,就可以保证相同的机器代码会产生相同的结果。

\n\n

...

\n
\n\n

此外,您可能也会对系列中有关双打的文章感兴趣。

\n