如何避免未使用的 SIMD 通道中的浮点异常
How to avoid floating point exceptions in unused SIMD lanes
我喜欢 运行 我的代码启用了浮点异常。
我在 Linux 下使用:
feenableexcept( FE_DIVBYZERO | FE_INVALID | FE_OVERFLOW );
到目前为止一切顺利。
我遇到的问题是,有时编译器(我使用 clang8)决定使用 SIMD 指令进行标量除法。很好,如果速度更快,即使对于单个标量,为什么不呢。
但结果是 SIMD 寄存器中未使用的通道可以包含零。
并且执行SIMD除法时,抛出浮点异常
这是否意味着如果您允许编译器使用 sse/avx 扩展,则根本无法使用浮点异常?
在我的例子中,这行 C 代码:
float a0, min, a, d;
...
a0 = (min - a) / (d);
...执行为:
divps %xmm2,%xmm3
然后抛出一个:
Thread 1 "noisetuner" received signal SIGFPE, Arithmetic exception.
我认为您在 clang 或 llvm 中发现了一个错误。
Here’s how I have reproduced,clang 10.0 发出相同的代码,即也有该错误。显然,vdivps
指令仅在向量的前 2 条通道中具有有效数据,而在较高的 2 条通道中它将 运行 0.0 / 0.0,因此您将得到 运行如果您在 mxcsr
中启用这些中断,请像您正在做的那样注册。
Microsoft、Intel 和 gcc 不会为该代码发出 divps
。可以的话换成gcc应该也不错
更新: Clang 10+ 有一个控制此类优化的选项,-ffp-exception-behavior=maytrap
,看看:https://godbolt.org/z/WG7bEE
我喜欢 运行 我的代码启用了浮点异常。 我在 Linux 下使用:
feenableexcept( FE_DIVBYZERO | FE_INVALID | FE_OVERFLOW );
到目前为止一切顺利。
我遇到的问题是,有时编译器(我使用 clang8)决定使用 SIMD 指令进行标量除法。很好,如果速度更快,即使对于单个标量,为什么不呢。
但结果是 SIMD 寄存器中未使用的通道可以包含零。
并且执行SIMD除法时,抛出浮点异常
这是否意味着如果您允许编译器使用 sse/avx 扩展,则根本无法使用浮点异常?
在我的例子中,这行 C 代码:
float a0, min, a, d;
...
a0 = (min - a) / (d);
...执行为:
divps %xmm2,%xmm3
然后抛出一个:
Thread 1 "noisetuner" received signal SIGFPE, Arithmetic exception.
我认为您在 clang 或 llvm 中发现了一个错误。
Here’s how I have reproduced,clang 10.0 发出相同的代码,即也有该错误。显然,vdivps
指令仅在向量的前 2 条通道中具有有效数据,而在较高的 2 条通道中它将 运行 0.0 / 0.0,因此您将得到 运行如果您在 mxcsr
中启用这些中断,请像您正在做的那样注册。
Microsoft、Intel 和 gcc 不会为该代码发出 divps
。可以的话换成gcc应该也不错
更新: Clang 10+ 有一个控制此类优化的选项,-ffp-exception-behavior=maytrap
,看看:https://godbolt.org/z/WG7bEE