隐式 SIMD (SSE/AVX) 使用 GCC 进行广播



我已经设法将我的大部分 SIMD 代码转换为 GCC 的矢量扩展。 但是,我还没有找到进行广播的好解决方案,如下所示

__m256 areg0 = _mm256_broadcast_ss(&a[i]);

我想做

__m256 argeg0 = a[i];

如果您通过恒定使用 SSE 在多向量中看到我的答案,我设法使用另一个 SIMD 寄存器获得广播。 以下作品:

__m256 x,y;
y = x + 3.14159f; // broadcast x + 3.14159
y = 3.14159f*x;  // broadcast 3.14159*x

但这行不通:

 __m256 x;
 x = 3.14159f;  //should broadcast 3.14159 but does not work

我如何使用 GCC 执行此操作?

我认为目前没有直接的方法,您必须使用已经注意到的语法来解决它:

__m256 zero={};
__m256 x=zero+3.14159f;

如果我们能就一个好的语法达成一致,它可能会在未来发生变化,请参阅 PR 55726。

请注意,如果要创建具有非常量float s的向量{ s, s, ... s },上述技术仅适用于整数或浮点数和-fno-signed-zeros。您可以将其调整为__m256 x=s-zero;,除非您使用 -frounding-math .最后一个版本,由Z玻色子建议,__m256 x=(zero+1.f)*s;在大多数情况下应该有效(除了可能对sNaN的编译器偏执狂)。

事实证明,对于精确的浮点模型(例如,使用 -O3 ),由于有符号零,GCC 无法将x+0简化为 x。 因此x = zero+3.14159f会产生低效的代码。 但是,GCC可以将1.0*x简化为仅x因此在这种情况下有效的解决方案是。

__m256 x = ((__m256){} + 1)*3.14159f;

https://godbolt.org/g/5QAQkC

有关更多详细信息,请参阅此答案。


更简单的解决方案是x = 3.14159f - (__m256){}因为x - 0 = x无论有符号零如何。

最新更新