2012-03-09 215 views
4

有一天我意外地注意到了这一点,现在决定对它进行广泛的测试。为什么const int比const int&更快?

所以,当我调用一个函数:

#define Type int 
#define Prm const Type & 
Type testfunc1(Prm v1, Prm v2, Prm v3, Prm v4, Prm v5, Prm v6, Prm v7, Prm v8, Prm v9, Prm v10){ 
    return (v1|v2|v3|v4|v5|v6|v7|v8|v9|v10); 
} 

了100万次:

 for(Type y = 0; y < 10000; y++){ 
      for(Type x = 0; x < 10000; x++){ 
       out |= testfunc1(x,y,x,x,y,y,x,y,x,y); 
      } 
     } 

随着类型intconst intconst int &,我注意到,const intconst int &更快。 (注意:即时通讯使用返回值来确保函数不会被优化)。

这是为什么?我一直认为加入&实际上会让它更快,但测试说的是相反的。我知道更大的数据类型可能会有不同的结果,但我没有测试过,因为我对结果非常肯定。

我的测试:

const int: 7.95s 
const int &: 10.2s 

编辑:我想这是因为我对建筑的真心;我Sint64型式试验,结果是:

const Sint64: 17.5s 
const Sint64 &: 16.2s 

EDIT2:是这样吗?与double型式试验(这是64位?),而结果让我不解:

const double: 11.28s 
const double &: 12.34s 

EDIT3:更新循环代码与64位类型匹配我的最新测试。

+2

像你一样使用返回值并不能确保它不会被优化。现在,整个计算可以在编译时完成,因此编译器可以优化所有内容,只需用'0x3FFF'代替循环。 – 2012-03-09 16:51:36

+0

我会对这个问题的答案感兴趣。这可能是const int的处理方式与函数prolog代码(由编译器放入)不同,而不是const int&。我正在接受一个有教养的猜测。 – octopusgrabbus 2012-03-09 16:53:23

+0

@ R.MartinhoFernandes,好吧,如果它确实优化了它,它不会执行它7.95秒;更不用说我的编译器不是那么聪明(它设法只在给参数的常量值时优化它) 。 – Rookie 2012-03-09 16:53:30

回答

9

通过将&放入参数中,您正在为程序添加更多代码。如果没有&,顺序是:

push values 
call Function 
pop values <- usually an update to stack pointer 

和功能:

return sp[arg1] | sp[arg2] | etc <- value read direct from stack. 

添加 '&' 做到这一点:

push address of value1 
push address of value2 
etc 
call Function 
pop values <- usually an update to stack pointer 

和功能:

return_value = 0; 
address = sp[arg1] 
or return_value, [address] 
address = sp[arg2] 
or return_value, [address] 
etc 
return return_value 

所以,你可以看到,&增加了很多。那么为什么要使用它?如果你有一个非常大的对象,传递一个指针比将对象复制到堆栈更合适。

+3

我还应该补充一点,以上是一般性描述。优化器可能会将值放入寄存器而不是堆栈中。 IA64编译器也可能将参数放入寄存器中。 – Skizz 2012-03-09 17:12:05

+0

加1用于提及寄存器。 – 2012-03-09 19:45:05

7

此结果严重依赖于系统。它表明在您的特定系统上复制参考值(最有可能实现为指针)的成本高于复制整数值的成本。这种差异的最可能原因是您的整数需要32位来表示,而您的指针/参考表示需要64位。 编辑这是更不用说访问您的整数的成本:获得它们的值需要额外的间接性。由于您只传递两个项目,因此缓存的使用很大程度上隐藏了额外的成本,但成本就在那里。

你是绝对正确较大的类型,虽然:经过参考,比方说,一个大structvector<...>仍然只需要64位(或不管它的大小为您的系统上),无论你有多少项目结构有,或有多少项目你的vector<...>持有。结构越大,通过价值传递它的成本就越高,因此通过将其作为参考而实现的节省。

+3

即使指针只需要32位,访问实际的int值也需要一个间接寻址,这可能会导致差异。 – 2012-03-09 16:56:09

+2

即使复制“int”比复制地址更昂贵,但参考版本还涉及间接内存读取操作,其成本可能与复制“int”的操作相同。 – 2012-03-09 16:57:43

+1

@ R.MartinhoFernandes你是对的,这是间接的代价。 OP中的测试的结构可以隐藏这个代价,因为他只会传递两个变量的地址而不是十个,所以缓存会提供八个间接访问,但是您的答案是正确的,但代价仍然是那里。 – dasblinkenlight 2012-03-09 17:01:54

1

传递地址而不是值会导致地址转义(在您最喜欢的编译器教科书中查找转义分析或点到分析),使优化变得更加困难。

是的,诸如内联和链接时间优化之类的东西可以缓解这些问题。

相关问题