内联时奇怪的编译器行为(包括ASM代码)

时间:2013-11-18 02:05:11

标签: c++ optimization inline simd

我的问题是,编译器选择不在特定情况下内联函数,从而使代码变得更慢。该函数应该计算向量的点积(SIMD加速)。我写了有两种不同的风格:

  1. Vector类聚合__m128成员。
  2. Vector只是__m128成员的typedef。
  3. 在案例1中,我得到的代码慢2倍,该函数不会内联。 在案例2中,我获得了最佳代码,非常快,内联。

    在案例1中,Vector和Dot函数如下所示:

    __declspec(align(16)) class Vector
    {
        public:
            __m128 Entry;
    
           Vector(__m128 s)
          {
              Entry = s;
          }
    };
    
    Vector Vector4Dot(Vector v1, Vector v2)
    {
        return(Vector(_mm_dp_ps(v1.Entry, v2.Entry, DotMask4)));
    }
    

    在案例2中,Vector和Dot函数如下所示:

    typedef __m128 Vector;
    
    Vector Vector4Dot(Vector v1, Vector v2)
    {
        return(_mm_dp_ps(v1, v2, DotMask4));
    }
    

    我正在发布模式下在x86上的Visual Studio 2012中编译MSVC,启用所有优化,优化速度,整个程序优化等。是否我将案例1的所有代码放在标题中或使用它与组合使用forceinline,没关系,它没有内联。这是生成的ASM:

    案例1:

    movaps  xmm0, XMMWORD PTR [esi]
    lea eax, DWORD PTR $T1[esp+32]
    movaps  xmm1, xmm0
    push    eax
    call    ?Vector4Dot@Framework@@SA?AVVector@23@T__m128@@0@Z ; Framework::Vector4Dot
    movaps  xmm0, XMMWORD PTR [eax]
    add esp, 4
    movaps  XMMWORD PTR [esi], xmm0
    lea esi, DWORD PTR [esi+16]
    dec edi
    jne SHORT $LL3@Test89
    

    这是我调用Vector4Dot的地方。这里是它的内部(函数):

    mov eax, DWORD PTR _v2$[esp-4]
    movaps  xmm0, XMMWORD PTR [edx]
    dpps    xmm0, XMMWORD PTR [eax], 255        ; 000000ffH
    movaps  XMMWORD PTR [ecx], xmm0
    mov eax, ecx
    

    对于案例2,我得到:

    movaps  xmm0, XMMWORD PTR [eax]
    dpps    xmm0, xmm0, 255             ; 000000ffH
    movaps  XMMWORD PTR [eax], xmm0
    lea eax, DWORD PTR [eax+16]
    dec ecx
    jne SHORT $LL3@Test78
    

    哪个更快。我不知道为什么编译器无法处理那个构造函数。如果我像这样改变case1:

    __m128 Vector4Dot(Vector v1, Vector v2)
    {
        return(_mm_dp_ps(v1.Entry, v2.Entry, DotMask4));
    }
    

    它以最大速度编译,与案例2相同。正是这种“类开销”给了我性能损失。有什么方法可以解决这个问题吗?或者我坚持使用原始__m128而不是Vector类?

0 个答案:

没有答案