バイナリ検索と補間検索の組み合わせの背後にある研究や理論はありますか?


14

私は読んで、このアルゴリズムはまだバイナリ検索アルゴリズムとみなすことができるの?数年前、ログファイルのインデクサー/検索を作成して、日付/時刻ウィンドウごとに大きなプレーンテキストファイル内のログエントリを見つけることを思い出しました。

これをしている間、私は補間検索を試すことにしました(それがそれが何であるかわからなかったので、自分でアイデアを見つけました)。その後、何らかの理由で、補間ステップとバイナリ分割ステップを交互に行うというアイデアを続けました。ステップ0では、テストポイントを決定するために補間し、ステップ1では正確な中間点などを取得します。

次に、純粋な補間検索、純粋なバイナリ検索、および組み合わせの試行を使用して、システムのベンチマークを行いました。交互アプローチは、時間とランダムに選択された時間のセットを見つける前に必要なテストの数の両方で明確な勝者でした。

リンクされた質問に触発されて、「代替補間検索とバイナリ検索」をすばやく検索したところ、何も見つかりませんでした。答えの1つに対するコメントで示唆されているように、「ヘッジ補間検索」も試しました。

既知のものにつまずいたことがありますか?特定の種類のデータに対して高速であるという理論的な正当性はありますか?通常、ログファイルはその間は大きく(たとえば、検索する1,000万行の1-2 GBのテキスト)、その中の日付/時間の広がりは、アクティビティの激しいバースト、一般的なピーク時間、および静かな時間で複雑でした。私のベンチマークテストは、検出するターゲット時間の均等な分布からサンプリングしました。

回答:


5

既知のものにつまずいたことがありますか?

Olog log nOlog n

  • 内省的検索が方法です(内挿検索とバイナリ検索を繰り返す)。これ以上詳細はありません。
  • N.サントロ、JBシドニー(1985)による補間バイナリ検索(IBS)。

    一般的な考え方は、検索される配列が所定のしきい値よりも大きい場合にのみ、補間検索が役立つということです。考慮された検索セグメントがユーザー定義のしきい値よりも小さい場合、バイナリ検索が無条件に適用されます。逆に、そのしきい値を超えると、内挿検索ステップが適用され、その後にバイナリ検索ステップが続きます。

    これには、アプローチに共通する多くのポイントがあります。

  • 適応検索(AS)(Biagio Bonasera、Emilio Ferrara、Giacomo Fiumara、Francesco Pagano、Alessandro Provetti)

    著者の言葉を使用して:

    [内挿-二分探索]は、内挿と二分探索を組み合わせた(しかしブレンドしない)同様のソリューションを考案しました。漸近的な複雑さは同じですが、いくつかの顕著な違いがあります。

    [切る]

    したがって、どの入力に対してもASがIBSよりも基本的な操作を行わないことを示すことができます。

    アルゴリズムは、検索セグメントの最適な半分を慎重に見つけるために、「単純な」補間検索よりも最大2倍の数の操作を費やす可能性があります。つまり、完了するために必要な反復回数が少なくなります。


6

2つのアルゴリズムをインターリーブして両方の世界を最大限に活用することは既知の手法ですが、通常はそれらを「並列」で実行し、どちらかが終了するとすぐに応答を返すと言われています。

補間検索は理論的には高速ですが、バイナリ検索と比較して2つの欠点があります。

  • 最悪の(線形の)最悪の場合のパフォーマンス

  • 中間点を計算するオーバーヘッドはかなり大きいです。バイナリ検索の反復は、補間検索の反復よりも数百倍高速です

範囲が大きいときに補間検索を実行し、範囲が狭くなったときにバイナリ検索に切り替えるアプローチが最も効率的であると期待しています。この実験を試していただければ幸いです。

ログnログログnログnログログn

結果は2つの現象で説明できると思います。

  • バイナリ検索と組み合わせると、最悪の場合の動作を回避できます

  • 小さいデータセットでのバイナリ検索への切り替えのプラスの効果


3
「バイナリ検索の反復は、補間検索の反復よりも数百倍高速です」と書きました。OPの場合、これらの2つの方法で中間点を計算することの差は、中間点の値を取得するのに必要なI / O時間によって小さくされることに注意してください。
リオリ

@liori:同じデータで繰り返されるバイナリ検索の初期の数回の反復は、同じ数個の要素が使用されるため、よりキャッシュに優しい可能性があります。そのため、四半期およびおそらく8分の1がキャッシュ内でホットになることが予想されます。範囲が十分に大きい場合は、バイナリから始めて、3回の反復後に補間に切り替えるのが理にかなっています。(または、非同期I / Oを実行して、最初に到着した結果を使用できる場合)。
ピーターコーデス

また、インメモリ検索の場合でも、キャッシュミス(200サイクルを超えるレイテンシ)は、たとえばIntel Haswellの 64ビット整数除算(32-96サイクル)のレイテンシの数倍です。32ビット整数除算は非常に高速です(22〜29サイクル)。メインメモリ帯域幅はすべてのコアの共有リソースですが、整数除算は各コアで複製されたリソースのみを使用します。
ピーターコーデス

2
ただし、複数の分散アクセスであっても、それらが一度に飛行している場合はより高速になるため、メモリ遅延はメモリ帯域幅よりもはるかに悪くなります。最新のx86ハードウェアでのインメモリbsearchで、現在の中間点をロードする前にNEXT反復の両方の可能性を(prefetcht0命令使用して)プリフェッチすることは勝利です。事前に次のフェッチアドレスを予測できない場合、これを行うことはできません。そのため、理論的な考慮事項は別として、実用的な実装の詳細は重要です。
ピーターコーデス

@liori:レコードを見つけるためにオンデマンドで読み取られていたため、ログファイルのインデックスを作成するとき、間違いなく中間点あたりのI / Oが主な要因でした。ファイル内のオフセットの計算とブロックの読み取りにはおそらく2桁以上の差がありました。したがって、計算される中間点の数が決定要因になります。インデックスにログファイルなしで今すぐ複製する場合-ここで試して投稿します-速度の差は測定できないかもしれませんが、測定可能な「必要な中間点の数」の差があるかもしれません。
ニールスレーター
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.