これは、低レベルの最適化手法について説明し、著者が高価な分割を安価な比較に変換する例を示す素晴らしい記事です。 https://www.facebook.com/notes/facebook-engineering/three-optimization-tips-for-c/10151361643253920
クリックしたくない人のために、基本的に彼はこれを変換しました:
uint32_t digits10(uint64_t v) {
uint32_t result = 0;
do {
++result;
v /= 10;
} while (v);
return result;
}
これに:
uint32_t digits10(uint64_t v) {
uint32_t result = 1;
for (;;) {
if (v < 10) return result;
if (v < 100) return result + 1;
if (v < 1000) return result + 2;
if (v < 10000) return result + 3;
// Skip ahead by 4 orders of magnitude
v /= 10000U;
result += 4;
}
}
その結果、最大 6 倍のスピードアップが実現しました。
比較は非常に安価ですが、ブランチはパイプラインの停止を引き起こす可能性があるため、非常に高価であるといつも聞いています。分岐に関する一般的な通念のため、このようなアプローチを考えたことはありませんでした。
この場合、分岐がボトルネックにならないのはなぜですか? それぞれの比較の直後に戻るからですか? ここのコード サイズが小さいため、プロセッサが予測を誤る可能性があまりないためでしょうか。それがボトルネックになり、部門のコストを支配し始めるのはどのような場合ですか? 著者はこれについて決して話しません。
安価な比較と高価なブランチの間の明らかな競合を解決できる人はいますか? もちろん、最適化の黄金律は、常に測定しなければならないということです。ただし、コードを高速化するための新しいアプローチを考え出すときに、比較を賢く使用できるように、この問題についてある程度の直感を持っているとよいでしょう。
ありがとう!