precompute:
- 4bit key offset by 0bit
- 4bit key offset by 1bit
- 4bit key offset by 2bit
- 4bit key offset by 3bit
- 4 bit mask offset by 0bit
- 4 bit mask offset by 1bit
- 4 bit mask offset by 2bit
- 4 bit mask offset by 3bit
for each byte in bytes:
for each offset:
mask out bytes we care about
check if it matches our precomputed key
- 我々は見ていない任意の項目が一致またはない可能性がありますので、我々はすべての項目を見ているので、少なくとも
O(n)
。
- すべての項目を一度見るだけで十分なので、非線形アルゴリズムを使用する理由はありません。
- 合計64個なので、高度に最適化されたSIMD命令は恐らく面倒ではありません。パフォーマンスを向上させる可能性は低いです。
キーとマスクの事前計算は、キーをシフトすることによって行われる時、及びマスクに1〜4つの関連ビットを設定することにより、1ビットを残しました。いくつかのkey
とオフセット0-3
のそれぞれについて、
match = (bytes[i] & (0x0F << offset)) == (key << offset)
。 (key << offset)
と(0x0F << offset)
は4つのループごとに再利用されるため、4つの値を事前に計算してループを展開する方が高速になります。あなたのコンパイラがこれを行うかもしれませんが、そうでない場合は手動で行う方法です:
matches = 0
for (int i = 0; i < 64; i += 4) {
const mask0 = 0x0F << 0
const key0 = key << 0
match0 = (bytes[i+0] & mask0) == key0
const mask1 = 0x0F << 1
const key1 = key << 1
match1 = (bytes[i+1] & mask1) == key1
...
matches += match0 + match1 + match2 + match3
}
私はあなたの答えに苦労しています。あなたはこのアルゴリズムを最適化する努力がそれに価値がないと言っていますか? –
私は、上記のアルゴリズムよりもはるかに高速なアルゴリズムを見つけることはできないと言っています。 –
ありがとうございます。私はまだ事前計算の部分で混乱しています。あなたは何を正確にしていますか? –