同一代码同一机器内相同的操作数不同的结果

same operands different results within same code same machine

相同的操作数在fortran90语言中以REAL类型单精度产生不同的结果,似乎是编译器选项给出不同的结果。

real   , dimension(n_pft)    :: sapwood_ratio
real   , dimension(n_pft)    :: qsw
real   , dimension(n_pft)    :: SLA
!these 4 variables are also real type
sla_scale =  0.1 * C2B
sla_inter =  2.4
sla_slope = -0.46
leaf_turnover_rate(2)          = 1.0
leaf_turnover_rate(3)          = 0.5
leaf_turnover_rate(4)          = 1./3.
leaf_turnover_rate(12)          = 1.0
leaf_turnover_rate(13)          = 0.5
leaf_turnover_rate(14)          = 1./3.


  sapwood_ratio(1:17) = 3900.0
    SLA( 2) = 10.0**(sla_inter + sla_slope * log10(12.0/leaf_turnover_rate( 2))) * sla_scale
    SLA( 3) = 10.0**(sla_inter + sla_slope * log10(12.0/leaf_turnover_rate( 3))) * sla_scale
    SLA( 4) = 10.0**(sla_inter + sla_slope * log10(12.0/leaf_turnover_rate( 4))) * sla_scale
    SLA(12) = 10.0**(sla_inter + sla_slope * log10(12.0/leaf_turnover_rate(12))) * sla_scale
    SLA(13) = 10.0**(sla_inter + sla_slope * log10(12.0/leaf_turnover_rate(13))) * sla_scale
    SLA(14) = 10.0**(sla_inter + sla_slope * log10(12.0/leaf_turnover_rate(14))) * sla_scale

到这里为止的一切都完美匹配,但是当我计算时

qsw(1:4)    = SLA(1:4)   / sapwood_ratio(1:4)    
qsw(5:13)   = SLA(5:13)  / sapwood_ratio(5:13)
qsw(14:15)  = SLA(14:15) / sapwood_ratio(14:15)

当我在集群上 运行 时,我得到

qsw(3)  0.0029858516063541173934937
qsw(13) 0.0029858518391847610473633

在我的本地机器上

qsw(3)  0.0029858518391847610473633
qsw(13) 0.0029858518391847610473633

但它们应该具有相同的精确值,就像元素 2/12 和 4/14 一样。此外,其他类似的计算也应该匹配。相同的代码在另一台机器上工作得很好,并且使用相同的包装器 mpif90,但是使用 gfortran 作为加载程序和稍微不同的编译选项,两者都有 -O3。无论如何,为什么这个计算不会在同一台机器上产生相同的结果? 当我使用这些选项编译时,此结果有效但未优化。

USE_INTERF=0
   F_OPTS= -FR -O0 -recursive  -check all -g -debug extended -debug-parameters used        \
     -fpe0 -no-ftz -traceback -ftrapuv -fp-stack-check -implicitnone                 \
           -assume byterecl -warn unused -warn uncalled -warn usage -gen-interfaces
   C_OPTS= -O0 -DLITTLE  -g -traceback
   LOADER_OPTS=$(F_OPTS)

这是产生此错误的另一个选项

USE_INTERF=1
   F_OPTS= -FR -O3 -recursive -traceback -assume byterecl
   C_OPTS= -O3 -DLITTLE -traceback
   F_LOWO_OPTS=-FR -O2 -recursive -traceback -assume byterecl
   LOADER_OPTS=$(F_OPTS)

不一致是由编译选项引起的。单独编译 'O0' 或编译 'O2' 或 'O3' 除了-fp 源,解决问题。这是浮点数学的问题。