2010-08-22 72 views
2

內聯不同類型的功能會帶來哪些好處,以及當在他們周圍開發時需要注意哪些問題?如果你能給出任何對我來說很有用的指針,我對於探查器並不是很有用,但它有許多不同的算法應用程序,它似乎將速度提高了8倍以上。在C++函數中使用內聯優化的注意事項是什麼?

回答

5

內聯函數經常被濫用,其後果是顯着的。內聯指示編譯器可以考慮內聯擴展的功能。如果編譯器選擇內聯一個函數,那麼函數不會被調用,而是被複制到位。性能增益避免了函數調用,堆棧幀操作和函數返回。收益可以相當大。

請注意,他們可以增加程序大小。他們可以通過減少調用者的參考位置來增加執行時間。當大小增加時,調用者的內部循環可能不再適合處理器緩存,導致不必要的緩存未命中並導致性能下降。內聯函數還會增加構建時間 - 如果內聯函數發生變化,則必須重新編譯世界。一些指導原則:

  • 避免內聯函數,直到分析表明哪些函數可以從內聯獲益。
  • 考慮在使用和不使用自動內聯進行概要分析之後,使用編譯器的選項進行自動內聯。
  • 只有函數調用開銷相對於函數代碼很大的內聯函數。換句話說,內聯調用其他(可能內聯)函數的大函數或函數並不是一個好主意。
+0

實際上,我真的很喜歡這些觀點,感謝分析器信息(我仍然不好) – John 2010-08-22 02:16:15

+0

實際上,正如你所說,這只是一個提示,最近編譯器似乎也是這樣認爲的。哪個好:) – peterchen 2010-08-23 15:51:31

+0

最後一點只有在多次調用一個大函數時纔有效。對於整個程序中的單個調用,它也可以內聯。當然,這樣做對性能沒有多大的好處。 – Joey 2013-03-27 08:30:22

3

最重要的指針是你應該在幾乎所有的情況下讓編譯器做它的事情,而不用擔心它。

即使您不聲明inline,但編譯器可以自由執行函數的內聯擴展,即使您聲明它爲inline,也可以免費執行內聯擴展。這完全取決於編譯器,這是可以的,因爲在大多數情況下,它比你在內聯擴展函數時要好得多。

+0

本來希望這個陳述「它比我和你做得更好」,儘管我知道你的意思是 – Chubsdad 2010-08-22 02:10:26

+0

@chubsdad:代名詞「你」可以表示「任何人」或者某些未指定的「某人」。它不一定會挑選OP或某些可能閱讀此答案的人羣。這是這個詞的常用用法。 – 2010-08-22 02:16:38

+0

哦。雖然全局變量在程序中不是很好,但走向全球是很好的! – Chubsdad 2010-08-22 02:29:27

0

內聯函數的主要好處是可以消除調用開銷並允許編譯器跨越調用邊界進行優化。通常,給予優化器的自由度越高,程序執行的效率就越高。

缺點是該功能不再存在。一個調試器不能告訴你它在裏面,沒有外部代碼可以調用它。您也不能在運行時替換它的定義,因爲函數體存在於許多不同的位置。

此外,您的二進制文件的大小增加。

通常,如果沒有外部呼叫者,則應聲明函數static,而不是將其標記爲inline。如果您確定沒有負面影響,請僅讓函數內聯。

2

編譯器比程序員做內嵌更好的原因之一是因爲成本/收益折衷實際上是在機器抽象的最低級別上決定的:有多少彙編指令構成了你想要內聯的函數。考慮典型非分支彙編指令的執行時間與函數調用之間的比率。這個比率對於機器代碼生成器是可預測的,所以這就是編譯器可以使用這些信息來引導內聯的原因。

高級編譯器經常試圖處理內聯的另一個機會:當函數B只從函數A調用並且從不從其他地方調用時。由於性能原因(假設A和B不是小函數),這種內聯並未完成,但通過減少需要生成的「函數」的總數來減少鏈接時間非常有用。

新增例子

,其中編譯器執行大規模內聯(與塊狀加速)的一個例子是在STL容器的彙編。 STL容器類被寫爲高度通用的,並且作爲回報,每個「功能」僅執行一小部分操作。當內聯被禁用時,例如在調試模式下編譯時,STL容器的速度顯着下降。

第二個例子是被調用函數包含某些指令,要求棧在調用者和被調用者之間不受干擾。 SIMD指令使用內在函數時會發生這種情況。幸運的是,編譯器足夠聰明,可以自動內聯這些被調用函數,因爲他們可以檢查是否發出了SIMD彙編指令並將它們內聯以確保堆棧未受干擾。

底線

除非您熟悉低水平分析和善於assembly programming/optimization,最好是讓編譯器做的工作。 STL是一種特殊情況,即使在調試模式下啓用內聯(使用開關)也是有意義的。

0

函數調用開銷很小。內聯函數的一個更重要的優點是可以直接使用「通過引用」變量,而不需要額外的指針間接級別。如果參數傳遞給簡單變量或字段,那麼大量使用通過引用傳遞的參數的函數可能會大大受益。