Performance Dot产品性能与SSE说明

Performance Dot产品性能与SSE说明,performance,assembly,optimization,x86,simd,Performance,Assembly,Optimization,X86,Simd,通过SSE 4.1指令集中的dpps指令或使用SSE 1中的一系列addps、shufps和mulps计算两个向量的点积是否更快?答案可能是非常有关联的,这完全取决于它在更大的代码流中的位置和使用方式,以及您使用的硬件 从历史上看,当英特尔推出新指令时,他们并没有为其投入太多的硬件领域。如果它得到足够的采用和使用,他们将在未来几代人中投入更多的硬件。因此,就原始ALU性能而言,与SSE2方式相比,Penryn上的\u-mm\u-dp\u-ps并不是特别令人印象深刻。另一方面,它在I-cache中

通过SSE 4.1指令集中的
dpps
指令或使用SSE 1中的一系列
addps
shufps
mulps
计算两个向量的点积是否更快?

答案可能是非常有关联的,这完全取决于它在更大的代码流中的位置和使用方式,以及您使用的硬件

从历史上看,当英特尔推出新指令时,他们并没有为其投入太多的硬件领域。如果它得到足够的采用和使用,他们将在未来几代人中投入更多的硬件。因此,就原始ALU性能而言,与SSE2方式相比,Penryn上的
\u-mm\u-dp\u-ps
并不是特别令人印象深刻。另一方面,它在I-cache中需要更少的指令,因此当更紧凑的编码性能更好时,它可能会有潜在的帮助

\u mm\u dp\u ps
的真正问题是作为SSE 4.1的一部分,你不能指望它在每台现代PC上都能得到支持(Valve的Steam硬件调查显示,游戏玩家的支持率约为85%)。因此,您最终不得不编写受保护的代码路径,而不是直线代码,这通常比使用该指令所获得的好处成本更高

如果您正在为保证支持它的CPU制作二进制文件,那么它将非常有用。例如,如果您正在使用
/arch:AVX
(甚至
/arch:AVX2
)进行构建,因为您的目标是像Xbox One这样的固定平台,或者正在构建多个版本的EXE/DLL,那么您可以假设SSE 4.1也将受到支持

这实际上是:

当然,这假设您将在其他向量操作中使用点积的“标量”结果。按照惯例,DirectXMath返回在返回向量上“飞溅”的标量

更新:虽然没有SSE/SSE2支持那么普遍,但对于您没有使用
/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
在大多数情况下至少是dot产品在SSE/SSE2添加和洗牌解决方案上的胜算还不清楚。

相关:但没有什么比一个好的旧性能测试更好了……这有更多的背景吗?通常整个情况下,必须做一个水平点积在第一位,如何才能避免?你能举个例子吗?例如,如果你在计算两个较大向量之间的点积,它不应该通过点小部分并将它们相加来建立(可以,但这是对水平运算的浪费),或者如果你基本上是在做微小的点积,那么在向量寄存器中没有向量几乎总是更好的,但是使用一个只有x坐标的向量,一个只有y坐标的向量等等,但是这两个都不适用。。这取决于你为什么不对它进行基准测试?由于您可能必须实现一个版本,尝试另一个版本不会有什么大不了的。
DPP
在Intel SnB系列CPU上的uop缓存中仍然需要4个uop,这通常是比一级I-cache更宝贵的资源。然而,这看起来确实像是uops战胜了该案例的后援。与水平求和的haddps不同,它只需4个UOP就能完成整个过程。
haddps
是SSE3,从技术上讲,x64 CPU或Windows 8.1/Windows 10不需要SSE3,尽管Valve调查显示它的支持率为99%,因此它在任何地方都能有效地为玩家提供支持。请参阅@Peter-SSE3版本与“回退”相比如何?除了代码大小之外,其他方面看起来都更糟糕
haddps
是3 UOP,5c延迟(在Haswell上)。所以在mulps之后,2xhaddps是4次洗牌和2次加法。SSE2版本是3次洗牌和2次添加,延迟为9c而不是10。(不包括mul)。顺便说一句,我以前没有看过,但这是一个很好的使用
\u mm\u shuffle\u ps
和两个不同的输入变量,以避免需要
movaps
来保存旧值以供下一次添加。但是,其中一个洗牌应该是
movhlps
:在奔腾M/Merom/K8上更快(洗牌速度较慢)。有关一些优化的水平和,请参阅。嗯,我认为你可以避免最后一次的广播洗牌,代价是额外增加1到2个movap,通过洗牌使最后一次添加的所有元素产生完整的结果。
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 );
}