Listeyi Atla İkili Arama Ağacına Karşı


Yanıtlar:


257

Atlama listeleri, eşzamanlı erişim / değişiklik için daha uygundur. Herb Sutter , eş zamanlı ortamlardaki veri yapısı hakkında bir makale yazdı . Daha fazla bilgi içerir.

Bir ikili arama ağacının en sık kullanılan uygulaması kırmızı-siyah bir ağaçtır . Eşzamanlı problemler ağaç modifiye edildiğinde ortaya çıkar ve genellikle yeniden dengelenmesi gerekir. Yeniden dengeleme işlemi, ağacın büyük bölümlerini etkileyebilir; bu, ağaç düğümlerinin çoğunda muteks kilidi gerektirir. Atlama listesine bir düğüm eklemek çok daha yerelleştirilmiştir, yalnızca etkilenen düğüme doğrudan bağlı düğümlerin kilitlenmesi gerekir.


Jon Harrops yorumlarından güncelleme

Fraser ve Harris'in en son makalesini okudum Eşzamanlı programlama kilitsiz . Kilitsiz veri yapılarıyla ilgileniyorsanız gerçekten iyi şeyler. Makale İşlemsel Bellek ve çok kelimeli karşılaştırmalı takas MCAS teorik işlemine odaklanmaktadır . Bunların her ikisi de henüz hiçbir donanımı desteklemediğinden yazılımda simüle edilmiştir. Yazılımda MCAS oluşturabildiklerinden oldukça etkilendim.

Bir çöp toplayıcı gerektirdiğinden işlemsel bellek öğelerini özellikle çekici bulmadım. Ayrıca yazılım işlem belleği performans sorunları ile uğraşmaktadır. Ancak, donanım işlem belleği yaygınlaşırsa çok heyecanlanırım. Sonunda hala araştırma ve başka bir on yıl boyunca üretim kodu için kullanılamaz.

Bölüm 8.2'de birkaç eşzamanlı ağaç uygulamasının performansını karşılaştırırlar. Bulgularını özetleyeceğim. 50, 53 ve 54 sayfalarında çok bilgilendirici grafikler olduğu için pdf'i indirmeye değer.

  • Kilitleme atlama listeleri inanılmaz derecede hızlı. Eşzamanlı erişim sayısı ile inanılmaz derecede iyi ölçeklenirler. Bu, atlama listelerini özel kılan şeydir, diğer kilit tabanlı veri yapıları baskı altında dolaşma eğilimindedir.
  • Kilitsiz atlama listeleri , atlama listelerini kilitlemekten sürekli olarak daha hızlıdır, ancak zar zor.
  • işlem atlama listeleri , kilitleme ve kilitleme olmayan sürümlerden 2-3 kat daha yavaştır.
  • kilitleme kırmızı-siyah ağaçlar eşzamanlı erişim altında dolandırıcı. Performansları her yeni eşzamanlı kullanıcıyla doğrusal olarak düşer. Bilinen iki kilitleme kırmızı-siyah ağaç uygulamasından biri, ağaç yeniden dengelemesi sırasında esasen küresel bir kilide sahiptir. Diğeri fantezi (ve karmaşık) kilit yükseltmeyi kullanır, ancak yine de küresel kilit sürümünü önemli ölçüde gerçekleştirmez.
  • kilitsiz kırmızı-siyah ağaçlar mevcut değil (artık doğru değil, bkz. Güncelleme).
  • işlemsel kırmızı-siyah ağaçlar işlemsel atlama listeleriyle karşılaştırılabilir. Bu çok şaşırtıcı ve umut vericiydi. İşlemsel bellek, yazmak daha kolaysa daha yavaş olsa da. Eşzamanlı olmayan versiyonda hızlı arama ve değiştirme kadar kolay olabilir.

Güncelleme
İşte kilitsiz ağaçlarla ilgili kağıt: CAS Kullanarak Kilitsiz Kırmızı-Siyah Ağaçlar .
Ona derinlemesine bakmadım, ancak yüzeyde sağlam görünüyor.


3
Dejenere olmayan bir atlama listesinde, düğümlerin yaklaşık% 50'sinin ekleme ve silme işlemini oldukça etkili kılan tek bir bağlantıya sahip olması gerektiğinden bahsetmiyoruz.
09:44, Adisak

2
Yeniden dengeleme için muteks kilit gerekmez. Bkz. Cl.cam.ac.uk/research/srg/netos/lock-free
Jon Harrop

