web-dev-qa-db-ja.com

Bツリーとバイナリツリー

インメモリ(RAM)検索操作をbツリーで実装している場合、バイナリツリーと比較した場合、キャッシュやその他の効果の点で優れていますか?

私が知っていることは

binary search tress---O(log n)
btrees ---------------O(c log n)

いろいろなブログでそれについて多くの議論がありました。

38
user609306

O(logb n)= O(c log n)= O(log n)しかし、big-O表記に隠されている定数係数は、実装とハードウェアに応じて、著しく異なる場合があります。

Bツリーはプラッターハードディスク用に設計されており、物理セクター全体が読み取られるまでのアクセス時間が長い(ヘッドを所定の位置に移動させる)時間が必要です。 Bツリーノードをセクターと同じ大きさにすると、アクセス回数が最小になり、各読み取り操作からの有用なデータが最大になります。

しかし、メモリ不足で作業している場合、アクセス時間はごくわずかなので、より良い比較は、アルゴリズムによってアクセスされる単一の単語の数を数えることです。

たとえば、2を格納するデータ構造を計画しましょう20 各1ワードのキー、32ビットマシンで合計4MiBの生データ。

二分探索木は220 ノード。それぞれが1つのキーと2つのポインタ(3ワード)を保持します。深さはログになります2(220)=20。平均的な検索では、キーとそのパスの各ノードからのポインターの1つをルートから下まで読み取る必要があります= 40ワード

ハードディスク用に作成されたBツリーには4kBのノードがあります。各ノードは、キーとポインタの組み合わせのソートされた配列として、256〜512の範囲で内部的に格納できます。平均的な検索はどのようになりますか?平均3/4の充填を考慮すると、各ノードには384のエントリが含まれ、その内部バイナリ検索は平均ログでアクセスする必要があります。2(384)= 5.95キー。平均深度は対数になります384(220)= 2.33なので、検索では平均して2.33倍の5.95キー、つまり約14ワードを読み取る必要があります。

ファンアウトの少ない(分岐係数)Bツリーの場合、各ノードは16〜32のキーを保持し、平均の塗りつぶしは24キー、平均の深度ログになります。24(220)= 4.36、各ノードのバイナリ検索はログを作成します2(24)= 4.58の比較。全体の平均検索では、約20ワードを読み取る必要があります。

最後の2つのデータ構造は、変更に対して読み取り操作を最適化するため、バイナリツリーよりも優れた結果が得られることに注意してください。これらのBツリーの1つにキーを挿入するには、平均して384ワードまたは24ワードのノード全体を1つ以下に書き換える必要がありますが、バイナリツリーの場合、書き込み操作は、 40ワードまでタッチします。

(以前は間違っていました。コメントの間違いを指摘してくれた@vircoと@Grooに感謝します。)

いずれにせよ、ファンアウトの少ないメモリのみのBツリー 実際にはバイナリツリーよりもパフォーマンスが良いように見えます のようです。

特にノードあたり32キーは、32ビットと64ビットの両方の現在のアーキテクチャにとってスイートスポットのようです。多くの新しい言語とライブラリは、32キーのBツリーを組み込みのデータ構造]と一緒に、またはハッシュテーブルと配列の代わりとして使用しています。この使用法は Clojure や他の関数型言語が主導しましたが、その後、不変のデータ構造(例: Immutable.js

この結果は、メモリから読み取られるワード数をカウントするだけでなく、CPUがストールしてRAMを待機させる読み取り操作であるキャッシュミスによっても説明できます。キャッシュアーキテクチャが、Bツリーノード全体を一度に含むRAM=のチャンクをフェッチできる場合、ディスクベースの大容量ストレージに正常に使用されているのと同じ最適化が得られます。

ハードディスクに最適化されたデータ構造の場合、物理ディスクセクターと同じ大きさのノードを持つBツリーを使用して、ディスクアクセス時間を最小化します。この場合、レベル3キャッシュがRAMに対して実行する読み取り操作と同じ大きさのノードを持つBツリーを使用して、キャッシュミスを最小限に抑えています。

50
Tobia

Bツリーは、キーとポインタがメモリ内でクラスタ化されるという点でバイナリツリーとは異なります。そのため、ディスク上とメモリ内の両方でキャッシュ動作がいくらか改善されます。ただし、漸近(big-O)ランタイムに違いはありません。

8