C 从i386移动到x86_64时的浮点精度

C 从i386移动到x86_64时的浮点精度,c,64-bit,floating-point,C,64 Bit,Floating Point,我有一个为Linux x86 32位开发的应用程序。有许多浮点运算和许多测试取决于结果。现在我们正在将它移植到x86_64,但是在这个体系结构中测试结果是不同的。我们不想为每个架构保留一组单独的结果 根据这篇文章,问题在于X86_64中的GCC假设为fpmath=sse,而X86假设为fpmath=387。387 FPU对所有操作使用80位内部精度,仅将结果转换为给定的浮点类型(浮点、双精度或长双精度),而SSE使用操作数类型确定其内部精度 我可以在编译自己的代码时强制-mfpmath=387并

我有一个为Linux x86 32位开发的应用程序。有许多浮点运算和许多测试取决于结果。现在我们正在将它移植到x86_64,但是在这个体系结构中测试结果是不同的。我们不想为每个架构保留一组单独的结果

根据这篇文章,问题在于X86_64中的GCC假设为fpmath=sse,而X86假设为fpmath=387。387 FPU对所有操作使用80位内部精度,仅将结果转换为给定的浮点类型(浮点、双精度或长双精度),而SSE使用操作数类型确定其内部精度

我可以在编译自己的代码时强制-mfpmath=387并且所有操作都正常工作,但是每当我调用某个库函数(sin、cos、atan2等)时,结果又是错误的。我想这是因为libm是在没有fpmath覆盖的情况下编译的

我试图用387仿真自己构建libm(glibc),但它导致了很多崩溃(不知道我是否做错了什么)

有没有办法强制进程中的所有代码在x86_64中使用387仿真?或者某个库在两种体系结构上都返回与libm相同的值?有什么建议吗


关于“您是否需要80位精度”的问题,我必须说,这不是单个操作的问题。在这个简单的例子中,差别非常小,没有差别。但是,当组合许多操作时,错误会传播,最终结果中的差异不再那么小,并且会产生影响。所以我想我需要80位的精度。

我想你需要修正你的测试。如果你认为浮点数学是准确的,你通常会让自己失望。与其测试精确的相等性,不如测试它是否足够接近预期结果。毕竟,您发现的不是bug,所以如果您的测试报告错误,那么测试就是错误的

正如您所发现的,您所依赖的每个库都将采用SSE浮点,因此,除非您计划现在和永远手动编译所有内容,以便将FP模式设置为x87,否则最好现在就处理这个问题,并接受FP math不是100%准确的,而且在两个不同的平台上通常不会产生相同的结果。(我相信AMD CPU在x87数学方面也会产生略微不同的结果)

你绝对需要80位精度吗?(如果是这样的话,除了自己编译所有内容以使用80位FP之外,显然没有其他选择。)


否则,调整测试以在一些小ε内执行比较和相等性测试。如果差值小于该ε,则认为值相等。

SSE浮点和387浮点使用完全不同的指令,因此无法说服SSE fp指令使用387。处理这一问题的最佳方法可能是让您的测试套件获得稍微不同的结果,而不是依赖于结果与最后一位相同。

80位精度实际上是危险的。问题是,只要变量存储在CPU寄存器中,它实际上就会被保留。每当它被强制输出到RAM时,它就会被截断为类型精度。因此,您可以让一个变量实际更改其值,即使它在代码中没有发生任何变化。

如果您想要
long double
精度,请对所有浮点变量使用
long double
,而不是期望
float
double
具有额外的神奇精度。这真是一件不费吹灰之力的事。

完全正确。依赖于扩展的内部精度只能导致心痛。我正在寻找一种不需要更改太多代码和加倍内存需求的解决方案。但是,正如你所说,这显然可以解决问题。