从 i386 移动到 x86_64 时的浮点精度 [英] Floating-point precision when moving from i386 to x86_64

查看:26
本文介绍了从 i386 移动到 x86_64 时的浮点精度的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I have an application that was developed for Linux x86 32 bits. There are lots of floating-point operations and a lot of tests depending on the results. Now we are porting it to x86_64, but the test results are different in this architecture. We don't want to keep a separate set of results for each architecture.

根据文章GCC 简介 - 对于GNU 编译器 gcc 和 g++ 问题是 X86_64 中的 GCC 假定 fpmath=sse 而 x86 假定 fpmath=387.387 FPU 对所有操作使用 80 位内部精度,并且只将结果转换为给定的浮点类型(float、double 或 long double),而 SSE 使用操作数的类型来确定其内部精度.

According to the article An Introduction to GCC - for the GNU compilers gcc and g++ the problem is that GCC in X86_64 assumes fpmath=sse while x86 assumes fpmath=387. The 387 FPU uses 80 bit internal precision for all operations and only convert the result to a given floating-point type (float, double or long double) while SSE uses the type of the operands to determine its internal precision.

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

I can force -mfpmath=387 when compiling my own code and all my operations work correctly, but whenever I call some library function (sin, cos, atan2, etc.) the results are wrong again. I assume it's because libm was compiled without the fpmath override.

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

I tried to build libm myself (glibc) using 387 emulation, but it caused a lot of crashes all around (don't know if I did something wrong).

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

Is there a way to force all code in a process to use the 387 emulation in x86_64? Or maybe some library that returns the same values as libm does on both architectures? Any suggestions?

关于你需要80位精度吗"的问题,不得不说这不是个别操作的问题.在这个简单的情况下,差异非常小,没有任何区别.但是,当复合大量操作时,错误会传播,最终结果的差异不再那么小,并且会有所不同.所以我想我需要 80 位精度.

Regarding the question of "Do you need the 80 bit precision", I have to say that this is not a problem for an individual operation. In this simple case the difference is really small and makes no difference. When compounding a lot of operations, though, the error propagates and the difference in the final result is not so small any more and makes a difference. So I guess I need the 80 bit precision.

推荐答案

我认为您需要修复您的测试.如果您认为浮点数学是准确的,您通常会让自己失望.与其测试完全相等,不如测试它是否足够接近预期结果.毕竟,您发现的不是错误,所以如果您的测试报告错误,测试就是错误的.;)

I'd say you need to fix your tests. You're generally setting yourself up for disappointment if you assume floating point math to be accurate. Instead of testing for exact equality, test whether it's close enough to the expected result. What you've found isn't a bug, after all, so if your tests report errors, the tests are wrong. ;)

正如您所发现的,您依赖的每个库都将假定 SSE 浮点数,因此除非您计划手动编译所有内容,现在和永远,这样您就可以设置 FP模式到 x87,你现在最好处理这个问题,只是接受 FP 数学不是 100% 准确,并且通常不会在两个不同的平台上产生相同的结果.(我相信 AMD CPU 在 x87 数学中的结果也略有不同).

As you've found out, every library you rely on is going to assume SSE floating point, so unless you plan to compile everything manually, now and forever, just so you can set the FP mode to x87, you're better off dealing with the problem now, and just accepting that FP math is not 100% accurate, and will not in general yield the same result on two different platforms. (I believe AMD CPU's yield slightly different results in x87 math as well).

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

Do you absolutely need 80-bit precision? (If so, there obviously aren't many alternatives, other than to compile everything yourself to use 80-bit FP.)

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

Otherwise, adjust your tests to perform comparisons and equality tests within some small epsilon. If the difference is smaller than that epsilon, the values are considered equal.

这篇关于从 i386 移动到 x86_64 时的浮点精度的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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