【问题标题】:SSE2 intrinsics: access memory directlySSE2 内在函数:直接访问内存
【发布时间】:2011-03-22 09:10:42
【问题描述】:

许多 SSE 指令允许源操作数是 16 字节对齐的内存地址。例如,各种 (un)pack 指令。 PUNCKLBW 具有以下签名:

PUNPCKLBW xmm1, xmm2/m128

现在这对于内在函数似乎根本不可能。看起来必须使用 _mm_load* 内在函数来读取内存中的任何内容。这是 PUNPCKLBW 的内在特性:

__m128i _mm_unpacklo_epi8 (__m128i a, __m128i b);

(据我所知,__m128i 类型总是引用 XMM 寄存器。)

现在,这是为什么呢?这是相当可悲的,因为我看到了直接寻址内存的一些优化潜力......

【问题讨论】:

    标签: optimization assembly sse simd intrinsics


    【解决方案1】:

    内在函数相对直接对应于实际指令,但编译器没有义务发出相应的指令。将操作后的加载(即使以内部函数编写)优化到操作的内存形式中是所有受人尊敬的编译器在有利时执行的常见优化。

    TLDR:将加载和操作写在intrinsic中,让编译器对其进行优化。

    编辑:简单的例子:

    #include <emmintrin.h>
    __m128i foo(__m128i *addr) {
        __m128i a = _mm_load_si128(addr);
        __m128i b = _mm_load_si128(addr + 1);
        return _mm_unpacklo_epi8(a, b);
    }
    

    使用gcc -Os -fomit-frame-pointer 编译得到:

    _foo:
    movdqa      (%rdi), %xmm0
    punpcklbw 16(%rdi), %xmm0
    retq
    

    看到了吗?优化器会对其进行排序。

    【讨论】:

    • 如果编译器对其进行了优化,我不会抱怨,但至少 clang 和 gcc 不会。这很容易使用 -S 选项进行检查。我找到了几乎所有内在函数的逐字内在函数-> 汇编翻译,并且可以将寄存器直接映射到变量。看起来这些编译器几乎没有优化 SIMD 内部代码......
    • @dietr:clang 和 gcc 都执行此优化,如您在我的示例中所见。您是否在关闭优化的情况下进行构建?尝试使用-O1 或更高版本。
    • 我正在使用-O2。我猜 gcc/clang 在我的特定代码中根本看不到任何优化潜力......
    【解决方案2】:

    您可以直接使用您的内存值。例如:

    __m128i *p=static_cast<__m128i *>(_aligned_malloc(8*4,16));
    
    for(int i=0;i<32;++i)
        reinterpret_cast<unsigned char *>(p)[i]=static_cast<unsigned char>(i);
    
    __m128i xyz=_mm_unpackhi_epi8(p[0],p[1]);
    

    结果中有趣的部分:

    ; __m128i xyz=_mm_unpackhi_epi8(p[0],p[1]);
    0040BC1B 66 0F 6F 00      movdqa      xmm0,xmmword ptr [eax] 
    0040BC1F 66 0F 6F 48 10   movdqa      xmm1,xmmword ptr [eax+10h] 
    0040BC24 66 0F 68 C1      punpckhbw   xmm0,xmm1 
    0040BC28 66 0F 7F 04 24   movdqa      xmmword ptr [esp],xmm0 
    

    所以编译器的工作有点糟糕——或者这种方式更快和/或使用选项可以解决这个问题——但它生成的代码可以工作,而 C++ 代码正在说明它想要什么相当直接。

    【讨论】:

      猜你喜欢
      • 2013-02-22
      • 2014-04-15
      • 2010-10-13
      • 2012-12-28
      • 1970-01-01
      • 1970-01-01
      • 2015-08-22
      • 2013-08-12
      • 1970-01-01
      相关资源
      最近更新 更多