x87 FPU 以使用内部 80 位精度模式而著称,这通常会导致跨编译器和机器产生意外且不可重现的结果。在我在 .NET 上搜索可重现的浮点数学时,我发现 .NET 的两个主要实现(Microsoft 和 Mono)都发出 SSE 指令,而不是 64 位模式下的 x87。
SSE(2) 对 32 位浮点数使用严格的 32 位寄存器,对 64 位浮点数使用严格的 64 位寄存器。通过设置适当的控制字,可以选择将非正规数刷新为零。
因此,SSE 似乎不受 x87 精度相关问题的影响,唯一的变量是可以控制的非规范行为。
撇开先验函数(与 x87 不同,SSE 本身不提供)的问题,使用 SSE 是否能保证跨机器和编译器的可重现结果?例如,编译器优化能否转化为不同的结果?我发现了一些相互矛盾的意见:
如果您拥有 SSE2,请使用它并从此过上幸福的生活。SSE2 支持 32b 和 64b 操作,中间结果是操作数的大小。- Yossi Kreinin,http://www.yosefk.com/blog/consistency-how-to-defeat-the- purpose-of-ieee-floating-point.html
...
SSE2 指令 (...) 完全符合 IEEE754-1985,它们允许更好的再现性(由于静态舍入精度)和与其他平台的可移植性。Muller 等人, 浮点算术手册- p.107
然而:
此外,您不能将 SSE 或 SSE2 用于浮点,因为它的指定太低而无法确定。-约翰·瓦特 http://www.gamedev.net/topic/499435-floating-point-determinism/#entry4259411