我的问题是,编译器选择不在特定情况下内联函数,从而使代码变得更慢。该函数应该计算向量的点积(SIMD加速)。我写了有两种不同的风格:
1.The Vector class aggregates a __m128 member.
2.The Vector is just a typedef of the __m128 member.
在案例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类?