简体   繁体   English

Linux,Mac OS X和Windows之间的数学舍入行为不同

[英]Different math rounding behaviour between Linux, Mac OS X and Windows

HI, 嗨,

I developed some mixed C/C++ code, with some intensive numerical calculations. 我开发了一些混合的C / C ++代码,并进行了大量的数值计算。 When compiled in Linux and Mac OS XI get very similar results after the simulation ends. 在Linux和Mac OS XI上编译时,模拟结束后会得到非常相似的结果。 In Windows the program compiles as well but I get very different results and sometimes the program does not seem to work. 在Windows中,该程序也可以编译,但结果却截然不同,有时该程序似乎无法正常工作。

I used GNU compilers in all systems. 我在所有系统中都使用了GNU编译器。 Some friend recommend me to add -frounding-math and now the windows version seems to work more stable, but Linux and Os X, their results, do not change at all. 一些朋友建议我添加-frounding-math,现在Windows版本似乎更稳定,但是Linux和Os X的结果完全不变。

Could you recommend another options to get more concordance between Win and Linux/OSX versions? 您是否可以推荐其他选项,以使Win和Linux / OSX版本之间更加协调?

Thanks 谢谢

PD I also tried -O0 (no optimizations) and specified -m32 PD我也尝试了-O0(无优化)并指定了-m32

I can't speak to the implementation in Windows, but Intel chips contain 80-bit floating point registers, and can give greater precision than that specified in the IEEE-754 floating point standard. 我不能说Windows中的实现,但是Intel芯片包含80位浮点寄存器,并且比IEEE-754浮点标准中指定的精度更高。 You can try calling this routine in the main() of your application (on Intel chip platforms): 您可以尝试在应用程序的main()中调用此例程(在Intel芯片平台上):

inline void fpu_round_to_IEEE_double()
{
   unsigned short cw = 0;
   _FPU_GETCW(cw);        // Get the FPU control word
   cw &= ~_FPU_EXTENDED;  // mask out '80-bit' register precision
   cw |= _FPU_DOUBLE;     // Mask in '64-bit' register precision
   _FPU_SETCW(cw);        // Set the FPU control word
}

I think this is distinct from the rounding modes discussed by @Alok. 认为这与@Alok讨论的舍入模式不同。

There are four different types of rounding for floating-point numbers: round toward zero, round up, round down, and round to the nearest number. 浮点数有四种不同的舍入类型:向零舍入,向上舍入,向下舍入和舍入到最接近的数字。 Depending upon compiler/operating system, the default may be different on different systems. 根据编译器/操作系统的不同,默认值在不同的系统上可能会有所不同。 For programmatically changing the rounding method, see fesetround . 有关以编程方式更改舍入方法的信息,请参见fesetround It is specified by C99 standard, but may be available to you. 它由C99标准指定,但可能对您可用。

You can also try -ffloat-store gcc option. 您也可以尝试-ffloat-store gcc选项。 This will try to prevent gcc from using 80-bit floating-point values in registers. 这将试图防止gcc在寄存器中使用80位浮点值。

Also, if your results change depending upon the rounding method, and the differences are significant, it means that your calculations may not be stable. 此外,如果您的结果根据四舍五入方法而有所不同,并且差异很大,则意味着您的计算可能不稳定。 Please consider doing interval analysis, or using some other method to find the problem. 请考虑进行间隔分析,或使用其他方法查找问题。 For more information, see How Futile are Mindless Assessments of Roundoff in Floating-Point Computation? 有关更多信息,请参见浮点计算中对舍入的无意识评估有多无效? (pdf) and The pitfalls of verifying floating-point computations (ACM link, but you can get PDF from a lot of places if that doesn't work for you). (pdf)和验证浮点计算的陷阱 (ACM链接,但是如果您不满意,则可以从很多地方获取PDF)。

In addition to the runtime rounding settings that people mentioned, you can control the Visual Studio compiler settings in Properties > C++ > Code Generation > Floating Point Model. 除了人们提到的运行时舍入设置,您还可以在“属性”>“ C ++”>“代码生成”>“浮点模型”中控制Visual Studio编译器设置。 I've seen cases where setting this to "Fast" may cause some bad numerical behavior (eg iterative methods fail to converge). 我已经看到了将其设置为“快速”可能会导致一些不良数值行为(例如,迭代方法无法收敛)的情况。

The settings are explained here: http://msdn.microsoft.com/en-us/library/e7s85ffb%28VS.80%29.aspx 此处说明了这些设置: http : //msdn.microsoft.com/zh-cn/library/e7s85ffb%28VS.80%29.aspx

The IEEE and C/C++ standards leave some aspects of floating-point math unspecified. IEEE和C / C ++标准未指定浮点数学的某些方面。 Yes, the precise result of adding to floats is determined, but any more complicated calculation is not. 是的,确定了添加到浮点数的精确结果,但没有确定任何更复杂的计算。 For instance, if you add three floats then the compiler can do the evaluation at float precision, double precision, or higher. 例如,如果添加三个浮点数,则编译器可以以浮点精度,双精度或更高的精度进行评估。 Similarly, if you add three doubles then the compiler may do the evaluation at double precision or higher. 同样,如果添加三个double,则编译器可能会以double precision或更高的精度进行评估。

VC++ defaults to setting the x87 FPUs precision to double. VC ++默认将x87 FPU的精度设置为两倍。 I believe that gcc leaves it at 80-bit precision. 我相信gcc会将其保留为80位精度。 Neither is clearly better, but they can easily give different results, especially if there is any instability in your calculations. 两者显然都不是更好,但是它们可以轻松给出不同的结果,尤其是在您的计算中存在任何不稳定的情况下。 In particular 'tiny + large - large' may give very different results if you have extra bits of precision (or if the order of evaluation changes). 如果您的精度更高(或评估顺序发生变化),则“小+大-大”的结果可能会非常不同。 The implications of varying intermediate precision are discussed here: 此处讨论了变化的中间精度的含义:

http://randomascii.wordpress.com/2012/03/21/intermediate-floating-point-precision/ http://randomascii.wordpress.com/2012/03/21/intermediate-floating-point-precision/

The challenges of deterministic floating-point are discussed here: 确定性浮点的挑战在这里讨论:

http://randomascii.wordpress.com/2013/07/16/floating-point-determinism/ http://randomascii.wordpress.com/2013/07/16/floating-point-determinism/

Floating-point math is tricky. 浮点数学很棘手。 You need to find out when your calculations diverge and examine the generated code to understand why. 您需要找出计算差异的时间,并检查生成的代码以了解原因。 Only then can you decide what actions to take. 只有这样,您才能决定要采取的措施。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM