2012-03-09 216 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

傳遞地址而不是值會導致地址轉義(在您最喜歡的編譯器教科書中查找轉義分析或點到分析),使優化變得更加困難。

是的,諸如內聯和鏈接時間優化之類的東西可以緩解這些問題。

相關問題