SORU
30 HAZİRAN 2011, PERŞEMBE


İkili kümeler verimli bir şekilde yerine getirilmesi

binary heaps verimli bir şekilde uygulanması konusunda bilgi arıyorum. Bir yerde verimli kümeler uygulama hakkında güzel bir makale olmalı gibi hissediyorum, ama bir şey bulamadım. Aslında bu konuda herhangi bir kaynak bulmak mümkün oldum . ben^>verimlibir dizi yığın depolama gibi temel ötesinde uygulanması. Aşağıda tarif olanlardan hızlı ikili bir yığın yapma teknikleri arıyorum.

Zaten Microsoft Visual C daha hızlı olan C bir uygulama yazdım ve gds'ler, std::priority_queue veya std::işlevi make_heap, std::push_heap ve std::pop_heap. Aşağıdaki zaten benim uygulamada hallettim teknikleri vardır. Ben sadece bu yeni fikirleri olduğunu sanmıyorum ama son 2 kendimi, geldi:

(Edit: eklenen bellek optimizasyonu bölüm)

  • 1 dizinler başlayın
    İkili kümeler Wikipedia implementation notes bak. Eğer yığın kök yerleştirilir at index 0, formülleri, daha sonra üst, sol alt ve sağ alt düğüm at indeksi, n sırasıyla (n-1)/2, 2n-1 ve 2n 2. Eğer 1 tabanlı bir dizi sonra kullanırsanız formülleri basit n, 2n/2 ve 2n 1 olur. Üst ve ALT sol 1 tabanlı bir dizi kullanarak daha verimli. Eğer p noktaları için bir 0-tabanlı dizi ve q = p - 1 Daha sonra biz erişim s[0] s[1] Bu yüzden yoktur Tepegöz kullanarak 1 tabanlı bir dizi.

  • Pop/yaprak temizleme ile değiştirilmesinden önce yığın alt element hareket edin
    Bir yığın Pop sıklıkla sol en alt yaprak üst elemanının değiştirilmesi tarafından açıklanan ve daha sonra yığın özelliği geri kadar hareket aşağı. Bu gittiğimiz her level 2 karşılaştırmalar gerektirir ve bu yığın üstüne bir yaprak taşındığımızdan beri, şimdiye kadar öbek aşağı gitmek olasıdır. Biraz daha az 2 günlük n karşılaştırmaları daha bekliyoruz bu yüzden.

    Bunun yerine, üst öğe olduğu yığın içinde bir delik bırakabilirsiniz. O zaman bu yinelenen kadar büyük çocuk hareket ettirerek yığın delik aşağı hareket ediyoruz. Geçtiğimiz gidip seviye başına sadece 1 karşılaştırma gerektirir. Bu şekilde delik bir yaprak olacak. Bu noktada yığın özelliği geri kadar delik pozisyonuna sağ en alt yaprak taşımak ve bu değeri öne alabiliriz. Taşındık değer bir yaprak olduğundan çok dibine kadar hareket beklemiyoruz. Eskisinden daha iyi olan n karşılaştırmaları, günlük biraz daha beklemeliyiz.

  • Destek üst değiştirin
    Max öğe kaldırmak ve aynı zamanda yeni bir öğe eklemek istediğiniz varsayalım. O zaman pop uygulamaları yukarıda açıklanan/kaldırma ya da yapabilirsiniz, ama sağ en alt yaprak taşımak yerine,/push eklemek istediğiniz yeni değeri kullanın. (Çoğu işlem bu tür bir turnuva ağacı bir yığın daha iyi olduğunu buldum, ama aksi takdirde yığın biraz daha iyi.)

  • (T) 2 Güç boyutu
    Üst, sol alt ve sağ alt formülleri dizinler üzerinde çalışmak ve doğrudan işaretçi değerleri üzerinde çalışmak için yapılmış olamaz. Dizinleri ile çalışmak için gidiyoruz ve bu dizin, bir dizi p değerleri p[i] bakmak anlamına gelir. P T* ve bir tamsayı ben ise

    &(p[i]) == static_cast<char*>(p)   sizeof(T) * i
    

    ve derleyici bu hesaplama gerçekleştirmek için p[i]. boyutu(T), bir derleme zamanı sabiti ve çarpma eğer boyutu(T) iki güç ise daha verimli bir şekilde yapılabilir. Benim uygulama daha hızlı 8 doldurma baytları 32 24 boyutu(T) artırmak için ekleyerek. Önbelleği düşük verimlilik muhtemelen bu yeterince büyük veri setleri için bir başarı değildir anlamına gelir.

  • Ön çarpma dizin
    Bu veri setinde #'lük bir performans artışı oldu. Biz hiç bir dizin bulma üst, sol alt ve sağ alt dışında olan tek şey Endeksi, bir dizi arayın. Eğer öyleyse biz takibini yapmak, j = boyutu(T) * ben yerine bir dizin ben, sonra yaparız bir ara p[i] olmadan çarpma olduğunu aksi takdirde örtülü olarak değerlendirilmesi p[i] çünkü

    &(p[i]) == static_cast<char*>(p)   sizeof(T) * i == static_cast<char*>(p)   j
    

    O zaman j-değerleri için sol alt ve sağ alt formülleri 2*j ve 2*j boyutu(T), sırasıyla. Üst formülü biraz daha zor, ve ben değer bir j-değeri dönüştürmek dışında pek fazla: geri yapmak için bir yol bulamadı

    parentOnJ(j) = parent(j/sizeof(T))*sizeof(T) == (j/(2*sizeof(T))*sizeof(T)
    

    Eğer boyutu(T) 2 güç ise o zaman bu 2 vardiya derlenir. O zamanki üst dizinleri kullanmaya ben daha 1 işlem daha. Ancak biz daha sonra kaydetmek 1 arama işlemi. Çok net etkisi ana ortaklık aynı süreyi bu şekilde, çocuk geriye doğru arama zaman alır bulmak ve sağ alt daha hızlı olur.

  • Bellek optimizasyonu

    TokenMacGuy ve templatetypedef cevapları önbellek özlüyor düşüren bellek tabanlı iyileştirmeleri işaret ediyor. Çok büyük veri setleri ve az kullanılan öncelik sırası için sıraya parçaları diske işletim sistemi ile takas olabilir. Bu durumda diskten değiştirme çok yavaş olduğu için buna değer, çok yük önbelleği en iyi şekilde faydalanmak için ekleyin. Verilerimi kolayca bellekte uyuyor ve sürekli kullanımda, kuyruk parçası muhtemelen diske takas olacak. Bu öncelik sırası en çok kullandığı için böyle olduğunu sanıyorum.

    CPU önbelleği daha iyi kullanmak için tasarlanmış başka bir öncelik sırası vardır. Örneğin 4-bir yığın daha az önbellek özlüyor olmalı ve ekstra yük miktarı o kadar fazla değil. Gitmekten 75% performans artışı olsun 1996 yılında LaMarca and Ladner rapor 4-kümeler hizalanır. Ancak, Hendriks 2010 yılında bildirildi

    Veri yerellik geliştirmek ve önbellek azaltmak için örtülü yığın LaMarca ve Ladner [17] tarafından önerilen iyileştirmeler de test edildi özlüyor. Gerçekten çok çarpık veri girişi için iki yönlü bir öbek göre biraz daha iyi bir tutarlılık gösteren dört yönlü bir yığın, ama sadece çok büyük sıra boyutları için hayata geçirdik. Çok büyük sıra boyutları daha hiyerarşik bir yığın tarafından yönetilir.

  • Soru
    Bu daha fazla teknikleri var mı?

  • CEVAP
    30 HAZİRAN 2011, PERŞEMBE


    İlginç bir kağıt/yazı üzerine bu konuyu dikkate alır davranışı önbellek/disk belleği üzerinde genel düzen öbek; fikri olmak, benim için büyük ölçüde daha pahalı ödemek için bir önbellek özledim ya sayfa daha neredeyse herhangi bir parçasında bir datastructure uygulanması. Kağıt bu adresleri bir yığın düzeni anlatılır.

    You're Doing It Wrong by Poul-Henning Kamp

    Bunu Paylaş:
    • Google+
    • E-Posta
    Etiketler:

    YORUMLAR

    SPONSOR VİDEO

    Rastgele Yazarlar

    • adrianisen

      adrianisen

      25 Kasım 2009
    • MagmaRhino

      MagmaRhino

      16 Temmuz 2011
    • nigahiga

      nigahiga

      21 Temmuz 2006