用SSE4.1指令集中的dpps指令或使用SSE 1中的一系列addps、shufps和mulps来计算两个向量的点积是否更快?
发布于 2016-06-17 15:09:03
答案可能是非常上下文化的,并且完全取决于它在更大的codeflow中的位置和使用方式,以及您所使用的硬件。
从历史上看,当英特尔推出新的指令时,他们并没有在硬件方面投入太多的精力。如果它被采纳并得到足够的使用,他们就会在后代中投入更多的硬件。因此,与SSE2方式相比,Penryn上的SSE2在原始ALU性能方面并不特别令人印象深刻。另一方面,它确实需要i-缓存中较少的指令,以便在更紧凑的编码能够更好地执行时,它可能会有所帮助。
_mm_dp_ps真正的问题在于它是SSE4.1的一部分,你不能指望它在每台现代PC上都能得到支持(阀门的蒸汽硬件调查将游戏玩家的比例定在85%左右)。因此,您最终不得不编写有保护的代码路径,而不是直线代码,而这通常比使用指令所带来的好处还要高。
它的有用之处在于,如果您要为一个保证支持它的CPU生成二进制文件。例如,如果您使用/arch:AVX (甚至/arch:AVX2)构建,或者是因为您的目标是Xbox这样的固定平台,或者是正在构建多个版本的EXE/DLL,您可以假设SSE4.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
}当然,这假设您将在附加向量操作中使用点积的“标量”结果。按照惯例,DirectXMath在返回向量中返回这样的标量“飞溅”。
更新:虽然不像SSE/SSE 2支持的那样普遍存在,但是对于没有使用/arch:AVX或/arch:AVX2构建的情况,您可以要求SSE3支持,然后尝试:
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 );
}尽管如此,目前还不清楚在大多数情况下,hadd在多数情况下会赢得至少在SSE/SSE2添加和洗牌解决方案上的点积。
https://stackoverflow.com/questions/37879678
复制相似问题