【问题标题】:SSE2 assembly-overflow using intrinsics使用内在函数的 SSE2 程序集溢出
【发布时间】:2011-10-22 18:28:39
【问题描述】:

我是 SSE 和 SSE2 的新手,我编写了一个小的 C 示例(分配两个计数器,一个增加一个减少而不是增加两个),它按预期工作。我使用了内在函数和 Microsoft Visual Studio 10 C++ Express。作为第二步,我想了解引擎盖下发生了什么,但我现在很困惑。 例如 for 循环中的赋值操作编译为:

__m128i a_ptr = _mm_load_si128((__m128i*)&(a_aligned[i]));
 mov         eax,dword ptr [i]  
 mov         ecx,dword ptr [a_aligned]  
 movdqa      xmm0,xmmword ptr [ecx+eax*2]  
 movdqa      xmmword ptr [ebp-1C0h],xmm0  
 movdqa      xmm0,xmmword ptr [ebp-1C0h]  
 movdqa      xmmword ptr [a_ptr],xmm0  

我知道前两行获取 a_aligned 地址的组成部分,第三行将其复制到 xmm0 寄存器。但我不明白为什么它被复制回内存,而不是再次复制到 xmm0(而不是 a_ptr)。我认为 _mm_load_si128 内在函数应该将 a_aligned[i] 的 128 位复制到 xmm0,仅此而已。为什么会这样?我理论上错了吗?如果不是,我应该如何提示编译器?我的示例代码是否正确(从某种意义上说它没有不必要的东西)? 这是我的完整示例代码:

#include <xmmintrin.h>
#include <emmintrin.h>
#include <iostream>

int main(int argc, char *argv[]) {
    unsigned __int16 *a_aligned = (unsigned __int16 *)_mm_malloc(32 * sizeof(unsigned __int16),16);
    unsigned __int16 *b_aligned = (unsigned __int16 *)_mm_malloc(32 * sizeof(unsigned __int16),16);
    unsigned __int16 *c_aligned = (unsigned __int16 *)_mm_malloc(32 * sizeof(unsigned __int16),16);

    for(int i = 0; i < 32; i++) {
        a_aligned[i] = i;
        b_aligned[i] = i;
        c_aligned[i] = 0;
    }

    for(int i = 0; i < 32; i+=8) {
        __m128i a_ptr = _mm_load_si128((__m128i*)&(a_aligned[i]));
        __m128i b_ptr = _mm_load_si128((__m128i*)&(b_aligned[i]));
        __m128i res = _mm_add_epi16(a_ptr, b_ptr);
        _mm_store_si128((__m128i*)&(c_aligned[i]), res);
    }

    for(int i = 1; i < 32; i++) {
        std::cout << c_aligned[i] << " ";
    }

    _mm_free(a_aligned);
    _mm_free(b_aligned);
    _mm_free(c_aligned);
    return 0;
}

【问题讨论】:

    标签: assembly intrinsics sse2


    【解决方案1】:

    Intrinsics 被明确设计用于帮助编译器代码生成器更好地优化代码。您正在查看由 Debug 配置生成的汇编代码。那不是优化的代码。查看 Release 构建中的代码:

            __m128i a_ptr = _mm_load_si128((__m128i*)&(a_aligned[i]));
    011D10A0  movdqa      xmm0,xmmword ptr [eax] 
            __m128i b_ptr = _mm_load_si128((__m128i*)&(b_aligned[i]));
    011D10A4  movdqa      xmm1,xmmword ptr [edx+eax] 
            __m128i res = _mm_add_epi16(a_ptr, b_ptr);
    011D10A9  paddw       xmm0,xmm1 
            _mm_store_si128((__m128i*)&(c_aligned[i]), res);
    011D10AD  movdqa      xmmword ptr [ecx+eax],xmm0 
    

    看起来更好,不是吗?

    【讨论】:

    • 谢谢,您的回答和 Stephen Canon 的一样有帮助,但他是第一个回答的人。
    • 是的,当您努力记录答案时会发生这种情况。不是问题,其他人可能会觉得它有用。
    【解决方案2】:

    在编译器设置中启用优化(使用发布配置而不是调试)。

    【讨论】:

    • 每个人都会遇到,别担心。
    猜你喜欢
    • 2019-06-07
    • 1970-01-01
    • 2012-02-20
    • 2012-05-17
    • 2013-02-22
    • 1970-01-01
    • 2011-03-22
    • 2011-07-10
    • 1970-01-01
    相关资源
    最近更新 更多