3
@Jon, evet ve hayır. Bilinen kilitsiz kırmızı-siyah ağaç uygulamaları yoktur. Fraser ve Harris, işlemsel bellek tabanlı bir kırmızı-siyah ağacın nasıl uygulandığını ve performansını gösterir. İşlemsel bellek araştırma alanında hala çok fazla, bu nedenle üretim kodunda, kırmızı-siyah bir ağacın ağacın büyük bölümlerini kilitlemesi gerekiyor.
deft_code

4
@deft_code: Intel yakın zamanda Haswell'de TSX aracılığıyla İşlemsel Bellek uygulamasını duyurdu . Bu, bahsettiğiniz kilitsiz veri yapıları için ilginç olabilir.
Mike Bailey

2
Bence Fizz'in cevabı bu cevaptan (2012) daha güncel (2015'ten itibaren) ve bu nedenle şimdiye kadar tercih edilen cevap olmalı.
fnl

81

Birincisi, size en kötü garantileri veren rastgele bir veri yapısını oldukça karşılaştıramazsınız.

Atlama listesi, Dean ve Jones'un "Atlama Listeleri ile İkili Arama Ağaçları Arasındaki İkiliği Keşfetme" bölümünde daha ayrıntılı olarak açıklanan şekilde rastgele dengelenmiş bir ikili arama ağacına (RBST) eşdeğerdir .

Diğer taraftan, en kötü durum performansını garanti eden deterministik atlama listelerine de sahip olabilirsiniz, bkz. Munro ve diğ.

Yukarıda iddia edilenlerin aksine, eşzamanlı programlamada iyi çalışan ikili arama ağaçları (BST) uygulamalarınız olabilir. Eşzamanlılık odaklı BST'lerle ilgili potansiyel bir sorun, kırmızı-siyah (RB) bir ağaçtan alacağınız gibi dengeleme konusunda da aynı garantileri elde edemeyeceğinizdir. (Ancak "standart", yani rastgele bölmeli atlama listeleri de size bu garantileri vermez.) Dengeyi her zaman korumak ve iyi (ve programlaması kolay) eşzamanlı erişim arasında bir denge vardır, bu nedenle rahat RB ağaçları genellikle kullanılır iyi eşzamanlılık istendiğinde. Gevşeme, ağacı hemen dengelemekten ibarettir. Biraz tarihli (1998) bir araştırma için Hanke'nin “Eşzamanlı Kırmızı-Siyah Ağaç Algoritmalarının Performansı” na bakınız [ps.gz] .

Bunlar üzerindeki en son iyileştirmelerden biri, sözde kromatik ağaçtır (temelde siyahın 1 ve kırmızı sıfır olacak, ancak aradaki değerlere izin verecek şekilde bir ağırlığınız vardır). Ve kromatik ağaç atlama listesine göre nasıl ücretlendirilir? Bakalım Brown ve ark. "Tıkanmasız Ağaçlar İçin Genel Bir Teknik" (2014) şunları söylemek zorundadır:

128 iş parçacığına sahip algoritmamız, Java'nın engellemeyen atlama listesinin% 13 ila% 156 oranında olduğunu, Bronson ve ark. % 63 ila 224 arasında ve yazılım işlem belleği (STM) 13 ila 134 kat kullanan bir RBT

