2009-03-20 17 views
9

C列にビット演算を行うための最も効率的な方法は何です最初の1つの結果から得られた別の配列と、ビットごとの演算を使用する2つ目の配列を各バイトで取得します。は、私のようなC配列を持つ

これを行う最も効率的な方法は何ですか?

あなたの答えに感謝します。後方プリロードプロセッサのキャッシュラインを行く

答えて

13
for (i = 10 ; i-- > 0 ;) 
    result_array[i] = byte_array[i] & byte_mask[i]; 
  • デクリメントを比較に含めると、いくつかの命令を保存できます。

これはすべてのアレイとプロセッサで機能します。ただし、配列がワード単位で配置されていることがわかっている場合、より高速な方法はより大きな型にキャストして同じ計算を行うことです。

たとえば、n=10の代わりにn=16とします。そして、これははるかに高速になります:

uint32_t* input32 = (uint32_t*)byte_array; 
uint32_t* mask32 = (uint32_t*)byte_mask; 
uint32_t* result32 = (uint32_t*)result_array; 
for (i = 4 ; i-- > 0 ;) 
    result32[i] = input32[i] & mask32[i]; 

は(もちろん、あなたがuint32_tのために適切な型を必要とし、nが2のべき乗でない場合は、最初および/またはそのようエンディングをクリーンアップする必要があります32

バリエーション:この質問では、具体的には結果が別の配列に配置されることを要求していますが、入力配列をインプレースで変更することはほぼ確実に速くなります。

+0

キャッシュプリフェッチャが逆順で機能するのを待ちますか?私はそれが前進することを先取りするだけだと思った。 – Crashworks

+2

プロセッサのキャッシュラインのプリロードについて心配するのは、早すぎる最適化のようです。 – Trent

+5

@Trent - 質問の*ポイント*は最適化です。また後方に行くことも遅くないので、あなたもそうかもしれません。 @Crashworks - キャッシュラインは通常は大規模な境界に位置合わせされていることを覚えておいてください。通常は、要求する前にバイトをプルする必要があります。 –

5

あなたはそれを速くしたい場合は、BYTE_ARRAYは(64ビットマシン上で8)4の倍数である長さを持っていることを確認して、次に:

char byte_array[12]; 
char byte_mask[12]; 
/* Checks for proper alignment */ 
assert(((unsigned int)(void *)byte_array) & 3 == 0); 
assert(((unsigned int)(void *)byte_mask) & 3 == 0); 
for (i = 0; i < (10+3)/4; i++) { 
    ((unsigned int *)(byte_array))[i] &= ((unsigned int *)(byte_mask))[i]; 
} 

これはそれにバイトをしているよりもはるかに高速であります1バイトあたり。

(これはインプレース変異であることに注意してください。あなたもオリジナルのBYTE_ARRAYを維持したい場合、あなたは明らかに代わりに別の配列に結果を格納する必要があります。)

+0

10/4 == 2なので、これは8文字しか処理しません。さらに、非x86アーキテクチャでは、非整合メモリアクセスによるバスエラーが発生することがあります。 – bk1e

+0

bk1e:そうです、私は<10/4ですが間違っています。バスエラーに関するコメントも正しいです。私は答えを編集します。 –

+0

4/8の倍数でない場合、duffのデバイスを使用してください:) – Brian

1
\#define CHAR_ARRAY_SIZE (10) 
\#define INT_ARRAY_SIZE  ((CHAR_ARRAY_SIZE/ (sizeof (unsigned int)) + 1) 

typedef union _arr_tag_ { 

    char   byte_array [CHAR_ARRAY_SIZE]; 
    unsigned int int_array [INT_ARRAY_SIZE]; 

} arr_tag; 

今すぐマスキング用int_array。これは、32ビットプロセッサと64ビットプロセッサの両方で動作する可能性があります。

arr_tag arr_src, arr_result, arr_mask; 

for (int i = 0; i < INT_ARRAY_SIZE; i ++) { 
    arr_result.int_array [i] = arr_src.int_array[i] & arr_mask.int_array [i]; 
} 

これを試してみると、コードもきれいに見える場合があります。

+0

サンプルコードを書いていただきありがとうございます:) – alvatar

関連する問題