2012-01-26 6 views
6

ビット拡張/複製を実行する効率的な(高速の)アルゴリズムはありますか?例えばビット拡張/複製のアルゴリズムですか?

、(24ビット値を作成)3により8ビット値の各ビットを展開:提案されている

1101 0101 => 11111100 01110001 11000111 

強引な方法は、ルックアップテーブルを作成することです。将来、展開値を変更する必要があるかもしれません。つまり、上記の例では3で拡張していますが、他の値で拡張する必要があるかもしれません。可能であれば、避けたい複数のルックアップテーブルが必要です。

+6

8ビットの値しか扱っていない場合は、ルックアップテーブルがほぼ確実に最適なオプションになります。それは非常に小さなスペースを使用します。あなたのユースケースとあなたが一般的であると予想される操作の詳細を教えてください。 – templatetypedef

+0

入力は一定のシリアルビットストリームです。現在の要件では、データの各チャンクは一度に8バイトずつ到着します。その後、3ビットずつ拡張して各ビットを別のビットストリームとして送出する必要があります。 192bitsで64bits。将来の要件は、それぞれの拡張された8ビット値の前に "ヘッダ"ビットを追加し、もちろんバイト境界にパディングすることを含むかもしれない。 LUTは速いですが、どれくらいの頻度で実行する必要があるかを考えれば、パフォーマンスの向上が期待できます。 – jivany

+1

多くのアーキテクチャには、この種の計算を大幅に高速化できる命令があります。これらの命令を活用してプラットフォーム間の互換性を崩すことを恐れていない場合は、ほぼ確実に勝つことができます。アルゴリズム的に "些細な"ものを最適化する場合は、低レベルの最適化を行うことが重要です。 @Kaganar合意。 – Kaganar

答えて

6

算術演算が何らかの理由でメモリアクセスより速い場合は、ルックアップテーブルよりも速くなる可能性があります。これは、計算がベクトル化される(PPC AltiVecまたはIntel SSE)場合、および/またはプログラムの他の部分がキャッシュメモリのすべてのビットを使用する必要がある場合に可能です。

膨張係数= 3の場合は、わずか7の命令が必要とされている:

out = (((in * 0x101 & 0x0F00F) * 0x11 & 0x0C30C3) * 5 & 0x249249) * 7; 

または他の代替、10の命令で:他の膨張係数> = 3の場合

out = (in | in << 8) & 0x0F00F; 
out = (out | out << 4) & 0x0C30C3; 
out = (out | out << 2) & 0x249249; 
out *= 7; 

unsigned mask = 0x0FF; 
unsigned out = in; 
for (scale = 4; scale != 0; scale /= 2) 
{ 
    shift = scale * (N - 1); 
    mask &= ~(mask << scale); 
    mask |= mask << (scale * N); 
    out = out * ((1 << shift) + 1) & mask; 
} 
out *= (1 << N) - 1; 

またはその他の代替、拡張係数> = 2の場合:

unsigned mask = 0x0FF; 
unsigned out = in; 
for (scale = 4; scale != 0; scale /= 2) 
{ 
    shift = scale * (N - 1); 
    mask &= ~(mask << scale); 
    mask |= mask << (scale * N); 
    out = (out | out << shift) & mask; 
} 
out *= (1 << N) - 1; 

shiftおよびmaskビットストリーム処理の前に値を計算する方がよい。

+0

素晴らしい返答です。私の同僚と私はこれに近づきましたが、ハンドウェーブとホワイトボードのブレーンストーミングを行っていましたが、私たちのアプローチよりもはるかに効率的です。私はコードの残りの部分を実装し、それがどのように運賃を参照しているいくつかのテストを実行する必要があります。 – jivany

+0

誰かがこれの背後にある数学へのリンクを持っていますか?私は周りを探索してきましたが、これがどのように機能するかについては説明なしに魔法を見つけることができました。私は魔法の数字にいくつかのパターンがあることを知っているが、他のすべてが私を逃げている。 –

+0

nvm、私はそれを考え出した。バイナリを書き出し、パターンを見つけるのに役立ちます。それでもなお、トピックのリンクは大変ありがとうございます。 https://gist.github.com/corytodd/056ed01228f59fee9a13d00fc25b9a62 –

1

時刻に1つの入力ビットを使用できます。もちろん、ルックアップテーブルよりも遅くなりますが、テーブルのための十分なスペースがない小さな8ビットマイクロコントローラ用の書き込みを行う場合は、できるだけ小さなROMフットプリントが必要です。

関連する問題