我有一个为Linux x86 32位开发的应用程序.根据结果,有许多浮点运算和大量测试.现在我们将它移植到x86_64,但测试结果在这个架构中是不同的.我们不希望为每个体系结构保留单独的结果集.
根据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位精度.
我说你需要修理你的测试.如果你假设浮点数学是准确的,你通常会让自己失望.而不是测试确切的相等性,测试它是否足够接近预期的结果.毕竟,你发现的并不是一个bug,所以如果你的测试报告错误,那么测试是错误的.;)
正如您所知,您依赖的每个库都将采用SSE浮点,因此除非您计划手动编译所有内容,现在和永久,只需将FP模式设置为x87,您最好不要处理现在问题,只是接受FP数学不是100%准确,并且通常不会在两个不同的平台上产生相同的结果.(我相信AMD CPU的产量在x87数学上也略有不同).
你绝对需要 80位精度吗?(如果是这样,除了自己编译所有内容以使用80位FP 之外,显然没有太多替代方案.)
否则,调整测试以在一些小epsilon中执行比较和相等测试.如果差值小于该值,则认为这些值相等.
80位精度实际上是危险的.问题是只要变量存储在CPU寄存器中,它就会被保留.每当它被强制输出到RAM时,它都被截断为类型精度.因此,即使代码中没有发生任何变化,您也可以让变量实际更改其值.