例:
if (almost_always_false_condition) {
// do something
}
99%の条件でfalseになることをコンパイラに提案する方法はありますか?条件の計算はチェックに約60サイクルかかり、コンパイル時にコンパイラ自体で計算することはできません。
(gcc 4.3)
例:
if (almost_always_false_condition) {
// do something
}
99%の条件でfalseになることをコンパイラに提案する方法はありますか?条件の計算はチェックに約60サイクルかかり、コンパイル時にコンパイラ自体で計算することはできません。
(gcc 4.3)
コードフローを調整するためのヒントとして、条件が特定の値を持つ可能性が高いことを GCC に提案したい場合は、次を使用する必要があります__builtin_expect( )
。
if (__builtin_expect(almost_always_false_condition,0)) {
// do something
}
ただし、条件の評価を回避する方法を見つけたいと思われますが、__builtin_expect( )
そうはなりません。条件をすばやく近似し、近似が真の場合にのみ完全なチェックを行う方法はありますか:
if (__builtin_expect(fastCheckThatIsTrueIfFullConditionIsTrue,0)) {
// most of the time, we don't even get to here, so you don't need
// to evaluate the condition
if (almostAlwaysFalseCondition) {
// do something
}
}
どのような状態か詳しく教えていただけますか?
1 回の実行で結果が異なる可能性がある場合は、ブール演算子の遅延評価を使用して条件を安価な部分と高価な部分に分割し、安価な部分を最初に実行できる場合があります。
if (a == 5 && somethingexpensive())
{
...
}
計算a == 5
は よりも安価であるためsomethingexpensive()
、ほとんどの場合、false
最初に実行する必要があります。これにより、somethingexpensive
句の評価が回避されます。
一方、結果がプログラムの実行に対して一定である場合は、計算結果を静的変数またはグローバル変数に格納することで最適化できます。
static int result = doevalfunctiononlyonce();
if (result)
{
....
}
if
このようにして、単純なメモリ ルックアップのコストを削減しました。
条件が別のプロシージャのアクションに応じてのみ変化する場合は、そのプロシージャからグローバルを更新できます。
int condition;
void appendToList(int a)
{
list.append(a);
if (list.somethingexpensive())
{
condition = true;
} else
{
condition = false;
}
}
void someotherfunction()
{
// if (list.somethingexpensive())
if (condition)
{
...
}
}
someotherfunction
これは、 が関数よりも頻繁に呼び出される場合に便利ですappendtolist
。
else
まず第一に、条項またはプログラムの他の場所で何サイクルが費やされますか?プロファイルを作成したり、スタックショットを撮ったりする場合、そのテストに少なくとも10%の時間を費やしていますか?そうでない場合は、おそらく最初に確認する必要があるより大きな問題があります。
次に、そのテストに10%を超える時間を費やしている場合は、50〜50の確率に近い決定ポイントを持つようにアルゴリズムを調整できるかどうかを確認する必要があります。50-50の決定ポイントは実行時に1ビットの情報を生成しますが、99-1の決定ポイントは約.07ビット*しか生成しません(つまり、あまり情報がないため、CPUサイクルの非効率的な使用です。 )この現象の例は、線形検索とバイナリ検索を比較する場合です。
*バイナリ決定ポイントがあり、結果の確率がa
とb
である場合、ビット単位の情報収量(エントロピー)はです-(a*log(a) + b*log(b))/log(2)
。
ドキュメントは、gcc がプロファイル駆動型の最適化を行う (またはできる) ことを示唆しています。これは私が gcc でやろうとしたことではないので、これ以上のアドバイスはできません。Google に問い合わせる価値はあるかもしれません。
私の意見では、この種の最適化を実行する最良の方法は、 オプション-fprofile-generate
と-fprofile-use
オプションを使用することです。これには、可能性が高いものとそうでないものに関する情報を収集するための代表的なユースケースのベースが必要ですが、テストはこの目的に使用できます。一方で、コードは見苦しく移植性のないディレクティブで装飾されていません。
これら 2 つのオプションの詳細については、https://gcc.gnu.org/onlinedocs/gcc-4.3.6/gcc/Optimize-Options.html#Optimize-Optionsを参照してください。