2011-02-01 10 views
5

固定サイズの循環バッファー(配列として実装されています):初期化時に、バッファーには指定された最大数の要素が入れられます。円内の現在の位置を追跡するために単一の位置インデックスを使用します。固定サイズの循環バッファーのインデックスを効率的にラップする方法

循環バッファ内の要素に効率的にアクセスするにはどうすればよいですか?ここに私の現在のソリューションされています

int GetElement(int index) 
{ 
    if (index >= buffer_size || index < 0) 
    { 
     // some code to handle the case 
    } 
    else 
    { 
     // wrap the index 
     index = end_index + index >= buffer_size ? (index + end_index) - buffer_size : end_index + index; 
    } 

    return buffer[index]; 
} 

いくつかの定義:
end_indexはすぐにサークル内の最後の要素の後の要素のインデックス(それも中START_INDEXと同じと考えられる、またはの最初の要素でありますサークル)。
buffer_sizeは、バッファの最大サイズです。

+0

(あなたが負の数で作業する必要があると仮定)? –

+0

@Fred、循環バッファに要素を追加すると、buffer_sizeを通過するたびにインデックスがラップされます。 – Kiril

+0

@リリック:私は何かが欠けているはずです。 –

答えて

10

バッファの長さが常に2の累乗で、トップビットがマスクされていることを確認します。

+1

モジュラス/モジュロ? :P –

+4

@ Johnatan:早期に最適化されたモジュロ演算、はい。 – delnan

+0

@delnan私は時期尚早には分かりません。個人的に私はモジュロを使用しますが、実際には、この理由で配列が2の累乗になることは非常に一般的な方法です。 – corsiKa

5

それはプロセッサに多少依存しますが、それはおそらく、少なくともreturn (end_index + index) % buffer_size;

+0

**(1)** end_indexは 'buffer_size'と等しくない(0インデックス配列)?これを念頭に置いて、 'a = -5'、' n = 4'なら '(a + n)%n;を返すように単純化しましょう。 n) 'は' -1'を返します。これはまだ範囲外です。 (すなわち、a <-nのために失敗する)。 – mpen

+1

@マーク:元のコードは負の数の可能性を暗示していますが、通常は許可されていません(ただし、unsigned型を使用する方が良いでしょう)。 –

+0

ああ...私の状況は違うと思います。私はしばしば最後の要素を意味する-1を使用します。 – mpen

0

FWIWような何かをしようとする価値がある、あなたが並列アレイ常に行うことができます:i = next[i];

をしかし、実際に、私はいつもてきましたこれは今までに大幅なパフォーマンスの問題である場合i++; if (i >= n) i = 0; OR

i = (i+1) % n;かかわらず、私は本当に驚いだろう:ちょうどこれが行わ。

4

I tested all 3 versions

// plain wrap 
public static int WrapIndex(int index, int endIndex, int maxSize) 
{ 
    return (endIndex + index) > maxSize ? (endIndex + index) - maxSize : endIndex + index; 
} 

// wrap using mod 
public static int WrapIndexMod(int index, int endIndex, int maxSize) 
{ 
    return (endIndex + index) % maxSize; 
} 

// wrap by masking out the top bits 
public static int WrapIndexMask(int index, int endIndex, int maxSize) 
{ 
    return (endIndex + index) & (maxSize - 1); 
} 

パフォーマンスの結果は(ティック):

Plain: 25 Mod: 16 Mask: 16 (maxSize = 512) 
Plain: 25 Mod: 17 Mask: 17 (maxSize = 1024) 
Plain: 25 Mod: 17 Mask: 17 (maxSize = 4096) 

だから、それはのサイズ上の任意の制限を必要としないため、弾性率は、より良い選択であると思われますバッファ。

11

私が作ってみたベストです:

public static int Wrap(int index, int n) 
{ 
    return ((index % n) + n) % n; 
} 

BUFFER_SIZEと等しくEND_INDEXされていない場合

+1

私にはわかりませんでしたので、ここで少し明確にします。 'a'はラップする必要のあるインデックスで、' n'は配列のサイズです。 – GER

関連する問題