__builtin_expect — 分支預測優化


 1.引言

在很多源碼如Linux內核、Glib等,我們都能看到likely()和unlikely()這兩個宏,通常這兩個宏定義是下面這樣的形式。

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

可以看出這2個宏都是使用函數 __builtin_expect()實現的, __builtin_expect()函數是GCC的一個內建函數(build-in function).

 

2. 函數聲明

函數__builtin_expect()是GCC v2.96版本引入的, 其聲明如下:
long __builtin_expect(long exp, long c);

2.1. 功能描述

由於大部分程序員在分支預測方面做得很糟糕,所以GCC 提供了這個內建函數來幫助程序員處理分支預測.

你期望 exp 表達式的值等於常量 c, c 的值, 如果 c 的值為0(即期望的函數返回值), 那么 執行 if 分支的的可能性小, 否則執行 else 分支的可能性小(函數的返回值等於第一個參數 exp).

GCC在編譯過程中,會將可能性更大的代碼緊跟着前面的代碼,從而減少指令跳轉帶來的性能上的下降, 達到優化程序的目的.

通常,你也許會更喜歡使用 gcc 的一個參數 '-fprofile-arcs' 來收集程序運行的關於執行流程和分支走向的實際反饋信息,但是對於很多程序來說,數據是很難收集的。

2.2. 參數詳解

  ① exp

    exp 為一個整型表達式, 例如: (ptr != NULL)

   ② c

     c 必須是一個編譯期常量, 不能使用變量

2.3. 返回值

  返回值等於 第一個參數 exp

2.4. 使用方法

與關鍵字if一起使用.首先要明確一點就是 if (value) 等價於 if (__builtin_expert(value, x)), 與x的值無關.

例子如下:

例子1 : 期望 x == 0, 所以執行func()的可能性小

if (__builtin_expect(x, 0))
{
    func();
}
else
{
  //do someting
}

例子2 : 期望 ptr !=NULL這個條件成立(1), 所以執行func()的可能性小

if (__builtin_expect(ptr != NULL, 1))
{  
  //do something
}
else
{
  func();
} 

例子3 : 引言中的likely()和unlikely()宏

  首先,看第一個參數!!(x), 他的作用是把(x)轉變成"布爾值", 無論(x)的值是多少 !(x)得到的是true或false, !!(x)就得到了原值的"布爾值"

  使用 likely() ,執行 if 后面的語句 的機會更大,使用 unlikely(),執行 else 后面的語句的機會更大。

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

int main(char *argv[], int argc)
{
   int a;

   /* Get the value from somewhere GCC can't optimize */
   a = atoi (argv[1]);

   if (unlikely (a == 2))
  { a
++;
}
else   {
   a
--;   } printf ("%d\n", a); return 0; }

  

 3. RATIONALE(原理)

if else 句型編譯后, 一個分支的匯編代碼緊隨前面的代碼,而另一個分支的匯編代碼需要使用JMP指令才能訪問到.

很明顯通過JMP訪問需要更多的時間, 在復雜的程序中,有很多的if else句型,又或者是一個有if else句型的庫函數,每秒鍾被調用幾萬次,

通常程序員在分支預測方面做得很糟糕, 編譯器又不能精准的預測每一個分支,這時JMP產生的時間浪費就會很大,

函數__builtin_expert()就是用來解決這個問題的.

具體從匯編角度來分析其原理的例子,大家可以參照http://kernelnewbies.org/FAQ/LikelyUnlikely,

其對應的中文翻譯版見http://velep.com/archives/795.html

 

-----------------------------------------------------------------------------------------------

參考文獻:

http://my.oschina.net/moooofly/blog/175019

http://bbs.csdn.net/topics/350111403

http://velep.com/archives/795.html

http://blog.csdn.net/linwhwylb/article/details/6084219

http://blog.csdn.net/sunnybeike/article/details/6802579

http://kernelnewbies.org/FAQ/LikelyUnlikely

http://gcc.gnu.org/onlinedocs/gcc/Other-Builtins.html


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM