2007年5月31日 星期四

[轉]likely,unlikely巨集與GCC內建函數__builtin_expect()

來源:http://blog.csdn.net/mopyman/archive/2006/02/09/595302.aspx

最近在讀linux 2.6 内核,雖然以前已經看了很多相關的知識,<>也看了2,3遍,但讀2.6内核仍然感到很吃力。面對2.6如此龐大的内核,信心真的不是很足,而且好像也没有很好的、有幫助的論壇來一起探討,哎!現在正在邊看<<情景分析>>,邊看最新的内核,自<<情景分析>>出版以來,内核已經有了很多的變化,好難讀啊!如果這様讀下去算不算“皓首窮經”呢,不得而知了!
言歸正傳
在讀linux/kernel/fork.c的時候遇到了unlikely宏定義,一路追踪,最後找到了GCC内建函數__builtin_expect(),查閲GCC手册,發現其定義如下:
long __builtin_expect (long exp, long c) [Built-in Function]
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
value of c must be a compile-time constant. The semantics of the built-in are that it
is expected that exp == c. For example:
if (__builtin_expect (x, 0))
foo ();
would indicate 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))
error ();
when testing pointer or floating-point values.
大致是説,由于大部分程序員在分支預測方面做得很糟糕,所以GCC提供了這個内建函數來幫助程序員處理分支預測,優化程序。其第一個參數exp為一個整型表達式,這個内建函數的返回值也是這個exp,而c為一個編譯期常量,這個函數的語義是:你期望exp表達式的值等于常量c,從而GCC為你優化程序,將符合這個條件的分支放在合適的地方。
因為這個程序只提供了整型表達式,所以如果你要優化其他類型的表達式,可以采用指針的形式。

unlikely的定義如下:
#define unlikely(x) __builtin_expect(!!(x), 0)
也就是説我們期望表達式x的值為0,從而如果我們用
…….
if(unlikely(x)){
bar();
}
來測試條件的話,我們就不期望bar()函數執行,所以該宏的名字用unlikely也就是不太可能來表示。
likely宏與次類似.

説到底__builtin_expect函數就是為了優化可能性大的分支程序。

沒有留言: