different behaviour or sqrt when compiled with 64 or 32 bits

帅比萌擦擦* 提交于 2019-12-30 18:30:09

问题


I'm using sqrt() function from math library, when I build for 64 bit using -m64 I'm getting correct result but when I build for 32 bit I have very inconsistent behaviour.

For example on 64bit

double dx = 0x1.fffffffffffffp+1023;
sqrt(dx); // => 0x1.fffffffffffffp+511
sqrt(0x1.fffffffffffffp+1023);// => 0x1.fffffffffffffp+511

(which I believe is the correctly rounded result, verified with mpfr)

But on 32 bit same input value it behaves differently.

double dx = 0x1.fffffffffffffp+1023;
sqrt(dx); // => 0x1.0p+512
sqrt(0x1.fffffffffffffp+1023); // => 0x1.fffffffffffffp+511

When the same value passed in a variable I'm getting wrong result. I checked rounding mode before and after each call and all are set to round to nearest. What the reason? I'm using gcc 4.6 on a 64bit machine, and options are -mfpmath=sse and -march=pentium for both x86 nad x64 cases.


回答1:


You haven't said which compiler or architecure you're using, but assuming gcc on x86 / x86-64 then the difference is likely down to the fact that by default gcc uses 387 floating point instructions on 32 bit x86, whereas it uses SSE instructions on x86-64.

The 387 floating point registers are 80 bits wide, whereas double is 64 bits wide. This means that intermediate results can have higher precision using the 387 instructions, which can result in a slightly different answer after rounding. (The SSE2 instructions operate on packed 64 bit doubles).

There's a few ways to change the way the compiler operates, depending on what you want:

  • If you use the -ffloat-store option on x86 builds, the compiler will discard extra precision whenever you store a value in a double variable;
  • If you use the -mfpmath=sse options on x86 builds, along with -msse2 or an -march= switch that specifies an SSE2-supporting architecture, the compiler will use SSE instructions for floating point just as on x86-64. The code will only run on CPUs that support SSE2, though (Pentium-M / Pentium 4 and later).
  • If you use the -mfpmath=387 option on x86-64 builds, the compiler will use 387 instructions for floating point just as on x86. This isn't recommended, though - the x86-64 ABI specifies that floating point values are passed in SSE registers, so the compiler has to do a lot of shuffling between 387 and SSE registers with this option.



回答2:


Certain compilers, such as gcc, when they see certain math library functions performed on static literals, actually calculate the value during compile time, where-as with the variable, it's by necessity calculated at run-time. The compile-time value is typically calculated by the compiler using a math library like MPFR, GNU MP, etc., so the results will be more accurate, or at least as accurate as possible from platform-to-platform.



来源:https://stackoverflow.com/questions/10808601/different-behaviour-or-sqrt-when-compiled-with-64-or-32-bits

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!