【问题标题】:difference between load1 and broadcast intrinsicsload1 和广播内在函数之间的区别
【发布时间】:2016-07-11 13:05:23
【问题描述】:

_mm_broadcast_ss()_mm_load_ps1() 有什么区别?

void example(){
   __declspec(align(32)) const float num = 20;

   __m128 a1 = _mm_broadcast_ss(&num); 
   __declspec(align(32)) float f1[4];
   _mm_store_ps (f1, a1);
   std::cout << f1[0] << " " << f1[1] <<" " << f1[2] << " " << f1[3] << "\n";

   __m128 a2 = _mm_load_ps1(&num); 
   __declspec(align(32)) float f2[4];
   _mm_store_ps (f2, a2);
    std::cout << f2[0] << " " << f2[1] <<" " << f2[2] << " " << f2[3] << "\n";
}

两种方式都得到了相同的输出,那为什么它们都存在呢?

【问题讨论】:

    标签: x86 sse simd intrinsics


    【解决方案1】:

    _mm_broadcast_ss 仅针对 AVX 目标进行编译。

    _mm_load1_ps / _mm_load_ps1 在为不支持 AVX 的目标进行编译时将编译为多条指令 (movss / shufps)。当您正在为 AVX 目标进行编译时,任何好的编译器都会使用 vbroadcastss 来实现它们。

    load1 / set1 和其他便利函数很早就引入了,因为让编译器选择移动数据的最佳策略通常是件好事。

    _mm_broadcast_* 内在函数是作为 vbroadcastss / vbroadcastsd 指令的直接包装器引入的。 (AVX2有整数vpbroadcast...vbroadcastss的reg-reg形式。AVX1只有vbroadcastss x/ymm, [mem]。)


    AFAICT,仅使用 _mm_load1_ps_mm_set1_ps 没有任何缺点。

    这对代码没有影响,并允许为非 AVX 目标构建相同的源代码。

    该选择可能会对-O0 的 asm 输出产生影响,但 IDK。如果您关心未优化构建中的 asm 输出,那么 1:这很奇怪,而 2:您必须看看您的编译器做了什么。


    从 Godbolt 上的 asm 输出中可以看到(用于 gcc):

    Without AVX (-mno-avx)

    bcast: compile error so I #ifdef it out
    
    __m128 load1(const float*p) {  return _mm_load1_ps(p); }
        movss   xmm0, DWORD PTR [rdi]
        shufps  xmm0, xmm0, 0
        ret
    

    With AVX (-mavx)

    __m128 bcast(const float*p) { return _mm_broadcast_ss(p); }        
        vbroadcastss    xmm0, DWORD PTR [rdi]
        ret
    __m128 load1(const float*p) {  return _mm_load1_ps(p); }
        vbroadcastss    xmm0, DWORD PTR [rdi]
        ret
    

    【讨论】:

    猜你喜欢
    • 2011-10-15
    • 1970-01-01
    • 1970-01-01
    • 2012-02-11
    • 2012-05-07
    • 2012-10-01
    • 1970-01-01
    • 1970-01-01
    • 2019-02-17
    相关资源
    最近更新 更多