这是代码吗
float a = ...;
__m256 b = _mm_broadcast_ss(&a)
总是比这段代码快
float a = ...;
_mm_set1_ps(a)
?
如果a
定义为static const float a = ...
而不是float a = ...
呢?
这是代码吗
float a = ...;
__m256 b = _mm_broadcast_ss(&a)
总是比这段代码快
float a = ...;
_mm_set1_ps(a)
?
如果a
定义为static const float a = ...
而不是float a = ...
呢?
_mm_broadcast_ss 具有架构强加的弱点,这些弱点在很大程度上被mm SSE API 隐藏。最重要的区别如下:
这意味着如果您在源不在内存中的情况下显式使用 _mm_broadcast_ss,那么结果可能会比使用 _mm_set1_ps 的效率低。这种情况通常发生在加载立即值(常量)或使用最近计算的结果时。在这些情况下,编译器会将结果映射到寄存器。要将值用于广播,编译器必须将值转储回内存。或者,可以使用 pshufd 直接从寄存器中弹出。
_mm_set1_ps 是实现定义的,而不是映射到特定的底层 cpu 操作(指令)。这意味着它可能会使用几个 SSE 指令之一来执行 splat。启用了 AVX 支持的智能编译器绝对应该在适当的时候在内部使用 vbroadcastss,但这取决于编译器优化器的 AVX 实现状态。
如果您非常确信您是从内存加载的——例如迭代数据数组——那么直接使用广播就可以了。但如果有任何疑问,我建议坚持使用 _mm_set1_ps。
在 a 的特定情况下static const float
,您绝对希望避免使用 _mm_broadcast_ss()。
如果您以 AVX 指令集为目标,gcc 将使用 VBROADCASTSS 来实现 _mm_set1_ps 内在函数。然而,Clang 将使用两条指令(VMOVSS + VPSHUFD)。
mm_broadcast_ss 可能比 mm_set1_ps 快。前者转换为单条指令 (VBROADCASTSS),而后者则使用多条指令进行仿真(可能是 MOVSS,然后是 shuffle)。但是,mm_broadcast_ss 需要 AVX 指令集,而 mm_set1_ps 只需要 SSE。