Meh*_*dad 9 c++ optimization sse simd vectorization
我有一大段代码,其中一部分包含这段代码:
result = (nx * m_Lx + ny * m_Ly + m_Lz) / sqrt(nx * nx + ny * ny + 1);
Run Code Online (Sandbox Code Playgroud)
我已经矢量化如下(一切都已经是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);
Run Code Online (Sandbox Code Playgroud)
结果是正确的; 但是,我的基准测试显示矢量化版本较慢:
result
到0
直接(和完全除去这部分代码)降低了整个过程至2500毫秒鉴于矢量版本只包含一个集SSE乘法(而不是四个单独的FPU乘法)的,为什么会慢?FPU确实比SSE快,或者这里有混淆变量吗?
(我在移动Core i5上.)
Pau*_*l R 16
您花费大量时间将标量值移入/移出SSE寄存器,_mm_set_ps
并且_mm_extract_ps
- 这会产生大量指令,其执行时间远远超过使用的任何好处_mm_mul_ps
.查看生成的程序集输出,以查看除单个MULPS
指令之外还生成了多少代码.
要正确地向量化,您需要使用128位SSE加载和存储(_mm_load_ps
/ _mm_store_ps
),然后使用SSE shuffle指令在需要的寄存器内移动元素.
还有一点需要注意 - 现代CPU,如Core i5,Core i7,有两个标量FPU,每个时钟可以发出2个浮点乘法.因此,SSE对单精度浮点的潜在好处最多只有2倍.如果您有过多的"内务管理"说明,很容易失去大部分/全部这两项福利,就像这里的情况一样.