İkili arama ve enterpolasyon aramasını birleştirmenin arkasında herhangi bir çalışma veya teori var mı?


14

Az önce okudum Bu algoritma hala bir İkili Arama algoritması olarak kabul edilebilir mi? ve birkaç yıl önce tarih / saat penceresine göre büyük düz metin dosyalarındaki günlük girdilerini bulmak için bir dizinleyici / günlük dosyaları aradığımı hatırladım.

Bunu yaparken enterpolasyon aramayı denemeye karar verdim (buna ne denildiğini bilmiyordum, bu fikre tek başıma rastladım). Sonra bir nedenle ikili enterpolasyon adımlarını ikili bölünmüş adımlarla değiştirme fikrine devam ettim: Adım 0'da test noktasına karar vermek için enterpolasyon yapacağım, sonra adım 1 tam orta noktayı alırdım vb.

Daha sonra sistemi saf enterpolasyon araması, saf ikili arama ve kombinasyon girişimimi kullanarak karşılaştırdım. Alternatif yaklaşım, rastgele seçilmiş bir dizi zaman bulmadan önce gereken zaman ve test sayısında açık bir kazanan oldu.

Bağlantılı sorudan esinlenerek, "alternatif enterpolasyon araması ve ikili arama" için hızlı bir arama yaptım ve hiçbir şey bulamadım. Ben de cevaplardan biri hakkındaki yorumumda önerildiği gibi "korunmuş enterpolasyon arama" denedim.

Bilinen bir şeyle karşılaştım mı? Belirli veri türleri için daha hızlı olmasının herhangi bir teorik gerekçesi var mı? Günlük dosyaları tipik olarak zaman için büyüktü (örneğin, aramak için belki 10 milyon satır içeren 1-2 GB metin) ve tarihlerin / saatlerin yayılması, yoğun aktivite patlamaları, genel pik süreleri ve sessiz sürelerle karmaşıktı. Kıyaslama testlerim, bulmak için hedef sürelerin eşit dağılımından örneklendi.

Yanıtlar:


5

Bilinen bir şeyle karşılaştım mı?

Enterpolasyon-arama ve ikili aramanın bir karışımına dayanan, ortalama vaka erişim süresi (tekdüze dağıtım) ve en kötü vaka süresi (değerler eşit dağılmamış) ile çeşitli yöntemler vardır. :O(log log n)O(log n)

  • İçgözlemsel arama yönteminizdir (enterpolasyon araması ve ikili arama arasında yineleme). Daha fazla ayrıntım yok.
  • İnterpolasyon-ikili arama (IBS), N. Santoro, JB Sidney (1985).

    Genel fikir, enterpolasyon aramasının yalnızca aranan dizi belirli bir eşik değerden daha büyük olduğunda yararlı olmasıdır. Dikkate alınan arama segmenti kullanıcı tanımlı bir eşik değerden daha küçük olduğunda, ikili arama koşulsuz uygulanır. Bunun tersine, bu eşik üzerinde bir enterpolasyon arama adımı uygulanır, ardından bir ikili arama adımı uygulanır.

    Bu, yaklaşımınızla ilgili birçok ortak noktaya sahiptir.

  • Uyarlamalı arama (AS) Biagio Bonasera, Emilio Ferrara, Giacomo Fiumara, Francesco Pagano, Alessandro Provetti

    Yazarların sözlerini kullanarak:

    [İnterpolasyon-ikili arama], enterpolasyon ve ikili aramayı birleştiren (fakat harmanlamayan) benzer bir çözüm geliştirdi. Asimptotik karmaşıklık aynı olmasına rağmen, bazı belirgin farklılıklar vardır.

    [KESMEK]

    Dolayısıyla, herhangi bir AS girişi için IBS'den daha temel işlemler yapmayacağını göstermek mümkündür.

    Algoritma, arama segmentinin en iyi yarılamasını dikkatlice bulmak için "basit" enterpolasyon aramasından iki kat daha fazla işlem harcayabilir, bu da tamamlanması için daha az yinelemenin gerektiği anlamına gelir (ancak daha büyük bir ek yükünüz vardır) .


6

Her iki dünyanın da en iyisini elde etmek için iki algoritmanın ayrıştırılması bilinen bir tekniktir, ancak genellikle bunları "paralel" olarak çalıştırma ve sonlandırıldığında bir cevap döndürme olarak ifade edilir.

