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

时间:2008-11-27 02:26:41

标签: c 64-bit floating-point

我有一个为Linux x86 32位开发的应用程序。根据结果​​,有许多浮点运算和大量测试。现在我们将它移植到x86_64,但测试结果在这个架构中是不同的。我们不希望为每个架构保留一组单独的结果。

根据文章 An Introduction to GCC - for the GNU compilers gcc and g++ ,问题是X86_64中的GCC假定 fpmath = sse ,而x86假定 fpmath = 387 。 387 FPU对所有操作使用 80位内部精度,仅将结果转换为给定的浮点类型(float,double或long double),而SSE使用操作数的类型来确定其内部精度。

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

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

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

关于“你需要80位精度”的问题,我不得不说这不是个别操作的问题。在这个简单的情况下,差异非常小,没有区别。但是,当复合很多操作时,错误会传播,并且最终结果的差异不再那么小,并且会产生影响。所以我想我需要80位精度。

4 个答案:

答案 0 :(得分:17)

我说你需要修理你的测试。如果你假设浮点数学是准确的,你通常会让自己失望。而不是测试精确相等,测试它是否足够接近预期结果。毕竟,你发现的不是一个错误,所以如果你的测试报告错误,测试是错误的。 ;)

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

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

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

答案 1 :(得分:5)

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

答案 2 :(得分:3)

如果您希望long double精确,请对所有浮点变量使用long double,而不是期望floatdouble具有额外的魔法精度。这真是一个明智的选择。

答案 3 :(得分:2)

SSE浮点和387浮点使用完全不同的指令,因此没有办法说服SSE fp指令使用387.可能最好的解决方法是将测试套件重新调整为略有不同的结果,以及不依赖于结果与最后一位相同。