2017-03-21 64 views
1

當前數據結構

我有一個代碼,其中的數據結構分別由A1A2兩個向量表示。編譯器能夠內聯這種方法嗎?

vector<A1> v1; 
vector<A2> v2; 

我的代碼的慢部分(總運行時間的約80%)由在遍歷這些載體和上的v2元件v1funA2元素應用該方法funA1

double result = 0; 
for (int i = 0 ; i < v1.size() ; i++) 
{ 
    results *= v1[i].funA1(); 
} 
for (int i = 0 ; i < v2.size() ; i++) 
{ 
    results *= v2[i].funA2(); 
} 

重塑數據結構

雖然數據結構使用這兩個向量,直覺寧願使用,其混合的數據類型A1A2的單個載體。使用兩種不同的載體會在代碼的其他地方帶來可讀性和維護的損失。

我想我可以將它們合併成一個單獨的向量。這個想法是使A1A2兄弟類別的母類A和使用vector<A> v作爲單個向量。我會在類A定義虛擬fun並覆蓋其在這兩個A1A2這樣我就可以做

double result = 0; 
for (int i = 0 ; i < v.size() ; i++) 
{ 
    results *= v[i].fun(); 
} 

問題

在第一種情況下,該方法funA1funA2可以通過內聯編譯器(實際上我自己將它們內聯,因爲它們是非常簡單的函數)。

在第二種情況下,恐怕內聯是不可能的。它是否正確?

編譯器是否管理內聯方法fun

當然,性能的損失可能可以忽略不計,我應該測試它,但我想知道在嘗試進行所有修改之前是否看起來先驗值得。

+2

如果您擔心可讀性,那麼使用lambda表達式可能會比使用['std :: accumulate'](http://en.cppreference.com/w/cpp/algorithm/accumulate)更好的選擇你的循環? –

+0

請參閱http://stackoverflow.com/a/18432062/2630032 –

+1

您將不得不使用'vector v'。如果你使用'vector v',你有對象切片。 – alain

回答

3

答案是肯定的「也許」。判斷你的編譯器是否確實內聯了調用的唯一方法是編譯它,然後查看彙編列表。這一切都取決於fun的複雜性(其中「複雜度」是編譯器特定的度量標準)。個人而言,除非這是您的應用程序中最具時間要求的部分,否則我不會擔心。函數調用並不昂貴。與往常一樣,爲了清晰和可讀性編寫代碼,然後進行優化。

+1

我同意:分析是獲得洞察力的最佳方式,因爲您的計劃實際上花費了大部分時間(因此您應該集中精力)。 –

-2

編譯器將在Class中內聯簡單函數。例如:一個函數只有返回。所以對於你的問題,我認爲它不。

1

你提出讓A::fun虛擬的,並且具有兩個覆蓋A1::funA2::fun,有一個電話,然後期望編譯器內聯A1::funA2::fun在一個電話?

這很樂觀。不是不可能的,但。

0

從計算速度的角度來看,最好使用單獨的向量。內聯虛擬功能需要虛擬化,雖然編譯器經常這樣做,但很難提供任何保證。除此之外,還有緩存(指令和數據),預取器,分支預測器 - 所有這些都可以受益於均勻遍歷。

如果您絕對需要合併這些向量,您可以嘗試將一個追加到另一個,以便一種類型的對象會聚集在一起。也許你甚至可以對大型矢量的兩個部分進行兩次單獨的遍歷,並且避免了virtaul調用。

在任何情況下,您最好的選擇就是描述您所能做的所有事情,並確定性能損失是否可以接受(或者說明顯)。

而且作爲@Someprogrammerdude提到的,看着你的代碼:)

1

簡短的回答是「不」的時候std::accumulate想到的。您需要使用不同類型的向量實例來對付編譯器能夠內聯虛函數調用。

假設A1A2A衍生的A1A2實例不能安全地存儲到std::vector<A>。這樣做的結果將是對象切片(例如,僅將每個對象的A部分複製到std::vector<A>中)。如果A是一個抽象類(即具有任何純虛函數),則這樣的事情將不會編譯。如果A不是抽象的,則std::vector<A>中的所有對象的靜態類型爲A - 因此調用v[i].fun()將爲每個元素調用A::fun()。所以A1::fun()A2::fun()將永遠不會被調用。

如果您將對象的地址存儲在std::vector<A *>中,則v[i]->fun()將根據對象的實際類型調用虛函數。但是,編譯器不能內聯,因爲要調用的函數是在運行時根據向量中每個對象的實際類型確定的(即每個對象的類型對編譯器來說是未知的)。類似的評論,如果你使用std::vector<std::unique_ptr<A>>

注:有一個std::vector<A *>std::vector<std::unique_ptr<A>>存儲指向多態類A的其他問題,如需要A有一個虛析構函數,在對象的生命週期進行正確的管理,等等。如果你將使用這種方法,你需要考慮這些事情 - 否則結果將是未定義的行爲。

如果你想幫助優化代碼的性能,您將需要提供更多的信息(例如,你如何具有一定輪廓信息,什麼類型的AA1A2是,什麼功能都做,等等) 。

+0

我更期待一個「不」,而不是「可能」,所以我upvote!但我當然注意到迄今爲止在答案中存在矛盾。我讚賞額外的解釋。謝謝 –

相關問題