なぜ1つのビットカウント方法を別の方法よりも選択するのですか?まあそれは本当にあなたのマシンとあなたが解決しようとしている問題に依存します。以下に示すすべての命令数は、基本的なRISCプロセッサのものであり、x86のようなより複雑な獣にうまく変換されない可能性があることに注意してください。
引用したHAKMEMアルゴリズムは13命令で実行されますが、モジュラス演算子のために非常に高速になる可能性は低くなります。目を見張ると、プロセッサがそれを利用できる場合に役立つ、かなり優れた命令レベルの並列性があるように見えます。
Bo Perssonが提示したアルゴリズムは非常に高速です(2 + 5*pop(x)
命令)が、単語がまばらに入力されている場合に限ります。また、密集した単語で機能するように変更することもできます。また、ブランチが含まれており、重要な命令レベルの並列性はありません。
編集:テーブルルックアップメソッドも非常に高速ですが、メモリアクセスを行います。テーブル全体がL1キャッシュにある場合、それはおそらく最速のアルゴリズムの1つです。テーブルがキャッシュにない場合、それはほぼ確実に最も遅いものの1つです。
以下のアルゴリズムは、HAKMEMアルゴリズムの1つのバリエーションであり、ハッカーのたのしみの本に示されています(この種のものが好きな場合は、この本を強くお勧めします)。19命令で実行され、ブランチフリーです。また、除算は使用しませんが、乗算はあります。また、同じマスクを可能な限り再利用することで、レジスターを使用する方法も非常に経済的です。ここでは、私が見ることができる重要な命令レベルの並列性はまだありません。
int pop(unsigned x) {
unsigned n;
n = (x >> 1) & 0x77777777;
x = x - n;
n = (n >> 1) & 0x77777777;
x = x - n;
n = (n >> 1) & 0x77777777;
x = x - n;
x = (x + (x >> 4)) & 0x0F0F0F0F;
x = x * 0x01010101;
return x >> 24;
}
Hacker's Delightの本には、9-8-7ビット幅のフィールドまたは浮動小数点演算子を使用するためのさらに特殊なアルゴリズムもいくつか紹介されています。上で提示した分析のほとんどは、その本からも部分的に取得されていることに注意してください。
実際には、トラックにはたくさんの方法があり、特定の状況でどれが最適に機能するかを確認する唯一の方法は、測定して比較することです。私はこれがかなり定型的な答えであることを理解していますが、代わりにあなたのプロセッサとコンパイラを裏返しに知ることです。