44

分岐予測のヒントを実行するポータブルな方法はありますか?次の例を考えてみましょう。

  if (unlikely_condition) {
    /* ..A.. */
  } else {
    /* ..B.. */
  }

これは行うことと何か違いがありますか?

  if (!unlikely_condition) {
    /* ..B.. */
  } else {
    /* ..A.. */
  }

または、コンパイラ固有のヒントを使用する唯一の方法ですか?(例:GCCの__builtin_expect)

コンパイラーifは、条件の順序に基づいて条件を異なる方法で処理しますか?

4

6 に答える 6

30

静的分岐予測を行うための標準的な方法は、if分岐せずに予測され(つまり、すべてのif句が実行されるのではなくelse)、ループと逆方向が実行さgotoれることです。したがって、else静的予測が重要であると予想される場合は、一般的なケースを入れないでください。取られていないループを回避するのはそれほど簡単ではありません。私は試したことがありませんが、else句を入れるとかなり移植性が高くなるはずです。

多くのコンパイラは何らかの形式のをサポートしていますが、他のコンパイラを保護するために、何らかの形で#pragma unrollそれを保護する必要があります。#if

分岐予測のヒントは、プログラムのフロー制御グラフを変換し、実行可能メモリに基本ブロックを配置する方法の完全な説明を理論的に表現できます。したがって、表現するものはさまざまであり、ほとんどの場合、移植性は高くありません。

GNUがのドキュメントで推奨しているように__builtin_expect、プロファイルに基づく最適化はヒントよりも優れており、労力も少なくて済みます。

于 2010-09-13T17:44:52.203 に答える
21

ほとんどの場合、次のコード

if (a)
{
   ...
}
else
{
    ...
}

実は

evaluate(A)

if (!A)
{
   jmp p1
}

... code A

   jmp p2

p1:

... code !A

p2:

Aが真の場合、「コードA」はすでにパイプラインにあることに注意してください。プロセッサは「jmpp2」コマンドを先に認識し、p2コードをパイプラインにロードします。

Aがfalseの場合、「コード!A」がパイプラインに含まれていない可能性があるため、速度が低下する可能性があります。

結論:

  1. Xが!Xよりも可能性が高い場合はIf(X)を実行します
  2. CPUがパイプラインを動的に最適化できるように、できるだけ早くAを評価するようにしてください。

evaluate(A)

do more stuff

if (A)
   ...
于 2010-09-13T17:55:01.320 に答える
7

最適化は本質的にコンパイラーのものであるため、それを支援するにはコンパイラー機能を使用する必要があります。言語自体は、最適化を気にしません(または義務付けません)。

したがって、コンパイラ固有の拡張機能なしで実行できる最善の方法は、コンパイラが助けなしに「正しいことを行う」ようにコードを編成することです。ただし、確認したい場合は、コンパイラ拡張機能を利用してください。(プリプロセッサの背後でそれらを抽象化してみて、コードの移植性を維持することができます。)

于 2010-09-13T17:38:14.990 に答える
7

C ++ 20は、ありそうな属性とありそうもない属性を提供します

そのステートメントを含む実行パスが、そのようなステートメントを含まない代替の実行パスよりも多かれ少なかれ可能性が高い場合に、コンパイラーが最適化できるようにします。

于 2020-01-30T18:37:37.463 に答える
1

自分のしていることに一貫しているだけです。使うのが好き

if (!(someExpression))

しかし、コンパイラはこれを同等に扱う必要があります。

于 2010-09-13T17:37:47.837 に答える
1

#ifdefカスタムマクロを介して特定のコンパイラをチェックし、これらを非表示にすることの何が問題になっていますか?#defineこれらの最適化ヒントをサポートするコンパイラがない場合は、プレーン式に拡張できます。私は最近、GCCが組み込み関数を介してサポートする明示的なキャッシュプリフェッチで同様のことを行いました。

于 2010-09-13T18:06:25.630 に答える