【发布时间】:2025-09-27 18:35:02
【问题描述】:
我正在尝试优化循环中的指令块,称为数千次,这是我算法的瓶颈。
此代码块计算 N 个矩阵 3x3(iA 数组)与 N 个向量 3(iV 数组)的乘法,并将 N 个结果存储在 oV 数组中。 (N 不固定,通常在 3000 到 15000 之间)
每行矩阵和向量都是 128 位对齐(4 个浮点数)以利用 SSE 优化(忽略第 4 个浮点值)。
C++ 代码:
__m128* ip = (__m128*)iV;
__m128* op = (__m128*)oV;
__m128* A = (__m128*)iA;
__m128 res1, res2, res3;
int i;
for (i=0; i<N; i++)
{
res1 = _mm_dp_ps(*A++, *ip, 0x71);
res2 = _mm_dp_ps(*A++, *ip, 0x72);
res3 = _mm_dp_ps(*A++, *ip++, 0x74);
*op++ = _mm_or_ps(res1, _mm_or_ps(res2, res3));
}
编译器生成这些指令:
000007FEE7DD4FE0 movaps xmm2,xmmword ptr [rsi] //move "ip" in register
000007FEE7DD4FE3 movaps xmm1,xmmword ptr [rdi+10h] //move second line of A in register
000007FEE7DD4FE7 movaps xmm0,xmmword ptr [rdi+20h] //move third line of A in register
000007FEE7DD4FEB inc r11d //i++
000007FEE7DD4FEE add rbp,10h //op++
000007FEE7DD4FF2 add rsi,10h //ip++
000007FEE7DD4FF6 dpps xmm0,xmm2,74h //dot product of 3rd line of A against ip
000007FEE7DD4FFC dpps xmm1,xmm2,72h //dot product of 2nd line of A against ip
000007FEE7DD5002 orps xmm0,xmm1 //"merge" of the result of the two dot products
000007FEE7DD5005 movaps xmm3,xmmword ptr [rdi] //move first line of A in register
000007FEE7DD5008 add rdi,30h //A+=3
000007FEE7DD500C dpps xmm3,xmm2,71h //dot product of 1st line of A against ip
000007FEE7DD5012 orps xmm0,xmm3 //"merge" of the result
000007FEE7DD5015 movaps xmmword ptr [rbp-10h],xmm0 //move result in memory (op)
000007FEE7DD5019 cmp r11d,dword ptr [rbx+28h] //compare i
000007FEE7DD501D jl MyFunction+370h (7FEE7DD4FE0h) //loop
我对低级优化不是很熟悉,所以问题是:如果我自己编写汇编代码,你会看到一些可能的优化吗?
例如,如果我改变它会运行得更快吗:
add rbp,10h
movaps xmmword ptr [rbp-10h],xmm0
通过
movaps xmmword ptr [rbp],xmm0
add rbp,10h
我还读到 ADD 指令比 INC 快...
【问题讨论】:
-
对于您询问的特定微优化(
add/movaps和add与inc的顺序)可能取决于您编码的特定 CPU 类型,阶段月亮等。我想即使您尝试过,您也不会看到可测量的差异,因为速度上的任何差异都会与主要计算中花费的时间重叠。从大局来看,我没有看到该代码有很多脂肪。也许 SSE 专家可以评论矢量化映射到英特尔矢量指令的程度。 -
“我还读到 ADD 指令比 INC 快...” -- 真的吗?我不知道组装的废话,但这似乎很奇怪。如果是这样的话,当你可以使用带有参数 1 的 ADD 时,你为什么还要使用 INC 呢?为什么 INC 会存在?
-
add与inc的事情与标志有关,在inc之后读取进位标志可能会带来麻烦。在 P4 上它有点相反,inc必须等待标志。在这种情况下,您会立即覆盖标志,所以这个inc在 P4 上不是问题(严重的是,谁在乎 P4) -
@BenjaminLindley 因为它已经存在。他们不能只是删除它。
inc的问题在 8086 中不存在,它只是在当时串行执行一条指令。 -
@harold:好的。这就说得通了。谢谢。
标签: c++ optimization assembly x86 sse