12

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

根据文章An Introduction to GCC - 对于 GNU 编译器 gcc 和 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

4 回答 4

18

我会说你需要修复你的测试。如果您假设浮点数学是准确的,那么您通常会让自己失望。与其测试完全相等,不如测试它是否足够接近预期结果。毕竟,您发现的不是错误,因此如果您的测试报告错误,则测试是错误的。;)

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

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

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

于 2008-11-27T02:42:38.397 回答
5

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

于 2009-01-27T22:39:58.643 回答
3

如果您想要long double精度,请使用long double所有浮点变量,而不是期望floatdouble具有额外的魔术精度。这真的是不言而喻。

于 2011-06-28T20:14:38.783 回答
2

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

于 2008-11-27T21:37:57.500 回答