4

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

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

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

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

4

4 回答 4

3

不同的编译器可以为相同的源代码发出不同的指令。如果数值计算处于工作边界,一组指令可能有效,而另一组指令无效。大多数编译器都可以选择使用更保守的浮点运算,而不是速度优化——我建议检查您正在使用的编译器选项以获取可用选项。更根本的是,这个问题——特别是编译器同意多次迭代但随后出现分歧——可能表明程序的数值方法处于临界状态。一个简单的解决方案是提高计算的精度,例如,从单精度到双精度。也许还可以调整参数,例如步长或类似参数。

于 2011-02-11T00:18:47.270 回答
2

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

于 2011-02-10T20:58:12.263 回答
2

这种行为可能有几个原因。我会做的是:

  1. 关闭任何优化

  2. 打开所有调试选项。如果您可以访问例如 intel 编译器,请使用ifort -CB -CU -debug -traceback. 如果您必须坚持使用 gfortran,请使用valgrind,它的输出不太可读,但通常总比没有好。

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

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

如果你幸运的话,只是一些变量没有正确初始化,你会通过这些技术之一捕捉到它。否则,正如 MSB 所建议的,有必要更深入地了解该程序的真正作用。而且,是的,可能需要从您说“出现一些 NaN 值”的点开始手动检查算法。

于 2011-02-11T01:10:35.563 回答
1

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

这里只是一些不同的语言特性(查看gfortranintel)。用fortran标准编写的程序在每个编译器上的工作都是一样的,但是很多人不知道标准语言特性是什么,语言扩展是什么,所以使用它们……当用不同的编译器编译时,就会出现问题.

如果您将代码发布在某个地方,我可以快速查看一下;否则,像这样,很难确定。

于 2011-02-10T22:52:11.220 回答