1. 程式人生 > 實用技巧 >轉載 __builtin_expect — 分支預測優化

轉載 __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

轉自:https://www.cnblogs.com/LubinLew/p/GCC-__builtin_expect.html