Evaluate 是個萬用小刀,讓你可以輕鬆嘗試各種 gcc/llvm 的優化,不用再花漫漫長夜修改 Makefile。這裡我們教大家如何使用 evaluate 來輕鬆啟動 Link Time Optimization (LTO) 以及 Profiler Guided Optimization(PGO)。


啟動 LTO

啟動 LTO 蠻簡單的,只要注意兩件事就可以:

  1. 使用正確的 AR
  2. 對 gcc 下 -flto

gcc LTO 所產生的 object file,內含的不是傳統的 machine code 的 object file,而是 compiler IR,也因此 symbol 的擺放方式和之前不同。如果編譯過程當中會「自產自銷」static library,compiler 就必須要告訴 ar 要怎麼處理 object file 的 symbol。

compiler 透過 plugin 的方式,讓 ar 可以讀懂 LTO 的 object file。

設定 ar plugin 的方式也很簡單,就是在每次 ar 執行的時候多增加 --plugin 參數。gcc plugin 的位置通常會在 /usr/lib/gcc/[machine triple]/[version]/ 底下,以 ubuntu 14.04 的 gcc 4.8 的例子,lto plugin 放在

    /usr/lib/gcc/x86_64-linux-gnu/4.8/liblto_plugin.so

我們也可以讓 gcc 自己來告訴我們 plugin 在哪裡,可以這樣取得 LTO library 的位置

    $ gcc --print-file-name=liblto_plugin.so

所以只要將 ar 多增加 --plugin gcc --print-file-name=liblto_plugin.so 就可以了,用 evaluate 的話就使用以下指令:

    $ sudo evaluate -tool `which ar` -mark --plugin=$(gcc --print-file-name=liblto_plugin.so)

然後對 gcc 下 -flto

    $ sudo evaluate -tool `which gcc` -mark -flto

然後正常執行編譯,就會啟動 LTO 優化。


啟動 PGO

PGO 的原理是藉由執行一次,產生一些關於 if/else 執行頻率的資料,幫助編譯器做更好的 block reordering 相關的優化。

啟動 PGO 需要的步驟比較多,可以分為:
1. 編譯出能產生統計資料的程式
2. 執行一次,產生統計資料
3. 再編譯一次,利用統計資料來優化

PGO 需要兩次編譯,每次編譯的參數都不一樣。在第一次編譯的時候,要告訴編譯器統計資料預備要放在哪個資料夾,我們可以利用 evaluate 這樣做:

    $ mkdir ./pgo_data
    $ evaluate -tool `which gcc` -mark -fprofile-dir=$PWD/pgo_data -fprofile-generate=$PWD/pgo_data

然後進行一般的編譯,並且再執行一次,假設 project 使用的是 Makefile,產生的檔案叫做 hello_world

    $ make
    $ ./hello_world

如此一來就會在 ./pgo_data 底下產生許多的 gcda 檔。gcda 檔記錄著這次執行過程的統計資料。

利用統計資料來優化也很簡單,可以這樣操作 evaluate:

    $ evaluate -tool `which gcc` -mark -Ofast -flto -fprofile-dir=$PWD/pgo_data -fprofile-use=$PWD/pgo_data -Wno-error=coverage-mismatch -fprofile-correction

有些 program 在執行的時候不會用到全部的程式碼,所以會有些 object 檔沒有對應的 gcda file,另外也有些情況是統計資料過大,導致於數值成為 -1,這時候就可以利用 -fprofile-correction 來修正統計資料。另外 -Wno-error=coverage-mismatch 也可以避免因為統計資料缺如所造成的錯誤。

設定好 evaluate 之後就開始編譯,這樣子就能啟動 PGO,很簡單吧!