1

解釈したい

std::vector<unsigned int> numbers

ビットベクトルとして、つまり の MSBnumbers[0]は 1 番目のビットであり、 の MSB はnumbers[1]33 番目のビットなどです。このベクトル内の 1 のすべてのシーケンスを検索し、対応する位置をデータ構造に格納したいと考えています。(また、ここでは単一のOneがシーケンスとして定義されています)

例: 値 15 と 112 が数値で格納されています。したがって、ビット 29 ~ 32 およびビット 58 ~ 60 は 1 に等しくなります。課題は、この関数の実行時間を最適化することです。

これを処理する方法についての私の考えは次のとおりです。2 つの forループを使用することを考えました。最初のループは「数値」の要素を繰り返し処理し (element_loop と呼びましょう)、2 番目のループは単一要素内のすべての 1 の位置を把握するために使用されます (bit_loop と呼びましょう)。そのために、シーケンスの「立ち上がり」と「立ち下がり」を検出することを考えました。

各 bit_loop サイクルの開始時に、マスクが 16 進数に初期化されます。値0x80000000。このマスクを使用して、最初のビットが 1 に等しいかどうかを確認します。はいの場合、現在の位置 (0) が保存されます。続いて、バイナリ表現のマスク " 10 00..." を使用して、次のサイクルの "立ち下がりエッジ" を検出します。「いいえ」の場合、次のサイクルで「立ち上がりエッジ」を検出するために、マスクは右に 1 ビット「01 00...」シフトされます。(私は太字の数字のカップルだけを気にします)

エッジが検出されると、現在の位置を保存し、適切な方法でマスクを 1 ビット シフトします。したがって、posの後。edge ( 01 ) neg に切り替えます。エッジ検出 ( 10 ) とその逆です。32 ビットの使用済み数値を繰り返しながら、すべてのエッジ位置をある種のベクトルに格納します。このベクトルは 2-dim である可能性があります。最初の列が 1 つのシーケンスの開始点で、2 番目の列がシーケンスの終了点です。さらに、ある要素から次の要素へのターンオーバーには特別な処理が必要になります。

これが私の一般的な質問です。このアプローチについてどう思いますか? これをより効率的に処理する方法はありますか?事前にご協力いただきありがとうございます。

ベン

4

2 に答える 2

1

ビットスキャンを効率的に行うためのさまざまなビット単位のトリックがありますが、C++ を使用している場合は、std::bitsetまたはを利用boost::dynamic_bitsetしてビット位置を反復処理できます。ただし、説明したアルゴリズムはブロックごとに逆方向に反復するため、 のようなものを使用して位置を反転する必要があります32 - (32 - i)

アーキテクチャによっては、各ビットにおよそ 1 サイクルかかるはずです。

于 2015-10-16T17:57:39.093 に答える
0

特別なプロセッサ命令またはさまざまな巧妙なトリックを使用して、単語に設定された最初のビットを見つけるための効率的な (一定時間の) 方法があります (設定されている最下位ビットの位置などを参照)。

少し注意すれば、逆方向に作業し、それらを使用して最初のゼロをスキャンし、次にマスキングとビット反転を実行して次のゼロを検索することができます。

これにより、特にシーケンスが平均して長いため、高速スキャンのゲインがビット調整のコストを上回る場合に、より高速なアルゴリズムが得られる可能性があります。

于 2015-10-16T18:16:23.773 に答える