2010-04-11 144 views
0

什麼是更快和/或通常更好?矢量[] vs複製

vector<myType> myVec; 
int i; 
myType current; 

for(i = 0; i < 1000000; i ++) 
{ 
current = myVec[ i ]; 
doSomethingWith(current); 
doAlotMoreWith(current); 
messAroundWith(current); 
checkSomeValuesOf(current); 
} 

vector<myType> myVec; 
int i; 

for(i = 0; i < 1000000; i ++) 
{ 
doSomethingWith(myVec[ i ]); 
doAlotMoreWith(myVec[ i ]); 
messAroundWith(myVec[ i ]); 
checkSomeValuesOf(myVec[ i ]); 
} 

目前我使用的第一個解決方案。每秒鐘真的有數百萬次的調用,每一次比較/移動都會帶來性能問題。

+14

爲什麼你在這裏問人們哪裏的速度更快,而不是在十分鐘內寫一個測試工具,以便給你一個明確的答案? – 2010-04-11 09:46:40

+3

當人們問布爾問題「哪一個更快」,而不是「多快多少」(就複雜度,CPU週期或時間而言)時,我總是感到驚訝 – 2010-04-11 10:09:07

+0

@Pavel:或者「在什麼情況下更快」 – jalf 2010-04-11 10:18:21

回答

0

取決於您的類型的賦值運算符。我希望通過參考這些函數來傳遞信息?但是對於所有性能問題,如果它對您很重要,請自己測試您的具體情況。

0

在格式方面,我建議以下(聲明在初始化點,使用常量的myType &):

 
vector myVec; 
for(int i = 0; i < 1000000; i++){ 
const myType& current = myVec[i]; 
doSomethingWith(current); 
doAlotMoreWith(current); 
messAroundWith(current); 
checkSomeValuesOf(current); 
} 

然而,在你原來的問題方面,使用名爲current是一個臨時變量至少與每次使用myVec[i]一樣快。不過,有可能優化編譯器會刪除myVec的冗餘查找(即使用賦值給臨時解決方案)......一般情況下,如果您重複調用一個聲明爲「const」的成員函數,而不使用任何非const成員函數,編譯器可以自由創建一個臨時對象並僅執行一次調用,將結果保存到本地臨時對象中。

11

第一個版本可能是不必要的昂貴,因爲它依賴於創建向量中對象的副本。除非myType是一些非常小且簡單的對象,如int,存儲參考可能是一個更好的主意。還應當申報當你需要它,並沒有更早,限制走樣的問題是威力否則會導致編譯器發出代碼效率不高:

創建副本的
vector<myType> myVec; 
for(int i = 0; i < 1000000; i ++) 
{ 
myType& current = myVec[ i ]; 
doSomethingWith(current); 
doAlotMoreWith(current); 
messAroundWith(current); 
checkSomeValuesOf(current); 
} 

一個優點,而不是使用引用是因爲它可能會導致編譯器將對象加載到寄存器中,而不是在每次訪問時從內存中讀取它。所以這兩個版本都值得嘗試。

任何當然,副本參考建議也適用於您的每個函數。他們是否通過價值或參考來進行論證?根據他們用它做什麼,以及如何定義myType,可能會比另一個更快。

第二個版本是有缺陷的,因爲它(除非編譯器能夠優化它)需要在每個時間內在內存中查找對象。根據您的STL實現,由於operator[]上的邊界檢查,可能還會有一些開銷。

創建臨時第一個,然後傳遞給您的每個函數是正確的路要走。問題在於是否該臨時應值類型(myType),或引用類型(myType&/const myType&)的

另一種選擇的是可以值得探討是把在其自身的單獨的循環中的每個函數調用。這在某些方面會傷害數據本地化,但如果某些功能使用大量本地數據,它可能會表現更好。它也可以在指令緩存中更好地發揮作用。

但實際上,性能非常複雜。高速緩存,亂序執行,myType的確切語義(特別是其拷貝構造函數和大小)以及編譯器執行的優化量都不爲我們所知。所以我們不能給你一個可靠的答案。

猜猜誰可以:你的編譯器。寫測試。試試兩個。計時結果。選擇更快的一個。

+0

bruno問:「有誰能向我解釋爲什麼在循環中聲明變量比在外部聲明更好。」 – Thomas 2010-04-11 10:43:36

1

除了避免多次訪問相同的索引並使用引用以避免複製之外,您可以在函數中使用快速調用調用約定。它指示編譯器在可能的情況下傳遞寄存器中的參數,而不是推送到堆棧。

但是,快速調用不是標準化的,所以它是供應商特定的。