SSE浮点运算是否可重复?

Asi*_*sik 11 .net floating-point sse ieee-754 x87

x87 FPU值得注意的是使用内部80位精度模式,这通常会导致编译器和机器出现意外和不可重现的结果.在我搜索 .NET上可重现的浮点数学时,我发现.NET(Microsoft和Mono)的两个主要实现都在64位模式下发出SSE指令而不是x87.

SSE(2)严格使用32位寄存器用于32位浮点数,严格使用64位寄存器用于64位浮点数.通过设置适当的控制字,可以选择将非正规数刷新为零.

因此,似乎SSE不会受到x87的精度相关问题的影响,并且唯一的变量是可以控制的非正规行为.

抛开超越函数的问题(SSE本身不像x87那样提供),是否使用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 et aliis, Handbook of Floating-Point Arithmetic - p.107

然而:

此外,您不能将SSE或SSE2用于浮点,因为它太低于指定而不具有确定性.- John Watte http://www.gamedev.net/topic/499435-floating-point-determinism/#entry4259411

Ste*_*non 11

SSE完全指定*.Muller是浮点运算专家; 你会信任谁,他或者是gamedev论坛上的某个人?

(*)对于非IEEE-754操作,例如rsqrtss,实际上有一些例外,其中英特尔从未完全指定行为,但这不会影响IEEE-754基本操作,更重要的是它们的行为实际上无法改变在这一点上,因为它会破坏太多东西的二进制兼容性,所以它们和指定的一样好.


tmy*_*ebu 6

正如 Stephen 指出的,给定的 SSE 汇编代码产生的结果将是可重现的;您向相同的代码提供相同的输入,最后得到相同的输出。(也就是说,约翰·瓦特的引述是完全错误的。)

不过,您在其中添加了“编译器”一词。那是完全不同的球赛。许多编译器在保持浮点代码的正确性方面仍然相当糟糕。(ATLAS 勘误表页面提到 clang“无法为某些操作生成正确的代码。”)如果您在代码中使用特殊函数,那么在某种程度上,您也会受到实现数学库的人的摆布。