Fortran中不同编译器在不同计算机上的一致浮点运算? [英] Consistent floating point arithmetic in fortran with different compilers on different computers?

查看:294
本文介绍了Fortran中不同编译器在不同计算机上的一致浮点运算?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如何使用不同的编译器和不同的计算机获得与浮点运算相同的结果?



这是p.f90

















$ b = 10d0
写(*,*)a

结束程序

用gfortran -op p.f90我得到0.90000000000000002



用ifort -g -op p.f90得到0.900000000000000

有没有办法达到一致性? b








$ b $ divc

解决方案

我们将转向下面的浮点运算,但首先让我处理一下您的错误观念。在write语句中使用 list-directed formatting 意味着编译器选择写出变量的格式是编译器的选择;这不是语言标准的要求。您使用 write(*,*)中的第二个 * 会告诉编译器写出一个变量的值如其所愿。所以你所拥有的并不是证明算术有什么问题,而是在 gfortran ifort 。如果我将你的写入语句修改为
$ b $ pre code $ write(*,'(f21.18)')

code>

然后我的英特尔Fortran程序写入

  0.900000000000000022 

到控制台。

<由于不熟悉浮点运算的细节,所以我不打算写一篇论文,只是几个与你的问题有关的观察。



IEEE-754 64位浮点数(可能是你用声明 real(kind = 8)得到的)只提供大约16个十进制数字有用的信息。实际上,由于它们是二进制的,并且一个基数和另一个基数之间的数字之间没有简单的对应关系,所以它实际上是15.95个十进制数字,许多用户将其舍弃,点数的十进制表示。因此, ifort gfortran 都会误导您与它们的尾部 2 s。

IEEE-754不仅定义了fp数字的格式,还定义了四舍五入和算术运算的一些规则。一个精心编写的程序,只使用那些算术运算(我认为平方根也是指定的),并且关心舍入模式和舍入操作应该在两个不同的处理器上产生相同的结果。当然,没有多少有用的数值程序将自己限制在基本的算术运算中。由于2003标准的Fortran已经包含了一个名为 ieee_arithmetic的内部模块 / code>这使程序员可以直接访问运行硬件的底层IEEE-754功能 - 但是请注意,它不要求硬件具有任何这样的功能。使用 ieee_arithmetic 和另一个名为 ieee_exceptions 的内部模块,如果您的硬件提供了必要的支持,那么应该能够编写程序它们在 gfortran ifort 下编译,并在执行时产生与每个fp的最后一位相同的结果数字。

您还需要熟悉您正在使用的编译器的优化选项和数值算术选项。大多数编译器有一个选项,它的含义是牺牲速度符合IEEE (for ifort 我认为它是 FP-模型)。一般来说,遵守IEEE-754的操作会使你的程序变慢。

How can I get the same results with floating-point arithmetic using different compilers and possibly also different computers?

This is p.f90

program fl
implicit none
real(kind=8) :: a

a=9d0/10d0
write(*,*) a

end program

With gfortran -o p p.f90 I get 0.90000000000000002

With ifort -g -o p p.f90 I get 0.900000000000000

Is there a way to achieve consistency? The small things propagate and become larger.

Best regards Alessandro

解决方案

We'll turn to floating-point arithmetic below, but let me deal first with a misconception you have. Your use of list-directed formatting in the write statement means that the format chosen by the compiler to write out a variable is, well, the compiler's choice; it's not mandated by the language standard. Your use of the second * in write(*,*) tells the compiler to write out the value of a variable as it wishes. So what you have is not evidence that there is something wrong with the arithmetic, but that there are differences between gfortran and ifort. If I modify your write statement to

write(*,'(f21.18)') a

then my Intel Fortran program writes

0.900000000000000022

to the console.

SO is littered with questions arising from unfamiliarity with the details of floating-point arithmetic so I'm not going to write a treatise, just a few observations relevant to your question.

IEEE-754 64-bit floating-point numbers (which is probably what you get with the declaration real(kind=8)) only provide approximately 16 decimal digits of useful information. Actually, since they're binary and there is no easy correspondence between the number of digits in one base and in another, it's actually 15.95 decimal digits and many users round this down and never look at anything after the 15th significant figure in a floating-point number's decimal representation. So both ifort and gfortran are misleading you with their trailing 2s.

IEEE-754 defines not only the formats for f-p numbers, but also some rules for rounding and for arithmetic operations. A carefully-written program which uses only those arithmetic operations (I think square root is also specified) and which takes care about rounding modes and rounding operations should produce the same results on two different processors. Of course, not many useful numerical programs confine themselves to the basic arithmetic operations.

Since the 2003 standard Fortran has included an intrinsic module called ieee_arithmetic which gives the programmer direct access to the underlying IEEE-754 capabilities of the hardware on which it is running -- but note that it does not require that the hardware have any such capabilities. Using ieee_arithmetic and another intrinsic module called ieee_exceptions you should, if your hardware provides the necessary support, be able to write programs which compile under both gfortran and ifort and which produce, when executed, the same results to the last bit of every f-p number.

You'll also need to familiarise yourself with the optimisation options and numerical arithmetic options of the compiler(s) you're using. Most compilers have an option whose meaning is sacrifice IEEE compliance for speed (for ifort I think it's fp-model). In general adherence to IEEE-754 for operations will slow your programs.

这篇关于Fortran中不同编译器在不同计算机上的一致浮点运算?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