如何在不同平台上强制32位浮点计算一致性?

时间:2014-11-04 07:50:49

标签: c++ floating-point floating-accuracy

我有一段简单的代码,可以使用浮点运算。 循环中很少有乘法,除法,exp(),减法和加法。 当我在不同的平台(如PC,Android手机,iPhone)上运行相同的代码时,我得到的结果略有不同。 结果在所有平台上几乎相同,但差异非常小 - 通常为浮点值的1/1000000。

我想原因是有些手机没有浮点寄存器,只是用整数模拟这些计算,有些手机有浮点寄存器,但有不同的实现。 这里有证明:http://christian-seiler.de/projekte/fpmath/

有没有办法强制所有平台产生一致的结果? 例如,一个好的&快速开源库,用整数(软件)实现浮点机制,因此我可以避免硬件实现的差异。

我需要精确一致性的原因是避免计算层之间的复合错误。 目前,这些复合错误会产生明显不同的结果。 换句话说,我并不在乎哪个平台的结果更正确,而是希望强制一致性以便能够重现同等行为。例如,在手机上发现的错误更容易在PC上调试,但我需要重现这种确切的行为

2 个答案:

答案 0 :(得分:2)

一种相对广泛使用的高质量软件FP实现是MPFR。但是,它比硬件FP慢很多。

当然,这不会解决您的算法在复合错误中遇到的实际问题,它只会使它在所有平台上产生相同的错误。如果可行的话,可能更好的方法是设计一种对FP算术中的小差异不敏感的算法。或者,如果你使用MPFR路径,你可以使用更高精度的FP类型,看看是否有帮助,不需要限制自己模拟硬件单/双精度。

答案 1 :(得分:1)

32位浮点数学,对于给定的计算,最多在16777216中具有1的精度(1 in 2 24 )。诸如exp之类的函数通常被实现为一系列计算,因此可能会出现更大的错误。如果连续进行多次计算,则错误将增加并相乘。通常,float具有大约6-7位精度。

正如一条评论所说,检查舍入模式是一样的。大多数FPU都有#34;到最近的#34; (rtn),"舍入到零" (rtz)和" to to even" (rte)模式,你可以选择。不同平台上的默认值可能会有所不同。

如果对相当大的数字执行相当小的数字的加法或减法,由于数字必须被标准化,因此这些操作会产生更大的错误。

标准化意味着移动使得两个数字都排成小数位 - 就像你在纸上做的那样,你必须填写额外的零来排列你添加的两个数字 - 但当然在纸上你可以添加12419818.0与0.000000001,最终得到12419818.000000001,因为纸张具有尽可能多的精度,你可以打扰。在floatdouble中执行此操作将导致与之前相同的数字。

确实存在浮点运算的库 - 最受欢迎的是MPFR - 但它是一个" multiprecision"库,但它会相当慢 - 因为它们并不是真的被构建为"插件替换浮动",而是一个工具,用于计算pi 1000个数字,或何时例如,您想要计算远大于64或128位的范围内的素数。

它可以解决使用这样一个库的问题,但它会很慢。

更好的选择,从float移动到double应该有类似的效果(double有53位尾数,而32位浮点数则为23,所以尾数中位数的两倍多。并且应该仍然可以作为任何合理的最新ARM处理器中的硬件指令使用,并且因此相对较快,但不如float快(FPU可从ARMv7获得 - 这当然是你在iPhone中找到的 - 至少来自iPhone 3和中高端Android设备 - 我设法发现三星Galaxy ACE有一个ARM9处理器[1997年首次推出] - 所以没有浮点硬件。)