質問

512以上のバイトの大きなバッファーでポップカウントする最速の方法を探しています。必要なアライメントを保証でき、バッファサイズは常に2のパワーです。バッファーはブロック割り当てに対応するため、通常、ビットはすべて設定されていないか、設定されていないか、ほとんどがバッファの「左」を有利に設定します。時折穴。

私が検討したいくつかの解決策は次のとおりです。

私は最速のソリューションに興味があります。Core2以下に属する32ビットx86チップセットで動作する必要があります。 SSEとSIMDは非常に興味深いです。次のQuad Core CPUでテストします。

matt@stanley:~/anacrolix/public/stackoverflow$ cat /proc/cpuinfo 
processor       : 0
vendor_id       : GenuineIntel
cpu family      : 6
model           : 15
model name      : Intel(R) Core(TM)2 Quad CPU    Q6600  @ 2.40GHz
stepping        : 11
cpu MHz         : 1600.000
cache size      : 4096 KB
physical id     : 0
siblings        : 4
core id         : 0
cpu cores       : 4
apicid          : 0
initial apicid  : 0
fdiv_bug        : no
hlt_bug         : no
f00f_bug        : no
coma_bug        : no
fpu             : yes
fpu_exception   : yes
cpuid level     : 10
wp              : yes
flags           : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe nx lm constant_tsc arch_perfmon pebs bts aperfmperf pni dtes64 monitor ds_cpl vmx est tm2 ssse3 cx16 xtpr pdcm lahf_lm tpr_shadow vnmi flexpriority
bogomips        : 4800.21
clflush size    : 64
cache_alignment : 64
address sizes   : 36 bits physical, 48 bits virtual
power management:
役に立ちましたか?

解決 3

私が見つけた最高のc/アセンブリ関数の概要 人口数/ハミング重量 以下の大きなバッファーの。

最速のアセンブリ関数はです ssse3_popcount3, 、 説明された ここ. 。それが必要です SSSE3, 、Intel Core 2以降で利用可能、2011年に到着するAMDチップセット。 シムド 16バイトのチャンクでポップカウントするための指示と、一度に4ループの反復を展開します。

最速のC関数はです popcount_24words, 、 説明された ここ. 。ビットスライスアルゴリズムを使用します。注目すべきことがわかりました クラング 実際に適切なベクトルアセンブリ命令を生成する可能性があり、それにより印象的なパフォーマンスが向上しました。これはさておき、アルゴリズムはまだ非常に高速です。

他のヒント

の32ビットバージョンを参照してください AMDソフトウェア最適化ガイド, 、1つの実装について195ページ。これにより、x86のアセンブリコードが直接提供されます。

でバリアントを参照してください スタンフォードはハッキングをビットしますスタンフォードバージョンは私にとって最高のもののように見えます。 x86 ASMとしてコーディングするのは非常に簡単に見えます。

どちらもブランチの命令を使用していません。

これらは、64ビットバージョンに一般化できます。

32または64ビットバージョンを使用すると、SIMDバージョンを実行することを検討する場合があります。 SSE2は、一度に4つのダブルワードまたは2つのQuadwords(いずれの方法でも128ビット)を実行します。あなたがしたいのは、利用可能な2つまたは4つのレジスタのそれぞれに32または64ビットのポップカウントを実装することです。完了したら、XMMレジスタに2つまたは4セットのポップカウントになります。最後のステップは、これらのポップカウントを保存して追加して最終的な回答を得ることです。推測すると、2つの並列64ビットポップカウントではなく、4つの並列32ビットポップカウントを少しでもやることを期待しています。最後に値。

最適化された32ビットPOPCNTルーチンの1つをから実装することをお勧めします ハッカーの喜び, 、しかし、SSEベクターで4 x 32ビット整数要素に対してそれを行います。その後、128ビットあたり128ビットを処理できます。これにより、最適化された32ビットスカラールーチンと比較して約4倍のスループットが得られるはずです。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top