Preface
最近一直在鼓搗 Python3 的手動編譯,偶然發現這篇文章介紹 LTO 的文章蠻有趣的,網址在 https://johnysswlab.com/link-time-optimizations-new-way-to-do-compiler-optimizations/ 算是 compiler LTO 概念的入門文章,一開始先跟你說了 compiler 針對一個蠻小的 code snippet 可以做些什麼 optimization,像是 inlining
和 loop merging
,以下面這個簡單的程式來說:
1 | int find_min(const int* array, const int len) { |
- 第一個能做的就是 inlining, 基本上我們透過 inline,可以減少 function call overhead,也就是把 code body 直接展開擺在呼叫他的地方。
- 接下來是 loop merging,可以看到 find_min & find_max 的長相很像,我們可以把他們合成一個 loop, 這樣可以減少 cpu 的工作量還可以提升 data cache 的 utilization。
1 | void main() { |
但這些 optimization 都有前提就是,他們必須是要在同一個 compliation unit 下面,而 C & C++ 的 compliation unit 是一個一個 file,所以當 find_max & find_min 放在 find.c,而 main 放在 main.c 這些套路就無法被 apply。
Link Time Optimization
Link Time Optimization 是在 linking 後,去看看能不能將這些 optimization 用上,比較常被用上的 optimization 是 inlining & code locality improvements,inlining 前文就提到過了,透過 inlining 後,還可以去做其他的 optimization。
而一般來說,compiler 會嘗試去分析哪些 function 比較常被呼叫,哪些比較少被用,所以他們可以透過這個分析,將 function 擺近一點去改善 code locality,例如 function A 經常呼叫 function B,把他們放靠近一點,是可以有效改善 page faults。
而通常來說做了 LTO 後,程式應該會快一點點,binary size 也會小一點點,這對一些 performance sensitive 的程式算是蠻大的幫助。但缺點也很明顯,用了 LTO 後,整個 compilation 的時間會多蠻多的,也需要用到更多的記憶體,所以 LTO 也不是被很多專案使用。
How to enable LTO
原來 GCC 4.7 就開始支援 LTO 了,基本上只要加上參數 -flto
就可以使用。
Conclusion
作者在文末也做了一些實驗,基本上是可以看到他自己的程式 runtime 提升了 10%,但是整個編譯的時間也暴增,而拿來用在 ffmpeg 上面則是看不到什麼好處,所以對於不同的專案還是 case by case。
LTO & PGO 現在常常被提起,我是感覺大家應該要把這些放進自己的工具箱,如果真的遇到 performance sensitive 的程式,可以拿來重編看看有沒有辦法近一步改善效率。