不同的行为或开方时64位或32位编译 [英] different behaviour or sqrt when compiled with 64 or 32 bits

查看:421
本文介绍了不同的行为或开方时64位或32位编译的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我使用的sqrt()函数的数学库,当我建立了64位使用-m64我得到正确的结果,但是当我建立32位我有非常不一致的行为。

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.

例如在64位

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

(我认为这是正确舍入结果,MPFR验证)

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

但在32位相同的输入值,它的行为是不同的。

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

当一个变量我得到错误的结果通过了相同的值。
我检查前和每次通话后舍入模式和所有被设置为四舍五入到最接近。
原因何在?
我使用的是64位机器上GCC 4.6,和选项 -mfpmath = SSE -march =奔腾的在x86 NAD 64例。

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.

推荐答案

您还没有说哪个编译或构建筑,你正在使用,但假设对 GCC 86 / X86-64 则差异可能向下,默认情况下GCC使用32位387浮点指令的事实86,而它使用的x86-64的SSE指令。

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.

387浮点寄存器为80位宽,而双击为64位宽。这意味着,中间结果可以用387​​指示,这可导致在一个稍微不同的答案四舍五入后具有较高的precision。 (SSE2指令操作的装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:


  • 如果您使用的x86的 -ffloat店选项生成,当你在双变量;

  • 如果您使用的x86版本,以及 -msse2 -mfpmath = SSE 选项或 -march = 开关,编译器将使用SSE指令浮点就像在x86-64的。在code将只能在支持SSE2,CPU上运行,但(奔腾M /奔腾4及更高版本)。

  • 如果您使用 -mfpmath = 387 选项X86-64上构建,编译器将使用387指令浮点就像在x86。这是不推荐的,虽然 - X86-64的ABI规定浮点值在SSE寄存器传递,所以编译器必须做387和上证使用该选项注册的洗牌大量

  • 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.

这篇关于不同的行为或开方时64位或32位编译的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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