我已经设法将我的大部分 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
无论有符号零如何。