2011-02-10 172 views
4

我必须使用Fortran程序,该程序曾经使用Microsoft Compaq Visual Fortran 6.6进行编译。我宁愿与gfortran一起工​​作,但我遇到了很多问题。 主要问题是生成的二进制文件具有不同的行为。我的程序需要一个输入文件,然后必须生成一个输出文件。但有时候,当使用gfortran编译的二进制文件时,它会在结束之前崩溃,或者给出不同的数值结果。 这是一个由研究人员使用大量浮点数编写的程序。Fortran:使用两种不同的编译器编译生成的代码之间的差异

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

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

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

回答

2

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

  1. 切断对所有调试选项中的任何优化

  2. 开关。如果您有权访问intel编译器,使用ifort -CB -CU -debug -traceback。如果你必须坚持gfortran,使用valgrind,它的输出是不太人性化的,但它往往比没有好。

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

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

如果你很幸运,它只是一些变量没有被正确初始化,你会通过其中一种技术来捕获它。否则,正如M.S.B.建议,对程序真正做的事情有更深入的了解是必要的。而且,是的,可能需要从您说'有些NaNs值出现'的地方开始手动检查算法。

2

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

1

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

这里只是一些language features that differ的(看gfortran英特尔)。编写fortran标准的程序在每个编译器上工作都一样,但很多人不知道什么是标准语言功能,以及什么是语言扩展,因此使用它们......当编译时遇到不同的编译器问题时。

如果您将代码发布到某处,我可以快速查看它;否则,像这样,'很难肯定地说。

3

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

+0

S.B.是否真的有理由使用单精度浮点数? – 2011-02-11 00:50:17