_mm_broadcast_ss比_mm_set1_ps快吗?

Ben*_*Uri 6 vectorization avx

这是代码

float a = ...;
__m256 b = _mm_broadcast_ss(&a)
Run Code Online (Sandbox Code Playgroud)

总是比这段代码快

float a = ...;
_mm_set1_ps(a)
Run Code Online (Sandbox Code Playgroud)

如果a被定义为static const float a = ...而不是float a = ...

jst*_*ine 9

_mm_broadcast_ss具有架构强加的弱点,这些弱点主要由mm SSE API 隐藏.最重要的区别如下:

  • _mm_broadcast_ss仅限于从内存加载值.

这意味着如果在源不在内存中的情况下显式使用_mm_broadcast_ss,那么结果的效率可能低于使用_mm_set1_ps的效率.当加载立即值(常量)或使用最近计算的结果时,通常会发生这种情况.在这些情况下,结果将由编译器映射到寄存器.要使用广播值,编译器必须将值转储回内存.或者,可以使用pshufd直接从寄存器进行splat.

_mm_set1_ps是实现定义的,而不是映射到特定的底层cpu操作(指令).这意味着它可能会使用几个SSE指令之一来执行splat.启用了AVX支持的智能编译器应该在适当的时候在内部使用vbroadcastss,但这取决于编译器优化器的AVX实现状态.

如果您非常有信心从内存加载 - 例如迭代数据 - 那么直接使用广播就可以了.但如果有任何疑问,我建议坚持使用_mm_set1_ps.

在a的特定情况下static const float,你绝对想避免使用_mm_broadcast_ss().


Mar*_*han 8

如果你定位AVX指令集,gcc将使用VBROADCASTSS来实现_mm_set1_ps内在函数.但是,Clang将使用两条指令(VMOVSS + VPSHUFD).

  • 不,这只是一个编译器错误. (4认同)

Jas*_*n R 5

mm_broadcast_ss可能比mm_set1_ps更快.前者转换为单个指令(VBROADCASTSS),而后者则使用多个指令(可能是MOVSS后跟shuffle)进行仿真.但是,mm_broadcast_ss需要AVX指令集,而mm_set1_ps只需要SSE.

  • 咦?`_mm_set1_ps`应该是一个`shufps`指令; 假设`_mm_broadcast_ss`实际上生成了一个'vbroadcastss`,如果该值尚未存在于内存中,它可能需要一个存储(并且它需要一个加载,因此它的延迟比最佳情况下的shuffle长).即使`vbroadcastss`更快,在启用AVX时,没有什么能阻止编译器为`_mm_set1_ps`内在发出`vbroadcastss`. (4认同)