Eklemek için EDIT: Fraser ve Harris (2007) "Kilitsiz Eşzamanlı Programlama" kendi kilitsiz sürümüne yaklaşan (burada üst cevapta büyük ölçüde ısrar eden bir nokta ) olarak karşılaştırılan Pugh'un kilit tabanlı atlama listesi , aynı zamanda iyi eşzamanlı çalışma için ayarlanmıştır, bkz. Pugh'un "Atlamalı Listelerin Eşzamanlı Bakımı" oldukça hafif olmasına rağmen. Yine de bir yeni / 2009 makalesi "Basit Bir İyimser atlama listesi Algoritması"eşzamanlı atlama listelerinin sözde daha basit (Pugh'unkinden) kilit tabanlı bir uygulamasını öneren Herlihy ve ark., Pugh'u, onlar için yeterince ikna edici bir doğruluk kanıtı sunmadığı için eleştirdi. Bu (belki çok bilgiçlik) bir kenarı bırakarak, Herlihy ve ark. bir atlama listesinin daha basit kilit tabanlı uygulamasının aslında JDK'nın kilitsiz uygulamasının yanı sıra ölçeklendirilemediğini, ancak yalnızca yüksek çekişme (% 50 ekler,% 50 silme ve% 0 aramalar) için ... ve Harris hiç test etmedi; Fraser ve Harris sadece% 75 arama,% 12.5 ekleme ve% 12.5 silme işlemlerini test etti (atlama listesinde ~ 500K öğeleriyle). Herlihy ve ark. ayrıca test ettikleri düşük çekişme durumunda JDK'nın kilitsiz çözümüne yakın gelir (% 70 aramalar,% 20 ekler,% 10 silme); atlama listelerini yeterince büyük hale getirdiklerinde, yani herhangi bir kilide çekişme olasılığını ihmal edilebilir hale getirdiklerinde, bu senaryo için kilitsiz çözümü gerçekten yendiler. Herlihy ve ark. Pugh'un ispatı konusunda kararsız kaldıklarını ve uygulamalarını da test ettiler, ama bunu yapmadılar.

EDIT2: Ben tüm kıyaslamaların (2015 yayınlandı) bir analoğu buldum: Gramoli'nin "Senkronizasyon Hakkında Bilmek İstediğinizden Daha Fazlası .

resim açıklamasını buraya girin

"Algo.4", Brown ve arkadaşlarının yukarıda bahsedilen öncüsüdür (daha eski, 2011 versiyonu). (2014 versiyonunun ne kadar iyi veya kötü olduğunu bilmiyorum). "Algo.26", Herlihy'nin yukarıda zikredildiği; gördüğünüz gibi, güncellemelerde çöker ve burada kullanılan Intel CPU'larda orijinal kağıttan Sun CPU'lara göre çok daha kötüdür. "Algo.28", JDK'dan ConcurrentSkipListMap; diğer CAS tabanlı atlama listesi uygulamalarına kıyasla umduğu kadar iyi değildir. Yüksek çekişme altındaki kazananlar Crain ve ark. Tarafından tarif edilen kilit tabanlı bir algoritmadır (!!). içinde "A Çekişme Dostu İkili Arama Ağacı" ve "Algo.30" dan "dönen skiplist" dir "multicores için Logaritmik veri yapıları" . ". Gramoli'nin bu kazanan algoritma makalelerinin üçünün de ortak yazarı olduğu unutulmamalıdır. "Algo.27" Fraser'ın atlama listesinin C ++ uygulamasıdır.

Gramoli'nin sonucuna göre, CAS tabanlı bir eşzamanlı ağaç uygulamasını vidalamak, benzer bir atlama listesini vidalamaktan çok daha kolay. Rakamlara dayanarak, aynı fikirde olmak zor. Bu gerçeğe ilişkin açıklaması:

Kilitsiz bir ağaç tasarlamadaki zorluk, çoklu referansları atomik olarak değiştirme zorluğundan kaynaklanmaktadır. Atlama listeleri, ardıl işaretçiler aracılığıyla birbirine bağlanan ve her düğümün hemen altındaki düğüme işaret ettiği kulelerden oluşur. Çoğu zaman ağaçlara benzer olarak kabul edilirler, çünkü her bir düğümün ardıl kulede ardılı ve onun altında bir ardıl vardır, ancak önemli bir ayrım, aşağı doğru işaretçinin genellikle değişmez olması ve dolayısıyla bir düğümün atomik modifikasyonunu basitleştirmesidir. Bu ayrım muhtemelen atlama listelerinin, Şekil [yukarıda] 'da görüldüğü gibi ağır çekişme altındaki ağaçlardan daha iyi performans göstermesinin nedenidir.

Bu zorluğun üstesinden gelmek Brown ve arkadaşlarının son çalışmalarında önemli bir endişeydi. LLX / SCX adını verdikleri, (makine düzeyinde) CAS kullanılarak uygulanan, çoklu kayıt LL / SC bileşik "ilkelleri" oluşturma üzerine tamamen ayrı (2013) bir "Engellemeyen Veri Yapıları için Pragmatik Temel Öğeler" var. Brown ve diğ. Bu LLX / SCX yapı taşını 2014'te (ancak 2011'de değil) eşzamanlı ağaç uygulamasında kullanmıştır.

