Phi*_*tor 2 optimization performance x86 assembly simd
是它更快地通过的装置计算两个向量的点积dpps指令形式SSE 4.1指令集或通过使用一系列的addps,shufps并mulps从SSE 1?
答案可能非常具有上下文性,并且完全取决于在更大的代码流中使用的位置和方式,以及您正在使用的硬件.
从历史上看,当英特尔推出新指令时,他们并没有专注于硬件领域.如果它被充分利用和使用,他们会在后代中使用更多的硬件.因此_mm_dp_ps,与原始ALU性能方面的SSE2方式相比,Penryn并不是特别令人印象深刻.另一方面,它确实需要I-cache中较少的指令,因此当更紧凑的编码表现更好时,它可能会有所帮助.
真正的问题_mm_dp_ps是作为SSE 4.1的一部分,你不能指望它在每一台现代PC都得到支持(Valve的Steam硬件调查将游戏玩家约为85%).因此,您最终必须编写受保护的代码路径而不是直线代码,这通常比使用该指令所带来的好处更高.
它是有用的,如果你为一个保证支持它的CPU制作二进制文件.例如,如果您正在构建/arch:AVX(或甚至/arch:AVX2),因为您的目标是像Xbox One这样的固定平台,或者正在构建EXE/DLL的多个版本,您也可以假设也支持SSE 4.1.
这实际上是DirectXMath的作用:
inline XMVECTOR XMVector4Dot( FXMVECTOR V1, FXMVECTOR V2 )
{
#if defined(_XM_NO_INTRINSICS_)
XMVECTOR Result;
Result.vector4_f32[0] =
Result.vector4_f32[1] =
Result.vector4_f32[2] =
Result.vector4_f32[3] = V1.vector4_f32[0] * V2.vector4_f32[0] + V1.vector4_f32[1] * V2.vector4_f32[1] + V1.vector4_f32[2] * V2.vector4_f32[2] + V1.vector4_f32[3] * V2.vector4_f32[3];
return Result;
#elif defined(_M_ARM) || defined(_M_ARM64)
float32x4_t vTemp = vmulq_f32( V1, V2 );
float32x2_t v1 = vget_low_f32( vTemp );
float32x2_t v2 = vget_high_f32( vTemp );
v1 = vpadd_f32( v1, v1 );
v2 = vpadd_f32( v2, v2 );
v1 = vadd_f32( v1, v2 );
return vcombine_f32( v1, v1 );
#elif defined(__AVX__) || defined(__AVX2__)
return _mm_dp_ps( V1, V2, 0xff );
#elif defined(_M_IX86) || defined(_M_X64)
XMVECTOR vTemp2 = V2;
XMVECTOR vTemp = _mm_mul_ps(V1,vTemp2);
vTemp2 = _mm_shuffle_ps(vTemp2,vTemp,_MM_SHUFFLE(1,0,0,0));
vTemp2 = _mm_add_ps(vTemp2,vTemp);
vTemp = _mm_shuffle_ps(vTemp,vTemp2,_MM_SHUFFLE(0,3,0,0));
vTemp = _mm_add_ps(vTemp,vTemp2);
return _mm_shuffle_ps(vTemp,vTemp,_MM_SHUFFLE(2,2,2,2));
#else
#error Unsupported platform
#endif
}
Run Code Online (Sandbox Code Playgroud)
这当然假设您将在其他向量操作中使用点积的"标量"结果.按照惯例,DirectXMath会在返回向量中返回这些标量"splatted".
更新:虽然不是很普及,因为SSE/SSE2支持,你可能需要SSE3支持,你是不是与建设情况/arch:AVX还是/arch:AVX2和尝试:
inline XMVECTOR XMVector4Dot(FXMVECTOR V1, FXMVECTOR V2)
{
XMVECTOR vTemp = _mm_mul_ps(V1,V2);
vTemp = _mm_hadd_ps( vTemp, vTemp );
return _mm_hadd_ps( vTemp, vTemp );
}
Run Code Online (Sandbox Code Playgroud)
也就是说,目前尚不清楚hadd在大多数情况下,对于SSE/SSE2添加和改组解决方案而言至少是dot-product的胜利.