如果我写
int main(int argc, char *argv[])
{
int temp[50][3];
return &temp[argc] - &temp[0];
}
用Visual C ++编译它,我回来了:
009360D0 55 push ebp
009360D1 8B EC mov ebp,esp
009360D3 8B 45 08 mov eax,dword ptr [argc]
009360D6 8D 0C 40 lea ecx,[eax+eax*2]
009360D9 B8 AB AA AA 2A mov eax,2AAAAAABh
009360DE C1 E1 02 shl ecx,2
009360E1 F7 E9 imul ecx
009360E3 D1 FA sar edx,1
009360E5 8B C2 mov eax,edx
009360E7 C1 E8 1F shr eax,1Fh
009360EA 03 C2 add eax,edx
009360EC 5D pop ebp
009360ED C3 ret
为什么我在这里得到imul
指令而不仅仅是位移等等?我觉得这很烦人,因为我在紧密的循环中做这样的指针运算,我怀疑imul
正在扼杀它的性能。无论如何,它没有必要。
是否有一种很好的方法可以一般地防止它,而是用更便宜的操作取而代之?
在我的原始程序中,我尝试添加一个虚拟变量,使每个元素的大小为4的倍数,而不是3,因此编译器可以使用位移而不是除法。
结果呢?即使数据结构较大,程序的运行时间也从9.2秒减少到7.4秒。
是的,这确实很慢。
答案 0 :(得分:8)
为什么我在这里得到
imul
指令而不仅仅是位移等?
乘法是除以3(每个内部数组的大小),使用0x2AAAAAAB
是2 31 / 3的事实。你不能通过少量的轮班和补充来做到这一点;乘法确实是最快的选择。
我怀疑
imul
正在扼杀其表现。
在大多数现代平台上,整数乘法通常与更简单的操作一样快,因此它可能是最快的选项,即使它可以被一些移位和添加替换。当您遇到性能问题时,请始终测量以找出真正的瓶颈;他们经常出现在你最不怀疑的地方。
是否有一种很好的方法可以一般地防止它,而是用更便宜的操作取而代之?
在乘法确实很昂贵的平台上:避免使用大小不合适的数据结构;并避免减去指针,因为这需要除以对象大小。