Intelによると、分岐の削除は、タイトなループで使用する C コードを最適化する最も効果的な方法の 1 つです。ただし、リンクされたページの例では、ループのアンロールと不変ブランチのループ外への移動のみがカバーされています。
最適化のための分岐削除の追加のさまざまな (前後の) 例はありますか?
Intelによると、分岐の削除は、タイトなループで使用する C コードを最適化する最も効果的な方法の 1 つです。ただし、リンクされたページの例では、ループのアンロールと不変ブランチのループ外への移動のみがカバーされています。
最適化のための分岐削除の追加のさまざまな (前後の) 例はありますか?
分岐を排除することが目標である場合は、数学または移植性のないソリューションを検討することをお勧めします。
次の例を検討してください。
if (a < b)
y = C;
else
y = D;
これは次のように書き直すことができます...
x = -(a < b); /* x = -1 if a < b, x = 0 if a >= b */
x &= (C - D); /* x = C - D if a < b, x = 0 if a >= b */
x += D; /* x = C if a < b, x = D if a >= b */
上記が機能するためには、プロセッサが分岐命令を生成せずにa < bを評価できると想定しています。また、可読性も低下します。
その価値はありますか?時々、しかし通常はそうではありません。分岐または分岐予測の誤りが、いずれかの分岐に偏っていないために多大なコストがかかっている場合は、それだけの価値があるかもしれません。しかし、おそらくそうではありません。いつものプロフィールです。
それがあなたの目標である場合、少しの数学/算術は分岐を排除するのに大いに役立ちます。これまで何度も言われてきましたが、できるからといって、そうしなければならないわけではありません。
お役に立てれば。
これはチュートリアルで、さらにいくつかの例があります。ここにあるもの以外に、switch ステートメントやセンチネル値の使用が考えられます。また、ifステートメントを回避するためのよりあいまいな方法のこの他のチュートリアルも見つけました。
最適化に取り組んでいる場合は、callgrind/kcachegrind などのプロファイリング ツールを使用して、最も時間を費やすコードの部分に注目することを強くお勧めします。特定の方法でコードを最適化すると、コードが難読化されたり、保守が難しくなったりする可能性があります。私の経験では、最適化のために最適化することは本当に悪い考えです。
プロファイラーを使用した後、より優れたデータ構造を使用するか、特定のアルゴリズムを回避することが、分岐の削除ではなく、C コードを最適化する最も効果的な方法であることに気付く場合があります。
説教するつもりはありません。ブランチを削除することがコードを最適化する最善の方法であるという前提に同意しないだけです。これが最新のプロセッサに非常に役立つことは理解していますが、最適化の取り組みの最初のステップは、コードの遅い部分を見つけてそこから進むことです。
最適なブロックの順序付けは、かなりの違いを生む可能性があり、コードのすべての部分で発生します。また、インテルが示した例を「非現実的」であるとして簡単に却下することはできません。