当我所做的只是将循环代码移动到函数中时,代码运行速度慢十倍

时间:2011-08-06 00:28:32

标签: c++ performance

我正在运行下面的代码,基本上做的很少。它只增加2和4亿次并输出运行时。

#include "time.h"
#include <iostream>
using namespace std;

void add (){
int tot = 2+4;
}

void main(){
int t = clock();
int count = 0;
while(count<100000000){
    int tot = 2+4;
    count++;
}
cout <<endl<< "runtime = " << fixed <<(double) (clock() - t) / CLOCKS_PER_SEC <<"s" << endl;

}

但我有兴趣看到完成相同但调用函数时的时差。所以我用“add()”替换了“int tot = 2 + 4”这一行。

我原本期望第二个运行时间略长,但时间要长得多。第一次实施= .3s,第二次实施= 3s

我理解调用该函数需要使用堆栈来存储返回地址并存储本地数据。但它必须做很多更多呢?

如果有人可以向我解释究竟是什么导致了运行时间的巨大差异,或者我正在做一些愚蠢的事情,那将会很棒。

3 个答案:

答案 0 :(得分:5)

正如Seth已经提到的,内联函数可能会得到优化。

在第一种情况下(基本优化)最有可能而不是不断添加这两个数字,它将解决2 + 4到6而只是做一个简单的

mov eax, 6 ;eax is just an example here or
mov tot_addr, 6 ; mem->mem mov

在第二种情况下,因为它是一个函数调用,系统必须

push 4 ;assuming 4 byte ints
push 4 ;wrote 2 to be clear that you have to push both variables
call add

或沿着这些方向的东西。因为需要为该函数创建调用堆栈(为了简单起见,省略了返回值push等)。一旦该函数返回,堆栈指针需要在第一次推送之前移回,然后RET将设置指令指针。正如您所看到的,这比做一个简单的

更昂贵
mov eax, 4
add eax, 2

如果你只做一个简单的(非优化的添加)

,可能就是这种情况

编辑:这里有一些关于内嵌函数的更多信息。当你内联函数时,它只需要函数本身可以执行的任何功能,并将指令直接放在引用的位置,而不是执行CALL指令并直接设置函数调用。例如,而不是

mov eax, 4
mov ecx, 2
push 4 ; size for return value
push eax
push ecx
call add

你最终会得到

mov eax, 4
mov exc, 2
add eax, ecx

在代码中:

int a = 4;
int b = 2;
int res = add(a, b);

会变成

int a = 4;
int b = 2;
int res = a + b;

假设您内联添加功能。

答案 1 :(得分:2)

相对于做其他事情,函数调用非常昂贵(比你想象的要贵),正如你提到的那样。尝试声明您的函数inline和/或启用优化以恢复性能。

答案 2 :(得分:0)

函数调用确实可以为CPU做更多的工作,而不仅仅是按下返回地址和参数。

在某些CPU上,你会遇到管道停滞。在阅读下一条指令时,甚至可能会出现i-cache错误。这些很容易造成你所注意到的10倍减速。

这就是为什么编译器会竭尽全力优化函数调用。