likelyとunlikely


likelyは条件が通常は真で、unlikelyは条件が通常は偽であるケースで、if文のパフォーマンス向上のために使用します。これらのマクロは、__builtin_expectで実装されgccマターとなります。
# define likely(x)      __builtin_expect(!!(x), 1)
# define unlikely(x)    __builtin_expect(!!(x), 0)
__builtin_expectは第1引数が第二引数1(真)なら、else処理はjmpとし、第1引数が0(偽)なら、then処理がjmpする様に展開されます。

次実行コードのインストラクションポインタIPをインクリメントするのでなく、jmpは次実行コードをキャッシュメモリから取得し、それをipに設定する負荷のかかる仕組みが必要と、CPUマターであるにしても想像できます。
void    likely(int a)
{
   if (__builtin_expect(!!(a == 2), 1)) {
       printf("%d\n", a);
   }
}

void    unlikely(int a)
{
   if (__builtin_expect(!!(a == 2), 0)) {
       printf("%d\n", a);
   }
}

likely:
.LFB13:
       .cfi_startproc
       subl    $28, %esp
       .cfi_def_cfa_offset 32
       cmpl    $2, 32(%esp)
       jne     .L5                <- elseはjmp .L5
       movl    $2, 4(%esp)
       movl    $.LC0, (%esp)
       call    printf
.L5:
       addl    $28, %esp
       .cfi_def_cfa_offset 4
       ret

unlikely:
.LFB14:
       .cfi_startproc
       subl    $28, %esp
       .cfi_def_cfa_offset 32
       cmpl    $2, 32(%esp)
       je      .L9               <- thenはjmp .L9
.L7:
       addl    $28, %esp
       .cfi_remember_state
       .cfi_def_cfa_offset 4
       ret
.L9:
       .cfi_restore_state
       movl    $2, 4(%esp)
       movl    $.LC0, (%esp)
       call    printf
       jmp     .L7
***追記
__builtin_expect(!!(x), 1)で、!!(x)とするのは、ポインタとする変数がNULLかそうでないか等のケースを想定しての実装です。なお、(a == 2)等の真偽を問うケースでは、!!は無視されます。

gcc依存と思いますが、私の環境では、最適化オプションO2以降でないと__builtin_expectが有効となりませんでした。

カーネル3ではgccの変更にともない、カーネルオプションにより、__builtin_expect以外による展開がされるようになっています。

最終更新 2015/08/30 12:48:01 - north
(2010/01/10 05:13:20 作成)


検索

アクセス数
3585543
最近のコメント
コアダンプファイル - sakaia
list_head構造体 - yocto_no_yomikata
勧告ロックと強制ロック - wataash
LKMからのファイル出力 - 重松 宏昌
kprobe - ななし
ksetの実装 - スーパーコピー
カーネルスレッドとは - ノース
カーネルスレッドとは - nbyst
asmlinkageってなに? - ノース
asmlinkageってなに? - よろしく
Adsense
広告情報が設定されていません。