gcc/linux核心中likely、unlikely和__attribute__(section(""))屬性

來源:互聯網
上載者:User

標籤:

查看linux核心源碼,你會發現有很多if (likely(""))...及if (unlikely(""))...語句,這些語句其實是編譯器的一種最佳化方式,具體分析如下:

likely及unlikely是一個宏定義:

#define likely(x)  __builtin_expect(!!(x), 1)

#define unlikely(x)  __builtin_expect(!!(x), 0)

 

likely()的 意思是認為這個分支最有可能發生,如if (likely(x == 0)){...},這個語句表示x等於0最有可能發生,其實語意就相當於if (x == 0){...},只不過likely針

對程式指令運行做了最佳化,不去做一些無謂的指令跳轉;unlikely()意思相反,就是最不可能發生,注意if (unlikely(x == 0))還是相當於if (x==0)的邏輯。

 

如果需要更進一步瞭解likely()就必須要深入瞭解__bulitin_expect(!!(x), 1)函數。

— Built-in Function: long __builtin_expect (long exp, long c)    You may use __builtin_expect to provide the compiler with branch prediction information. In general, you should prefer to use actual profile feedback for this (-fprofile-arcs), as programmers are notoriously bad at predicting how their programs actually perform.
   However, there are applications in which this data is hard to collect. The return value is the value of exp, which should be an integral expression. The semantics of the built-in are that it is expected that exp == c. For example: if (__builtin_expect (x, 0)) foo (); indicates that we do not expect to call foo, since we expect x to be zero. Since you are limited to integral expressions for exp, you should use constructions such as if (__builtin_expect (ptr != NULL, 1)) foo (*ptr); when testing pointer or floating-point values.

文檔連結:https://gcc.gnu.org/onlinedocs/gcc/Other-Builtins.html#Other-Builtins

 

從gcc官方文檔來看,內建函數long __builtin_expect (long exp, long c)主要用於最佳化程式的分支預測,減少程式的指令跳轉,現代處理器一般都是流水線架構,

很多晶片級的最佳化是靠流水線預取完成的,所以我們的程式最佳化也是需要盡量減少跳轉。

 

文檔也提到了由於大部分程式員根本就不瞭解自己程式的運行情況,所以推薦我們在編譯時間加上-fprofile-arcs選項去評估我們的程式分支運行情況;-fprofile-arcs選

項是程式碼涵蓋範圍測試載入器gcov使用時需要增加的編譯選項,gcov能夠去統計及分析我們的程式的分支運行情況,關於gcov的使用這裡不做介紹,只需要知道gcov是

一個測試統計工具,配合-fprofile-arcs工具使用,__builtin_expect 根據gcov的分析結果來做實際的分支預測最佳化。

 

這裡可以大家還會有疑問,為什麼#define likely(x)  __builtin_expect(!!(x), 1)中要使用!!(x),這其實是因為函數__builtin_expect (long exp, long c)期望是exp == c,這時的1相當於bool值true,所以exp需要是一個bool運算式,通過!!可以變成bool運算式而不改變原有函數,這樣才能夠正確的與1或0(bool值)做匹配判斷;試想如果沒有!!,即#define likely(x)  __builtin_expect((x), 1),那麼likely(10)原本是希望運算式是true,但是根據函數的處理邏輯10 != 1,那麼最佳化會以false的結果來最佳化,這樣就陰差陽錯了!!!

 

 

最後講述一下__attribute__(section(""))屬性,這個屬性比較好理解,就是為某個函數或變數指定section,比如:

int __attribute__(section(".test.data")) value = 0;

這樣的話變數value將會被放在.test.data段中;

void __attribute__((section(".test.text"))) func(void){}

這樣函數func會被放入.test.text段中。

 

查看section資訊可以通過如下命令:readelf -S xxx,可以查看可執行檔也可以是目標檔案.o,關於section這裡不過多介紹,只要大概知道一般我們的代碼都是放在.text段,全域變數一般放在.data段,我們通過__attribute__((""))定義的符號就放在我們特定的section裡面。

 

gcc/linux核心中likely、unlikely和__attribute__(section(""))屬性

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.