SSE slower than FPU?
SSE slower than FPU?
我有一大块代码,其中一部分包含以下代码:
result = (nx * m_Lx + ny * m_Ly + m_Lz) / sqrt(nx * nx + ny * ny + 1);
我已经将其矢量化如下(一切都已经是float
):
__m128 r = _mm_mul_ps(_mm_set_ps(ny, nx, ny, nx),
_mm_set_ps(ny, nx, m_Ly, m_Lx));
__declspec(align(16)) int asInt[4] = {
_mm_extract_ps(r,0), _mm_extract_ps(r,1),
_mm_extract_ps(r,2), _mm_extract_ps(r,3)
};
float (&res)[4] = reinterpret_cast<float (&)[4]>(asInt);
result = (res[0] + res[1] + m_Lz) / sqrt(res[2] + res[3] + 1);
结果是正确的;然而,我的基准测试显示,矢量化版本的速度慢:
- 非矢量化版本需要3750毫秒
- 矢量化版本需要4050毫秒
- 直接将
result
设置为0
(并完全删除这部分代码)可将整个过程缩短至2500毫秒
既然矢量化版本只包含一组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,如酷睿i5、酷睿i7,有两个标量FPU,每个时钟可以发出2个浮点乘法。因此,SSE对单精度浮点的潜在好处最多只有2倍。如果你有过多的"内务管理"说明,很容易失去大部分/全部这2倍的好处,就像这里的情况一样。
有几个问题:
- 在这样的操作中使用SSE指令不会有太多好处,因为SSE指令应该在并行操作(即同时乘以多个值)上更好。你的所作所为是对SSE的滥用
- 不要设置值,使用指向数组中第一个值的指针,但是您的值不在数组中
- 不要提取值并将其复制到数组中。这也是对SSE的滥用。结果应该在一个数组中
我认为处理器在加载下一个值时使用FPU有时间计算第一次乘法。SSE必须首先加载所有值。
相关文章:
- Clang:x86 FPU调用约定
- D-lang being faster than C++?
- 为什么需要 FPU 重置以防止 NaN 结果传播到下一个计算结果?
- MATLAB faster than LAPACK?
- "How to use long long data-type rather than pointers data-type to modify other variables ?"
- 获取所有 FPU 寄存器的值,甚至"empty"个寄存器的值
- 如何实现随机访问迭代器的"less than operator"?
- 如何在 C++ 类中重载 'less than' 运算符以比较常量?
- 为什么我收到错误:"there is more than one default constructor"?
- std::tuple faster than std::array?
- 有没有办法通过'greater/lesser than'而不是"="来定义'int'?
- FPU中数量少的计算故障
- "compares less than 0"是什么意思?
- FPU控制功能是否与x64_64处理器相关
- OpenSSL 错误"data greater than mod len"
- 特征:如何将"greater than"的结果(在ArrayXf上)转换为特征向量
- Is calloc better than malloc?
- "less than" 与GCC 4与6的ifstream比较
- 在 C 族中,在一个循环中,为什么"less than or equal to"比"less than"符号更受欢迎?
- SSE slower than FPU?