8

这是代码吗

float a = ...;
__m256 b = _mm_broadcast_ss(&a)

总是比这段代码快

float a = ...;
_mm_set1_ps(a)

?

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

4

3 回答 3

11

_mm_broadcast_ss 具有架构强加的弱点,这些弱点在很大程度上被mm SSE API 隐藏。最重要的区别如下:

  • _mm_broadcast_ss 仅限于从内存中加载值。

这意味着如果您在源不在内存中的情况下显式使用 _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()。

于 2014-10-27T21:10:26.600 回答
8

如果您以 AVX 指令集为目标,gcc 将使用 VBROADCASTSS 来实现 _mm_set1_ps 内在函数。然而,Clang 将使用两条指令(VMOVSS + VPSHUFD)。

于 2012-11-04T19:49:09.873 回答
6

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

于 2012-11-04T13:31:54.537 回答