代码之家  ›  专栏  ›  技术社区  ›  David L Morris

哪个编译得更快:“n*3”或“n+(n*2)”?

  •  6
  • David L Morris  · 技术社区  · 16 年前

    哪个编译成更快的代码:“ans=n*3”或“ans=n+(n*2)”?

    假设n是int或long,并且运行在现代的win32 intel设备上。

    如果涉及到一些解引用,这会有所不同吗,也就是说,哪一个会更快?

    long    a;
    long    *pn;
    long     ans;
    
    ...
    *pn = some_number;
    ans = *pn * 3;
    

    ans = *pn+(*pn*2);
    

    或者,在任何情况下,优化编译器都可能解决这一问题,这是否是人们不必担心的问题?

    11 回复  |  直到 12 年前
        1
  •  55
  •   aku    16 年前

    IMO这样的微优化是不必要的,除非您使用一些特殊的编译器。我会把可读性放在第一位。

        2
  •  15
  •   Ferruccio    16 年前

    没关系。现代处理器可以在一个或更少的时钟周期内执行整数MUL指令,而不像旧的处理器需要执行一系列的移位和内部添加以执行MUL,从而使用多个周期。我敢打赌

    MUL EAX,3
    

    执行速度比

    MOV EBX,EAX
    SHL EAX,1
    ADD EAX,EBX
    

    这类优化可能有用的最后一个处理器可能是486。(是的,这偏向于Intel处理器,但也可能代表其他体系结构)。

    在任何情况下,任何合理的编译器都应该能够生成最小/最快的代码。所以,总是首先考虑可读性。

        3
  •  10
  •   Antti Kissaniemi    16 年前

    因为你自己很容易测量,为什么不这样做呢?(使用) gcc time 来自CygWin)

    /* test1.c */
    int main()
    {
        int result = 0;
        int times = 1000000000;
        while (--times)
            result = result * 3;
        return result;
    }
    
    machine:~$ gcc -O2 test1.c -o test1
    machine:~$ time ./test1.exe
    
    real    0m0.673s
    user    0m0.608s
    sys     0m0.000s
    

    测试几次,然后对另一个案例重复测试。

    如果你想偷看汇编代码, gcc -S -O2 test1.c

        4
  •  4
  •   Will Dean    16 年前

    这将取决于编译器、其配置和周围的代码。

    你不应该在没有测量的情况下尝试猜测事物是否“更快”。

    一般来说 现在你不应该担心这种纳米级优化的东西——它几乎总是完全无关的,如果你真的在一个重要的领域工作,你就已经在使用一个分析器并查看编译器的汇编语言输出了。

        5
  •  4
  •   Tim Cooper    12 年前

    不难发现编译器对您的代码做了什么(我在这里使用的是devstudio 2005)。用以下代码编写一个简单程序:

    int i = 45, j, k;
    j = i * 3;
    k = i + (i * 2);
    

    在中间行放置一个断点,然后使用调试器运行代码。当触发断点时,右键单击源文件并选择“转到反汇编”。现在您将有一个窗口,其中包含CPU正在执行的代码。在这种情况下,您会注意到最后两行产生完全相同的指令,即“lea eax,[ebx+ebx*2]”(在这种特殊情况下不进行位移位和添加)。在现代IA32 CPU上,由于CPU的流水线性质,直接执行mul而不是位移动可能更有效,这会在过早使用修改后的值时招致惩罚。

    这说明了AKU所说的,也就是说,编译器足够聪明,可以为代码选择最好的指令。

        6
  •  1
  •   Vinko Vrsalovic    16 年前

    它确实取决于您实际使用的编译器,但很可能它们转换为相同的代码。

    您可以通过创建一个小的测试程序并检查它的反汇编来自己检查它。

        7
  •  1
  •   Paul Tomblin    16 年前

    大多数编译器都足够聪明,可以将整数乘法分解成一系列的位移位和加法。我不知道Windows编译器,但至少在GCC中,你可以让它吐出汇编程序,如果你看一下它,你可能会发现在两种编写方式中都有相同的汇编程序。

        8
  •  1
  •   Angel    16 年前

    不在乎。我认为还有更重要的事情要优化。你花了多少时间思考和写这个问题,而不是自己编码和测试?

    -)

        9
  •  1
  •   Community CDub    8 年前

    只要你使用一个合适的优化编译器, 编写易于编译器理解的代码 . 这使得编译器更容易执行巧妙的优化。

    您问这个问题表明优化编译器比您更了解优化。所以相信编译器。使用 n * 3 .

    看一看 this answer 也。

        10
  •  0
  •   Konrad Rudolph    16 年前

    编译器擅长优化您的代码。任何现代编译器都会为这两种情况生成相同的代码,并另外替换 * 2 左移。

        11
  •  0
  •   Mark D    16 年前

    相信您的编译器可以优化这样的代码片段。可读性在代码级别更重要。真正的优化应该在更高的层次上进行。