如何避免指针运算中的乘法?

时间:2014-02-13 11:41:00

标签: c++ visual-c++ code-generation multiplication pointer-arithmetic

如果我写

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秒。

是的,这确实很慢。

1 个答案:

答案 0 :(得分:8)

  

为什么我在这里得到imul指令而不仅仅是位移等?

乘法是除以3(每个内部数组的大小),使用0x2AAAAAAB是2 31 / 3的事实。你不能通过少量的轮班和补充来做到这一点;乘法确实是最快的选择。

  

我怀疑imul正在扼杀其表现。

在大多数现代平台上,整数乘法通常与更简单的操作一样快,因此它可能是最快的选项,即使它可以被一些移位和添加替换。当您遇到性能问题时,请始终测量以找出真正的瓶颈;他们经常出现在你最不怀疑的地方。

  

是否有一种很好的方法可以一般地防止它,而是用更便宜的操作取而代之?

在乘法确实很昂贵的平台上:避免使用大小不合适的数据结构;并避免减去指针,因为这需要除以对象大小。