2

ウィキペディアから:

主な欠点は、全体的なスペース使用量が多く、インデックス作成が遅いことです。どちらも、ツリー構造が大きくなり、深くなるにつれて、より深刻になります。ただし、インデックス作成の実際のアプリケーションの多くは、文字列の反復のみを含みます。これは、リーフノードがキャッシュ効果の恩恵を受けるのに十分な大きさである限り高速のままです。

ロープとストリングの間にある種の妥協点を実装しています。基本的にはロープだけですが、連結された文字列が短い場合に連結オブジェクトを文字列に平坦化する点が異なります。これにはいくつかの理由があります。

  1. 連結された文字列が短い場合、連結オブジェクトの利点は最小限に抑えられます(2つの文字列を通常の形式で連結するのにそれほど時間はかかりません)。
  2. これを行うと、木の大きさ/深さが減少します(ロープの欠点が減少します)。
  3. これを行うと、リーフノードのサイズが大きくなります(キャッシュをより有効に活用するため)。

ただし、長さが長くなるとロープのメリットも少なくなるので、妥協点を見つけたいと思います。「スイートスポット」は、論理的には「リーフノードがキャッシュ効果の恩恵を受けるのに十分な大きさ」の周りにあるように見えます。問題は、それがどれくらい大きいかわからないということです。

編集:私がこれを書いている間、理想的なサイズはキャッシュページのサイズであることに気づきました。それは、ロープが文字列でとにかく発生する場合にのみキャッシュミスを引き起こすためです。だから私の2番目の質問は、この推論は正しいですか?また、キャッシュページのサイズを検出するクロスプラットフォームの方法はありますか?

私の目標言語はC++です。

4

1 に答える 1

3

ロープのような文字列の極限ケースは、 の上に構築されstd::list<char>ます。それは明らかにあまり効果的ではありません。反復すると、「リーフ」/文字ごとに 1 つのキャッシュ ミスが発生する可能性があります。リーフあたりの文字数が増えると、ミスの平均数が減少し、リーフの割り当てが 1 つのキャッシュ ラインを超えるとすぐに不連続になります。

より大きな葉を持つことはまだ良い考えかもしれません。キャッシュ階層内のメモリ転送は、異なるレベルで異なる粒度を持つ場合があります。また、CPU の混合セット (コンシューマ PC) を対象とする場合、より高い 2 の累乗であるリーフ サイズは、より多くのマシンのキャッシュ ライン サイズの整数倍になります。たとえば、16 バイトと 32 バイトのキャッシュ ラインを使用して CPU をアドレス指定している場合、32 バイトは常に整数のキャッシュ ラインであるため、より適切な選択となります。キャッシュラインの半分を無駄にするのは残念です。

于 2009-08-24T07:55:30.310 に答える