1. ホーム
  2. linux

[解決済み] Linuxカーネルのprocess/unlikelyマクロはどのように動作し、どのような利点があるのでしょうか?

2022-03-23 08:45:17

質問

Linuxカーネルの一部を調べていたら、以下のような呼び出しを発見しました。

if (unlikely(fd < 0))
{
    /* Do something */
}

または

if (likely(!err))
{
    /* Do something */
}

その定義がわかりました。

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

最適化のためというのはわかるのですが、どのような効果があるのでしょうか?また、それを使うことでどの程度のパフォーマンスやサイズの低下が期待できるのでしょうか?また、少なくともボトルネックとなるコード(もちろんユーザースペース内)において、手間をかける(そしておそらく移植性を失う)だけの価値があるのでしょうか?

解決方法は?

ジャンプ命令の分岐予測を有利にするような命令を出すようにコンパイラに指示するのです。もし予測が正しければ、ジャンプ命令は基本的に自由であり、ゼロサイクルで実行されることになります。一方、予測が外れた場合、プロセッサのパイプラインをフラッシュする必要があり、数サイクルのコストがかかることになる。しかし、ほとんどの場合、予測は正しいので、性能面では有利になります。

このようなパフォーマンスの最適化はすべて、コードが本当にボトルネックになっているか、そしておそらくマイクロな性質から、タイトなループで実行されていることを確認するための広範なプロファイリングの後にのみ実行すべきです。一般的にLinuxの開発者はかなり経験豊富なので、そうしていると想像します。彼らはgccだけをターゲットにしているので、移植性についてはあまり気にしていませんし、生成させたいアセンブリについても非常に近い考えを持っています。