C (または派生言語) を使用していますか? もしそうなら、配列のエンコーディングを制御できますか? たとえば、ビットマップを使用してカウントできるとします。ビットマップの優れた点は、ルックアップ テーブルを使用してカウントを合計できることです。ただし、サブ範囲の端が 8 で割り切れない場合は、最後の部分的なバイトを特別に処理する必要がありますが、速度は大幅に向上します。 .
そうでない場合は、少なくとも 1 バイトとしてエンコードできますか? その場合、スパース性が存在する場合は、スパース性を利用できる可能性があります (より具体的には、ゼロのマルチ インデックス スワスが頻繁に存在することを期待します)。
だから:
u8 input = {1,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,1,1,0,0,0,1....................N};
あなたは(未テスト)のようなものを書くことができます:
uint countBytesBy1FromTo(u8 *input, uint start, uint stop)
{ // function for counting one byte at a time, use with range of less than 4,
// use functions below for longer ranges
// assume it's just one's and zeros, otherwise we have to test/branch
uint sum;
u8 *end = input + stop;
for (u8 *each = input + start; each < end; each++)
sum += *each;
return sum;
}
countBytesBy8FromTo(u8 *input, uint start, uint stop)
{
u64 *chunks = (u64*)(input+start);
u64 *end = chunks + ((start - stop) >> 3);
uint sum = countBytesBy1FromTo((u8*)end, 0, stop - (u8*)end);
for (; chunks < end; chunks++)
{
if (*chunks)
{
sum += countBytesBy1FromTo((u8*)chunks, 0, 8);
}
}
}
基本的なトリックは、ターゲット配列のスライスを、言語が一度に見ることができる単一のエンティティにキャストし、その値のいずれかがゼロであるかどうかを推論によってテストし、ブロック全体をスキップする機能を利用することです。ゼロが多いほど、うまく機能します。大きなキャスト整数が常に少なくとも 1 つある場合、このアプローチはオーバーヘッドを追加するだけです。u32 を使用する方がデータに適している場合があります。または、1 と 8 の間に u32 テストを追加すると役立ちます。ゼロが 1 よりもはるかに一般的なデータセットの場合、私はこの手法を大いに活用しました。