c – SSE比FPU慢?

我有一大块代码,其中的一部分包含这段代码
result = (nx * m_Lx + ny * m_Ly + m_Lz) / sqrt(nx * nx + ny * ny + 1);

我已经矢量化了如下(一切已经是一个浮动):

__m128 r = _mm_mul_ps(_mm_set_ps(ny,nx,ny,nx),_mm_set_ps(ny,m_Ly,m_Lx));
__declspec(align(16)) int asInt[4] = {
    _mm_extract_ps(r,0),_mm_extract_ps(r,1),2),3)
};
float (&res)[4] = reinterpret_cast<float (&)[4]>(asInt);
result = (res[0] + res[1] + m_Lz) / sqrt(res[2] + res[3] + 1);

结果是正确的然而,我的基准测试表明矢量化版本较慢:

>非矢量化版本需要3750 ms
>矢量化版本需要4050 ms
>直接将结果设置为0(完全删除这部分代码)将整个过程减少到2500 ms

给定矢量化版本只包含一组SSE乘法(而不是四个单独的FPU乘法),为什么它较慢? FPU确实比SSE快,还是在这里有混乱的变数?

(我在手机Core i5上.)

解决方法

您正在花费大量时间将标量值与_mm_set_ps和_mm_extract_ps的SSE寄存器进行移动 – 这正在生成大量指令,其执行时间远远超过使用_mm_mul_ps所带来的任何好处.看看生成的程序集输出,以查看除了单个MULPS指令之外还要生成多少代码.

为了正确向量化,您需要使用128位SSE加载和存储(_mm_load_ps / _mm_store_ps),然后使用SSE随机播放指令在需要的寄存器内移动元素.

另外要注意的是现代cpu(如Core i5,Core i7)有两个标量FPU,每个时钟可以发出2个浮点倍增.因此,SSE对单精度浮点的潜在收益最多只有2倍.如果您有过多的“家务”说明,这很容易损失大部分/所有这2x的好处.

相关文章

本程序的编译和运行环境如下(如果有运行方面的问题欢迎在评...
水了一学期的院选修,万万没想到期末考试还有比较硬核的编程...
补充一下,先前文章末尾给出的下载链接的完整代码含有部分C&...
思路如标题所说采用模N取余法,难点是这个除法过程如何实现。...
本篇博客有更新!!!更新后效果图如下: 文章末尾的完整代码...
刚开始学习模块化程序设计时,估计大家都被形参和实参搞迷糊...