Teorik olarak daha hızlı olmasına rağmen, enterpolasyon aramasının ikili aramaya kıyasla iki dezavantajı vardır:

  • Korkunç (doğrusal) en kötü durum performansına sahip

  • Orta noktayı hesaplama yükü oldukça büyüktür; ikili arama yinelemesi, enterpolasyon arama işleminden yüz kat daha hızlıdır

Aralık büyükken enterpolasyon araması yaptığınız ve aralık küçüldüğünde ikili aramaya geçeceğiniz bir yaklaşımın en verimli olmasını beklerim. Bu deneyi deneyebilirsen iyi olur.

Veri kümeniz küçüldükçe ve arasındaki fark önemsiz hale gelir; zaten çok küçük ve çok daha küçük olamazdı. Bu noktada, enterpolasyon araması yapma yükü, kaydedebileceğiniz yinelemelere kıyasla buna değmez.log günlüğü n günlüğü n günlüğü günlüğü nlognloglognlognloglogn

Sonuçlarınızın iki olayla açıklanabileceğini düşünüyorum:

  • İkili arama ile birleştirmek en kötü durum davranışından kaçınmanıza izin verir

  • Küçük bir veri kümesi üzerinde ikili aramaya geçmenin olumlu etkisi


3
"Bir ikili arama yinelemesi, enterpolasyon arama işleminden yüzlerce kat daha hızlıdır" yazdınız. OP'nin durumunda, bu iki yöntemde orta noktanın hesaplanması arasındaki farkın, orta noktanın değerini almak için gerekli I / O süresi tarafından gölgelendiğini lütfen unutmayın.
liori

@liori: Aynı veriler üzerinde tekrarlanan ikili aramaların ilk birkaç yinelemesi, aynı birkaç öğe kullanıldığından daha önbellek dostu olabilir. Böylece çeyreklerin ve belki de sekizinci kişilerin önbellekte sıcak kalması beklenebilir. İkili ile başlamak ve üç yinelemeden sonra enterpolasyona geçmek, aralıklar yeterince büyükse mantıklı olabilir. (Ya da zaman uyumsuz G / Ç yapabilir ve önce gelen sonuç varsa kullanabilirsiniz).
Peter Cordes

Ayrıca, bir bellek içi arama için bile, önbellek kaçırmanın (200 döngü gecikmesinin üzerinde) örneğin Intel Haswell'de 64 bit tamsayı bölümünün (32-96 döngü) gecikme süresinin birkaç katı vardır . 32 bit tamsayı bölümü önemli ölçüde daha hızlıdır (22-29 döngü). Ana bellek bant genişliği tüm çekirdekler için paylaşılan bir kaynaktır, ancak tamsayı bölümü yalnızca her çekirdekte çoğaltılmış kaynakları kullanır.
Peter Cordes

2
Bununla birlikte, bellek gecikmesi bellek bant genişliğinden çok daha kötüdür, çünkü birden fazla dağınık erişim bile uçuştalarsa daha hızlı gider. Modern x86 donanımında bellek içi bir arama için, geçerli orta noktayı yüklemeden önce NEXT yinelemesi için her iki olasılığı da önceden almak (bir prefetcht0talimatla ) kazanmasıdır . Bir sonraki getirme adresini önceden tahmin edemiyorsanız bunu yapamazsınız. Bu nedenle , teorik hususların yanı sıra pratik uygulama detayları da önemli olabilir .
Peter Cordes

@liori: Kayıtları bulmak için istek üzerine okunduğundan, bir günlük dosyasını dizine alırken kesinlikle orta nokta başına G / Ç ana faktördü. Muhtemelen dosyadaki ofseti hesaplamak ve bir blok okumak arasında ikiden fazla büyüklük sırası vardır - bu nedenle hesaplanan orta noktaların sayısı belirleyici faktör olacaktır. Şimdi bir günlük dosyası olmadan endekslemek için - burada çalışacağım ve göndereceğim bir şey - çoğaltılabilirsem, ölçülebilir bir hız farkı olmayabilir, ancak ölçülebilir bir "gerekli orta nokta sayısı" farkı olabilir.
Neil Slater
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.