2010-12-12 9 views
3

各バイトの下位6ビットだけが有用なデータを持つ100,000バイトの配列から開始します。できるだけ速く75,000バイトの配列にデータをパックして、データの順序を保持する必要があります。できるだけ早く配列にデータをパック

unsigned int Joinbits(unsigned int in) {} 
+3

6ビット* 4 = 24ビット= 3バイト。一度に4バイトを処理するコードを記述し、それぞれに「正しいこと」を実行すると、勝者になります。 –

+0

システムのワードサイズはどのくらいですか?あなたのシステムプロセッサーは何ですか? 「可能な限り速く」は、どの操作が最も並列性が高く、コード量が最小であるかなど、システム固有の動作に依存します。 –

+0

6ビットの値の中には結果にオーバーラップするバイト境界があることを考えると、ここではエンディアンが影響します。どのエンディアンが欲しいですか? –

答えて

4
// 00111111 00111111 00111111 00111111 
// 000000 001111 111122 222222 
void pack6(
    register unsigned char o, 
    register unsigned char const *i, 
    unsigned char const *end 
) 
{ 
    while(i!=end) 
    { 
    *o++ = *i   << 2u | *(i+1) >> 4u; ++i; 
    *o++ = (*i & 0xfu) << 4u | *(i+1) >> 2u; ++i; 
    *o++ = (*i & 0xfcu) << 6u | *(i+1)  ; i+=2; 
    } 
} 

は失敗し、入力の上位2ビットがゼロであると仮定。 完全に移植可能です。 4入力バイトを6回読み込むので、読み取り時に50%の非効率性がありますが、プロセッサキャッシュとコンパイラオプティマイザが役立ちます。変数を使用して読み取りを保存しようとすると、生産性が低下する可能性があります。

0
for(int pos=0; pos<100000; pos+=4) 
{ 
    *(int*)out = (in[0] & 0x3F) | ((in[1] & 0x3F)<<6) | ((in[2] & 0x3F)<<12) | ((in[3] & 0x3F)<<18); 
    in += 4; 
    out += 3; 
} 
+0

これは、intが任意の位置にあるプラットフォームでのみ機能します。 –

+0

大部分のプラットフォームでSegfaultはミスアライメントが原因です。 – Yttrill

+1

ほとんどのプラットフォームですか?確かにいくつかのプラットフォームを意味します。あなたがプラットフォームとしてWindowsを数えれば。 – TonyK

0

これはCで、私はC++を知りません。おそらくバグがいっぱいで、決して最速の方法ではないかもしれませんが、それはおそらく高速ではありません。でも、何かを学ぶのは楽しい挑戦のように思えたので、私はちょうどいい気分にしました。 :入力の長さが4で割り切れない場合はD

unsigned char unpacked[100000]; 
unsigned int packed[75000/4]; 

for (int i = 0; i < (100000/6); i += 6) { 
    unsigned int fourBytes = unpacked[i]; 
    fourBytes += unpacked[i + 1] << 6; 
    fourBytes += unpacked[i + 2] << 12; 
    fourBytes += unpacked[i + 3] << 18; 
    fourBytes += unpacked[i + 4] << 24; 
    fourBytes += unpacked[i + 5] << 30; 

    unsigned short twoBytes = unpacked[i + 5] >> 2; 
    twoBytes += unpacked[i + 6] << 4 
    twoBytes += unpacked[i + 7] << 10; 

    packed[i] = fourBytes; 
    packed[i + 4] = twoBytes; 
} 
+0

まず、ビット操作を行うときは、符号なしの文字とintを排他的に使用してください。最後の2つの割り当ては機能しません。位置iとi + 4にのみバイトを割り当てます。 – Yttrill

+0

また、解凍された[]の最後の4バイトが失われます。 – TonyK

+0

4つの入力バイトを3つの出力バイトにパックしたいとします。あなたは現在、5を4にパックしてから、3を2にパックしようとします。また、char配列にintを代入すると、intデータで4つの連続した配列スロットが埋められません(CまたはC++では保証されていない 'sizeof(int)== 4 'を前提とします)。 intをcharに変換し、指定された1つのスロットに割り当てます。 –

関連する問題