Fortran:使用两个不同的编译器编译生成的代码之间的差异

时间:2011-02-10 20:51:09

标签: fortran gfortran

我必须使用Fortran程序,以前使用Microsoft Compaq Visual Fortran 6.6编译。我更愿意与gfortran合作,但我遇到了很多问题。 主要问题是生成的二进制文件具有不同的行为。我的程序接受一个输入文件,然后必须生成一个输出文件。但有时,当使用gfortran编译的二进制文件时,它会在结束之前崩溃,或者给出不同的数值结果。 这是一个由研究人员编写的程序,它使用了大量的浮点数。

所以我的问题是:这两个编译器之间有什么区别可能导致这种问题?

编辑: 我的程序计算一些参数的值,并且有很多次迭代。一开始,一切顺利。经过几次迭代后,会出现一些NaN值(仅在由gfortran编译时)。

编辑: 想想你的每个人的答案。 所以我使用了intel编译器,它通过提供一些有用的错误消息来帮助我。 我的问题的根源是某些变量未正确初始化。看起来在使用compaq visual fortran进行编译时,这些变量会自动将0作为一个值,而使用gfortran(和intel)则需要随机值,这可以解释在后续迭代中累加的一些数值差异。 所以现在解决方案是更好地理解程序以纠正这些缺失的初始化。

4 个答案:

答案 0 :(得分:3)

不同的编译器可以为相同的源代码发出不同的指令。如果数值计算在工作的边界上,则一组指令可能有效,而另一组则无效。大多数编译器都可以选择使用更保守的浮点运算,而不是速度优化 - 我建议检查您用于可用选项的编译器选项。更根本的是,这个问题 - 特别是编译器同意多次迭代但后来发散 - 可能表明程序的数值方法是临界的。简单的解决方案是增加计算的精度,例如从单一到双。也许还会调整参数,例如步长或类似参数。更好的方法是更深入地了解算法,并可能做出更根本的改变。

答案 1 :(得分:2)

我不知道崩溃,但英特尔机器中数字代码结果的一些差异可能是由于一个编译器使用80个双精度数和其他64位双精度数,即使不是变量但可能是临时价值观。此外,浮点计算对执行基本操作的顺序敏感。不同的编译器可能会生成不同的操作序列。

答案 2 :(得分:2)

此类行为可能有多种原因。 我会做的是:

  1. 关闭所有优化

  2. 启用所有调试选项。如果您有权访问,例如intel编译器,使用ifort -CB -CU -debug -traceback。如果你必须坚持gfortran,使用valgrind,它的输出有点不那么人性化,但它通常总比没有好。

  3. 确保没有隐式类型变量,在所有模块和所有代码块中使用implicit none

  4. 使用一致的浮点类型。我个人总是使用real*8作为我的代码中唯一的浮点类型。如果使用外部库,则可能需要更改某些例程的调用签名(例如,BLAS对单精度和双精度变量具有不同的例程名称)。

  5. 如果你幸运的话,只是某些变量没有得到正确的初始化,你会通过其中一种技术来捕捉它。否则,如同M.S.B.建议,更深入地了解该计划的真正作用是必要的。并且,是的,可能需要手动检查算法,从您说“出现一些NaNs值”开始。

答案 3 :(得分:1)

不同类型实现的差异,各种非标准供应商扩展的差异,可能是很多事情。

以下是language features that differ中的一些内容(请参阅 gfortran intel )。写入fortran标准的程序在每个编译器上工作相同,但是很多人不知道什么是标准语言功能,什么是语言扩展,所以使用它们...当编译时出现不同的编译器麻烦

如果您在某处发布代码,我可以快速查看一下;否则,就像这样,“很难说肯定。”