Belki de burada "sıcak nokta yok" / çekişme dostu (CF) atlama listesinin temel fikirlerini özetlemeye değer olduğunu düşünüyorum.. Rahat RB ağaçlarından (ve benzer eşzamanlı olarak kızarmış veri yapılarından) önemli bir fikri birleştirir: kuleler artık yerleştirildikten hemen sonra inşa edilmez, ancak daha az çekişme olana kadar ertelenir. Tersine, uzun bir kulenin silinmesi birçok çekişme yaratabilir; bu, Pugh'un 1990'da eşzamanlı atlama listesi kağıdına kadar gözlendi, bu yüzden Pugh, silme üzerine işaretçi tersini getirdi (ne yazık ki, atlama listelerindeki Wikipedia sayfasının hala bu güne değinmediği bir tidbit). CF atlama listesi bunu bir adım daha ileri götürür ve yüksek bir kulenin üst seviyelerinin silinmesini geciktirir. CF atlama listelerindeki her iki gecikmeli işlem, yazarlarının "uyarlama iş parçacığı" olarak adlandırdığı (CAS tabanlı) ayrı bir çöp toplayıcı benzeri iş parçacığı tarafından gerçekleştirilir.

Senkrobench kodu (test edilen tüm algoritmalar dahil) şu adreste bulunabilir: https://github.com/gramoli/synchrobench . En son Brown ve ark. uygulama (yukarıdakilere dahil değildir) http://www.cs.toronto.edu/~tabrown/chromatic/ConcurrentChromaticTreeMap.java adresinde bulunabilir 32'den fazla çekirdek makine var mı? J / K Demek istediğim bunları kendiniz çalıştırabilirsiniz.


12

Ayrıca, verilen cevaplara ek olarak (uygulama kolaylığı dengeli bir ağaca karşılaştırılabilir performansla birleştirilmiştir). Sırayla geçişin (ileri ve geri) uygulanmasının çok daha basit olduğunu düşünüyorum çünkü bir atlama listesinin etkili bir şekilde uygulama içinde bağlantılı bir listesi var.


1
bir bin ağacının sıralı olarak geçişi şu kadar basit değildir: "def func (düğüm): func (sol (düğüm)); op (düğüm); func (sağ (düğüm))"?
Claudiu

6
Tabii, hepsi tek bir işlev çağrısında dolaşmak istiyorsanız bu doğru. ancak std :: map'de olduğu gibi yineleyici stilinde geçiş yapmak istiyorsanız çok daha can sıkıcı olur.
Evan Teran

@Evan: CPS ile yazabileceğiniz işlevsel bir dilde değil.
Jon Harrop

@Evan: def iterate(node): for child in iterate(left(node)): yield child; yield node; for child in iterate(right(node)): yield child;? =). yerel olmayan kontrol iz awesom .. @Jon: CPS'de yazmak bir acıdır, ama belki devamlarla mı kastediyorsunuz? jeneratörler temel olarak python için devam eden özel bir durumdur.
Claudiu

1
@Evan: evet, düğüm parametresi bir değişiklik sırasında ağaçtan kesildiği sürece çalışır. C ++ geçişi aynı kısıtlamaya sahiptir.
deft_code

10

Uygulamada, projelerimdeki B-ağacı performansının atlama listelerinden daha iyi olduğu sonucuna vardım. Atlama listelerinin anlaşılması daha kolay gözükmektedir, ancak B-ağacını uygulamak o kadar da zor değildir .

Bildiğim bir avantaj, bazı zeki insanların sadece atomik işlemleri kullanan kilitsiz bir eşzamanlı atlama listesinin nasıl uygulanacağını bulmasıdır. Örneğin, Java 6 ConcurrentSkipListMap sınıfını içerir ve çılgınsanız kaynak kodunu okuyabilirsiniz.

Ama aynı anda bir B-ağacı varyantı yazmak çok zor değil - başka biri tarafından yapıldığını gördüm - eğer ağaçta yürürken düğümleri "her ihtimale karşı" önceden ayırır ve birleştirirseniz, çıkmazlar hakkında endişe ve bir kerede sadece ağacın iki düzeyde bir kilit tutmanız gerekir. Senkronizasyon yükü biraz daha yüksek olacak, ancak B-ağacı muhtemelen daha hızlı olacaktır.


4
Bence İkili Ağaca B-Ağacı
dememelisiniz

8

Gönderen Vikipedi makalesinde sen alıntı:

