GCCコンパイラは、可能性の高いマクロと可能性の低いマクロを定義するために使用される__builtin_expectステートメントをサポートします。
例えば。
#define likely(expr) (__builtin_expect(!!(expr), 1))
#define unlikely(expr) (__builtin_expect(!!(expr), 0))
Microsoft Visual Cコンパイラと同等のステートメント、または同等のものはありますか?
GCCコンパイラは、可能性の高いマクロと可能性の低いマクロを定義するために使用される__builtin_expectステートメントをサポートします。
例えば。
#define likely(expr) (__builtin_expect(!!(expr), 1))
#define unlikely(expr) (__builtin_expect(!!(expr), 0))
Microsoft Visual Cコンパイラと同等のステートメント、または同等のものはありますか?
http://www.akkadia.org/drepper/cpumemory.pdf(57ページ)によると、CPUが動的に正しく予測する場合でも、静的分岐予測を使用することは理にかなっています。その理由は、静的予測が正しく行われた場合、L1iキャッシュがさらに効率的に使用されるためです。
そのようなものは何もありません。__assume()がありますが、使用しないでください。これは別の種類のオプティマイザ ディレクティブです。
__GNUC__
実際、gnu ビルトインがマクロでラップされている理由は、定義されていない場合に自動的に削除できるようにするためです。これらのマクロについては、最低限必要なものは何もありません。実行時間の違いに気付かないことは間違いありません。
*likely
非 GNUでは (null out) を取り除くだけです。あなたはそれを見逃すことはありません。
ブランチとループの再編成によるインテルの予測ミス防止ドキュメント:
これらのルールを利用するコードを効果的に作成するには、if-else ステートメントまたは switch ステートメントを作成するときに、最も一般的なケースを最初に確認し、最も一般的でないケースまで段階的に作業を進めます。
残念ながら、次のようなものを書くことはできません
#define if_unlikely(cond) if (!(cond)); else
VS10 の MSVC オプティマイザはそのような「ヒント」を無視するためです。
私は自分のコードで最初にエラーを処理することを好むので、効率の悪いコードを書いているようです。幸いなことに、CPU がブランチに 2 回遭遇すると、静的ヒントの代わりにその統計が使用されます。
__assumeも同様のはずです。
ただし、これを本当にうまくやりたい場合は、静的なヒントではなく、プロファイルに基づく最適化を使用する必要があります。
質問が古いため、MSVC に[[likely]]
/がない、または影響がないという回答は時代遅れです。[[unlikely]]
最新の MSVC は[[likely]]
/ [[unlikely]]
in/std:c++20
および/std:c++latest
モードをサポートしています。
違いを示すGodbolt のコンパイラ エクスプローラーのデモを参照してください。
上記のリンクからわかるように、x86/x64 の forif-else
ステートメントに対する目に見える影響の 1 つは、条件付きジャンプ フォワードがありそうもない分岐に対して行われることです。C++20 およびサポートする VS バージョンより前は、必要に応じて条件を否定して、可能性の高い分岐をif
部分に配置し、可能性の低い分岐を部分に配置することで、同じことが達成できました。else
このような最適化の効果は最小限であることに注意してください。タイトなループで頻繁に呼び出されるコードの場合、動的分岐予測はとにかく正しいことを行います。