Fortran:使用两种不同编译器编译的生成代码之间的差异
我必须编写一个 Fortran 程序,该程序过去是使用 Microsoft Compaq Visual Fortran 6.6 编译的。我更喜欢使用 gfortran,但我遇到了很多问题。 主要问题是生成的二进制文件具有不同的行为。我的程序需要一个输入文件,然后必须生成一个输出文件。但有时,当使用 gfortran 编译的二进制文件时,它会在结束之前崩溃,或者给出不同的数值结果。 这是一个由研究人员编写的程序,其中使用了大量浮点数。
所以我的问题是:这两个编译器之间有什么差异可能导致此类问题?
编辑: 我的程序计算一些参数的值,并且有多次迭代。一开始,一切都很顺利。经过几次迭代后,会出现一些 NaN 值(仅当由 gfortran 编译时)。
编辑: 想一想大家的答案。 所以我使用了英特尔编译器,它通过提供一些有用的错误消息来帮助我。 我的问题的根源是某些变量没有正确初始化。看起来,当使用 compaq Visual fortran 编译时,这些变量自动采用 0 作为值,而使用 gfortran(和 intel)时,它采用随机值,这解释了在以下迭代中累加的一些数值差异。 所以现在的解决方案是更好地理解程序来纠正这些缺失的初始化。
I have to work on a fortran program, which used to be compiled using Microsoft Compaq Visual Fortran 6.6. I would prefer to work with gfortran but I have met lots of problems.
The main problem is that the generated binaries have different behaviours. My program takes an input file and then has to generate an output file. But sometimes, when using the binary compiled by gfortran, it crashes before its end, or gives different numerical results.
This a program written by researchers which uses a lot of float numbers.
So my question is: what are the differences between these two compilers which could lead to this kind of problem?
edit:
My program computes the values of some parameters and there are numerous iterations. At the beginning, everything goes well. After several iterations, some NaN values appear (only when compiled by gfortran).
edit:
Think you everybody for your answers.
So I used the intel compiler which helped me by giving some useful error messages.
The origin of my problems is that some variables are not initialized properly. It looks like when compiling with compaq visual fortran these variables take automatically 0 as a value, whereas with gfortran (and intel) it takes random values, which explain some numerical differences which add up at the following iterations.
So now the solution is a better understanding of the program to correct these missing initializations.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
造成这种行为的原因可能有多种。
我要做的是:
关闭所有优化
打开所有调试选项。如果您有权访问例如英特尔编译器,请使用
ifort -CB -CU -debug -traceback
。如果您必须坚持使用 gfortran,请使用valgrind
,它的输出有点不太可读,但通常总比没有好。确保没有隐式类型变量,在所有模块和所有代码块中使用
implicit none
。使用一致的浮点类型。我个人总是使用
real*8
作为代码中唯一的浮点类型。如果您使用外部库,则可能需要更改某些例程的调用签名(例如,BLAS 对于单精度和双精度变量具有不同的例程名称)。如果幸运的话,这只是某个变量没有正确初始化,您将通过其中一种技术来捕获它。否则,正如 MSB 所建议的那样,有必要更深入地了解该程序的真正用途。而且,是的,可能需要从您所说的“出现一些 NaN 值”的点开始手动检查算法。
There can be several reasons for such behaviour.
What I would do is:
Switch off any optimization
Switch on all debug options. If you have access to e.g. intel compiler, use
ifort -CB -CU -debug -traceback
. If you have to stick to gfortran, usevalgrind
, its output is somewhat less human-readable, but it's often better than nothing.Make sure there are no implicit typed variables, use
implicit none
in all the modules and all the code blocks.Use consistent float types. I personally always use
real*8
as the only float type in my codes. If you are using external libraries, you might need to change call signatures for some routines (e.g., BLAS has different routine names for single and double precision variables).If you are lucky, it's just some variable doesn't get initialized properly, and you'll catch it by one of these techniques. Otherwise, as M.S.B. was suggesting, a deeper understanding of what the program really does is necessary. And, yes, it might be needed to just check the algorithm manually starting from the point where you say 'some NaNs values appear'.
不同的编译器可以为相同的源代码发出不同的指令。如果数值计算处于工作边界,则一组指令可能有效,而另一组则无效。大多数编译器都可以选择使用更保守的浮点运算,而不是速度优化——我建议检查您正在使用的编译器选项以获取可用选项。更根本的是,这个问题——特别是编译器在多次迭代中达成一致但随后出现分歧——可能表明该程序的数值方法处于边缘状态。一个简单的解决方案是提高计算的精度,例如从单精度提高到双精度。也许还可以调整参数,例如步长或类似参数。更好的办法是更深入地了解算法,并可能做出更根本的改变。
Different compilers can emit different instructions for the same source code. If a numerical calculation is on the boundary of working, one set of instructions might work, and another not. Most compilers have options to use more conservative floating point arithmetic, versus optimizations for speed -- I suggest checking the compiler options that you are using for the available options. More fundamentally this problem -- particularly that the compilers agree for several iterations but then diverge -- may be a sign that the numerical approach of the program is borderline. A simplistic solution is to increase the precision of the calculations, e.g., from single to double. Perhaps also tweak parameters, such as a step size or similar parameter. Better would be to gain a deeper understanding of the algorithm and possibly make a more fundamental change.
我不知道崩溃的情况,但英特尔机器中数字代码结果的一些差异可能是由于一个编译器使用 80 位双精度数和其他 64 位双精度数,即使不是变量,而是临时值。此外,浮点计算对基本运算的执行顺序很敏感。不同的编译器可能会生成不同的操作顺序。
I don't know about the crash but some differences in the results of numerical code in an Intel machine can be due to one compiler using 80-doubles and the other 64-bit doubles, even if not for variables but perhaps for temporary values. Moreover, floating-point computation is sensitive to the order elementary operations are performed. Different compilers may generate different sequence of operations.
不同类型实现的差异、各种非标准供应商扩展的差异可能有很多。
这里只是一些不同的语言功能(看看gfortran 和 英特尔)。按照 Fortran 标准编写的程序在每个编译器上的工作方式都是相同的,但是很多人不知道标准语言功能是什么,以及语言扩展是什么,因此使用它们......当使用不同的编译器编译时会出现麻烦。
如果您将代码发布到某个地方,我可以快速查看一下;不然的话,像这样,就不好说了。
Differences in different type implementations, differences in various non-Standard vendor extensions, could be a lot of things.
Here are just some of the language features that differ (look at gfortran and intel). Programs written to fortran standard work on every compiler the same, but a lot of people don't know what are the standard language features, and what are the language extensions, and so use them ... when compiled with a different compiler troubles arise.
If you post the code somewhere I could take a quick look at it; otherwise, like this, 'tis hard to say for certain.