N (n) bizi her bir düğümü artan sırada ziyaret etmeye zorlayan işlemler (tüm listeyi yazdırmak gibi), atlama listesinin seviye yapısının sahne arkasında derandomizasyonunu en uygun şekilde gerçekleştirme fırsatı sağlar, atlama listesini O (log n) arama zamanına getirmek. [...] Yakın zamanda [böyle] Θ (n) işlemlerini yapmadığımız bir atlama listesi, daha geleneksel dengeli ağaç veri yapıları ile aynı mutlak en kötü durum performans garantisini sağlamaz , çünkü her zaman mümkündür (çok düşük bir olasılıkla), atlama listesini oluşturmak için kullanılan jetonların kötü dengelenmiş bir yapı üretmesi

EDIT: yani bir değiş tokuş: Atla Listeleri dengesiz bir ağaca dejenere olma riski altında daha az bellek kullanır.


bu atlama listesini kullanmaya karşı bir sebep olacaktır.
Claudiu

7
MSDN'den alıntılar, "[100 seviye 1 element için] şans, 1,267,650,600,228,229,401,496,703,205,376'da tam olarak 1'dir".
peterchen

8
Neden daha az bellek kullandıklarını söyledin?
Jonathan

1
@peterchen: Anlıyorum, teşekkürler. Peki bu deterministik atlama listelerinde gerçekleşmez mi? @Mitch: "Atla Listeleri daha az bellek kullanır". Atlama listeleri dengeli ikili ağaçlardan daha az bellek kullanır? Her düğümde ve yinelenen düğümlerde 4 işaretçi var gibi görünüyor, oysa ağaçlarda sadece 2 işaretçi var ve yineleme yok.
Jon Harrop

1
@Jon Harrop: Birinci seviyedeki düğümlerin düğüm başına yalnızca bir işaretçiye ihtiyacı vardır. Daha yüksek seviyelerdeki herhangi bir düğümün düğüm başına sadece iki işaretçi (bir sonraki düğüme bir ve onun altındaki seviyeye) ihtiyacı vardır, ancak elbette seviye 3 düğümü, bir değer için toplam 5 işaretçi kullandığınız anlamına gelir. Tabii ki, bu hala çok fazla bellek emecek (işe yaramayan bir atlama listesi istiyorsanız ve büyük bir veri kümesine sahipseniz ikili bir aramadan daha fazla moreso) ... ama sanırım bir şey eksik ...
Brian

2

Atlama listeleri listeler kullanılarak uygulanır.

Tek ve çift bağlantılı listeler için kilitsiz çözümler mevcuttur - ancak herhangi bir O (logn) veri yapısı için doğrudan CAS kullanan kilitsiz çözümler yoktur.

Ancak atlama listeleri oluşturmak için CAS tabanlı listeleri kullanabilirsiniz.

(CAS kullanılarak oluşturulan MCAS'ın rastgele veri yapılarına izin verdiğini ve MCAS kullanılarak kırmızı-siyah ağaç kavramının bir kanıtı oluşturulduğunu unutmayın).

Yani, onlar gibi garip, çok yararlı olduğu ortaya çıktı :-)


5
"Herhangi bir O (logn) veri yapısı için doğrudan CAS kullanan kilitsiz çözümler yoktur". Doğru değil. Karşı örnekler için bkz. Cl.cam.ac.uk/research/srg/netos/lock-free
Jon Harrop

-1

Listeleri Atla kilit sıyırma avantajına sahiptir. Ancak, çalışma süresi yeni bir düğüm seviyesinin nasıl belirlendiğine bağlıdır. Genellikle bu Random () kullanılarak yapılır. 56000 kelimelik bir sözlükte, atlama listesi bir yayvan ağacından daha uzun ve ağaç bir karma tablodan daha uzun sürdü. İlk ikisi karma tablonun çalışma zamanıyla eşleşemedi. Ayrıca, karma tablosunun dizisi eşzamanlı olarak da soyulmuş olabilir.

Atlama Listesi ve benzer sıralı listeler, referansın yeri gerektiğinde kullanılır. Örn: bir uygulamada bir tarihin öncesinde ve öncesinde uçuş bulma.

Hafızalı bir ikili arama yayılan ağaç harika ve daha sık kullanılır.

Skip List Vs Splay Tree Vs Hash Table Sözlükteki çalışma zamanı


Hızlıca baktım ve sonuçlarınız SkipList'i SplayTree'den daha hızlı gösteriyor.
Chinasaur

Atlama listesinin bir parçası olarak randomizasyonu varsaymak yanıltıcıdır. Elemanların nasıl atlandığı çok önemlidir. Olasılıksal yapılar için randomizasyon eklenir.
user568109
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.