Saya baru-baru ini menemukan struktur data yang dikenal sebagai daftar lewati . Tampaknya memiliki perilaku yang sangat mirip dengan pohon pencarian biner.
Mengapa Anda ingin menggunakan daftar lompatan di atas pohon pencarian biner?
Saya baru-baru ini menemukan struktur data yang dikenal sebagai daftar lewati . Tampaknya memiliki perilaku yang sangat mirip dengan pohon pencarian biner.
Mengapa Anda ingin menggunakan daftar lompatan di atas pohon pencarian biner?
Abaikan daftar lebih dapat menerima akses / modifikasi bersamaan. Herb Sutter menulis artikel tentang struktur data di lingkungan bersamaan. Ini memiliki informasi yang lebih mendalam.
Implementasi pohon pencarian biner yang paling sering digunakan adalah pohon merah-hitam . Masalah-masalah bersamaan muncul ketika pohon dimodifikasi, seringkali perlu menyeimbangkan kembali. Operasi penyeimbangan kembali dapat memengaruhi sebagian besar pohon, yang akan membutuhkan kunci mutex pada banyak simpul pohon. Memasukkan sebuah simpul ke daftar lewati jauh lebih terlokalisasi, hanya simpul yang terhubung langsung ke simpul yang terpengaruh perlu dikunci.
Pembaruan dari komentar Jon Harrops
Saya membaca tulisan Fraser dan Harris, pemrograman bersamaan tanpa kunci . Hal yang sangat bagus jika Anda tertarik pada struktur data bebas kunci. Makalah ini berfokus pada Memori Transaksional dan operasi teoretis multi-kata-bandingkan-dan-swap MCAS. Keduanya disimulasikan dalam perangkat lunak karena belum ada perangkat keras yang mendukungnya. Saya cukup terkesan bahwa mereka mampu membangun MCAS dalam perangkat lunak sama sekali.
Saya tidak menemukan hal-hal memori transaksional sangat menarik karena memerlukan pengumpul sampah. Juga memori transaksional perangkat lunak terganggu dengan masalah kinerja. Namun, saya akan sangat senang jika memori transaksional perangkat keras menjadi hal biasa. Pada akhirnya ini masih penelitian dan tidak akan digunakan untuk kode produksi selama satu dekade atau lebih.
Pada bagian 8.2 mereka membandingkan kinerja beberapa implementasi pohon konkuren. Saya akan meringkas temuan mereka. Layak untuk mengunduh pdf karena memiliki beberapa grafik yang sangat informatif di halaman 50, 53, dan 54.
Pembaruan
Berikut adalah kertas tentang pohon bebas-kunci: Pohon Merah-Hitam Bebas-Kunci Menggunakan CAS .
Saya belum melihat ke dalamnya, tetapi di permukaan tampak padat.
Pertama, Anda tidak dapat secara adil membandingkan struktur data acak dengan yang memberikan Anda jaminan terburuk.
Daftar lompatan setara dengan pohon pencarian biner acak seimbang (RBST) dengan cara yang dijelaskan secara lebih rinci di Dean dan Jones ' "Menjelajahi Dualitas Antara Daftar Lewati dan Pohon Pencarian Biner" .
Sebaliknya, Anda juga dapat memiliki daftar lompatan deterministik yang menjamin kinerja kasus terburuk, lih. Munro et al.
Berbeda dengan beberapa klaim di atas, Anda dapat memiliki implementasi pohon pencarian biner (BST) yang bekerja dengan baik dalam pemrograman bersamaan. Masalah potensial dengan BST yang berfokus pada konkurensi adalah Anda tidak dapat dengan mudah mendapatkan jaminan yang sama tentang keseimbangan seperti yang Anda lakukan dari pohon merah-hitam (RB). (Tapi "standar", yaitu randomzided, lewati daftar juga tidak memberi Anda jaminan ini.) Ada pertukaran antara mempertahankan keseimbangan setiap saat dan akses yang baik (dan mudah diprogram), sehingga pohon RB yang santai biasanya digunakan ketika konkurensi yang baik diinginkan. Relaksasi terdiri dari tidak menyeimbangkan pohon segera. Untuk survei yang agak bertanggal (1998) lihat Hanke's '' The Performance of Algoritma Pohon Merah-Hitam bersamaan '' [ps.gz] .
Salah satu peningkatan terbaru pada hal ini adalah apa yang disebut pohon kromatik (pada dasarnya Anda memiliki beberapa bobot sehingga hitam akan menjadi 1 dan merah akan menjadi nol, tetapi Anda juga membiarkan nilai di antaranya). Dan bagaimana pohon berwarna berubah terhadap daftar lompatan? Mari kita lihat apa yang Brown dkk. "Teknik Umum untuk Pohon Tanpa Pemblokiran" (2014) harus mengatakan:
EDIT menambahkan: daftar lompatan berbasis kunci Pugh, yang diperbandingkan dalam Fraser dan Harris (2007) "Pemrograman Bersamaan Tanpa Kunci" mendekati versi bebas kunci mereka sendiri (satu poin yang ditekankan dalam jawaban teratas di sini), juga di-tweak untuk operasi bersamaan yang baik, lih. "Pemeliharaan Serentak dari Daftar Lewati" Pugh , meskipun dengan cara yang agak ringan. Namun demikian, satu makalah yang lebih baru / 2009 "Algoritma daftar sederhana Optimisme"oleh Herlihy et al., yang mengusulkan implementasi berbasis kunci yang seharusnya lebih sederhana (daripada Pugh) dari daftar lompatan bersamaan, mengkritik Pugh karena tidak memberikan bukti kebenaran yang cukup meyakinkan bagi mereka. Mengesampingkan keraguan ini (mungkin terlalu berlebihan), Herlihy et al. menunjukkan bahwa penerapan daftar loncatan berbasis penguncian yang lebih sederhana sebenarnya gagal untuk menskalakan serta penerapan JDK yang bebas penguncian daripadanya, tetapi hanya untuk pertengkaran tinggi (50% sisipan, 50% penghapusan dan pencarian 0%) ... yang Fraser dan Harris tidak menguji sama sekali; Fraser dan Harris hanya menguji pencarian 75%, sisipan 12,5% dan penghapusan 12,5% (pada daftar lompatan dengan ~ 500K elemen). Implementasi yang lebih sederhana dari Herlihy et al. juga mendekati solusi bebas-kunci dari JDK dalam kasus pertikaian rendah yang mereka uji (70% pencarian, 20% sisipan, 10% dihapus); mereka benar-benar mengalahkan solusi bebas kunci untuk skenario ini ketika mereka membuat daftar lompatan mereka cukup besar, yaitu pergi dari elemen 200K ke 2M, sehingga kemungkinan pertikaian pada kunci apa pun menjadi diabaikan. Akan lebih baik jika Herlihy et al. telah melupakan hangus mereka atas bukti Pugh dan menguji implementasinya juga, tetapi sayangnya mereka tidak melakukan itu.
EDIT2: Saya menemukan (2015 diterbitkan) motherlode dari semua tolok ukur: Gramoli's "Lebih Dari Yang Pernah Ingin Anda Ketahui tentang Sinkronisasi. Synchrobench, Mengukur Dampak Sinkronisasi pada Algoritma Bersamaan" : Berikut adalah gambar kutipan yang relevan dengan pertanyaan ini.
"Algo.4" adalah prekursor (versi lama, 2011) dari Brown et al. Yang disebutkan di atas. (Saya tidak tahu seberapa baik atau buruk versi 2014). "Algo.26" adalah Herlihy yang disebutkan di atas; seperti yang Anda lihat akan dibuang pada pembaruan, dan jauh lebih buruk pada CPU Intel yang digunakan di sini daripada pada CPU Sun dari kertas asli. "Algo.28" adalah ConcurrentSkipListMap dari JDK; itu tidak berhasil sebaik yang diharapkan dibandingkan dengan implementasi daftar lewati berbasis CAS lainnya. Pemenang di bawah pertentangan tinggi adalah "Algo.2" algoritma berbasis kunci (!!) yang dijelaskan oleh Crain et al. di "Pohon Pencarian Biner Ramah-Contention" dan "Algo.30" adalah "daftar putar berputar" dari "struktur data Logaritmik untuk multicores" . ". Maklum bahwa Gramoli adalah penulis bersama untuk ketiga makalah algoritma pemenang ini. "Algo.27" adalah implementasi C ++ dari daftar lompatan Fraser.
Kesimpulan Gramoli adalah bahwa jauh lebih mudah untuk mengacaukan implementasi pohon konkuren berbasis-CAS daripada mengacaukan daftar lompatan yang sama. Dan berdasarkan angka-angka, sulit untuk tidak setuju. Penjelasannya untuk fakta ini adalah:
Mengatasi kesulitan ini adalah masalah utama dalam karya Brown et al. Mereka memiliki seluruh kertas (2013) terpisah "Pragmatis Primitif untuk Non-blocking Data Structures" untuk membangun multi-record senyawa LL / SC "primitif", yang mereka sebut LLX / SCX, yang diimplementasikan sendiri menggunakan CAS (level mesin). Brown et al. menggunakan blok bangunan LLX / SCX ini pada 2014 mereka (tetapi tidak pada 2011 mereka) implementasi pohon bersamaan.
Saya pikir mungkin juga layak untuk merangkum di sini ide-ide mendasar dari daftar lompatan "no hot spot" / friendly-contention (CF). Ini menambah ide penting dari pohon RB yang rileks (dan struktur data friedrrrency serupa): menara tidak lagi dibangun segera setelah dimasukkan, tetapi ditunda sampai ada sedikit pertengkaran. Sebaliknya, penghapusan menara tinggi dapat menciptakan banyak pertengkaran; ini diamati sejauh kertas loncatan daftar Pugh 1990 bersamaan, itulah sebabnya Pugh memperkenalkan pembalikan pointer pada penghapusan (sebuah berita gembira bahwa halaman Wikipedia pada daftar lompatan masih tidak disebutkan sampai hari ini, sayangnya). Daftar lompatan CF mengambil langkah lebih jauh dan menunda menghapus tingkat atas menara tinggi. Kedua jenis operasi yang tertunda dalam daftar lompatan CF dilakukan oleh utas pengumpul sampah yang terpisah (berbasis CAS), yang oleh penulisnya disebut "utas pengadaptasi".
Kode Synchrobench (termasuk semua algoritma yang diuji) tersedia di: https://github.com/gramoli/synchrobench . Brown et al terbaru. implementasi (tidak termasuk dalam hal di atas) tersedia di http://www.cs.toronto.edu/~tabrown/chromatic/ConcurrentChromaticTreeMap.java Apakah ada yang punya mesin inti 32+ yang tersedia? J / K Maksud saya adalah bahwa Anda dapat menjalankan ini sendiri.
sumber
Juga, selain jawaban yang diberikan (kemudahan implementasi dikombinasikan dengan kinerja yang sebanding dengan pohon seimbang). Saya menemukan bahwa mengimplementasikan in-order traversal (maju dan mundur) jauh lebih sederhana karena daftar-lompatan secara efektif memiliki daftar tertaut di dalam implementasinya.
sumber
def iterate(node): for child in iterate(left(node)): yield child; yield node; for child in iterate(right(node)): yield child;
? =). kontrol non-lokal dan awesom .. @ Jon: menulis di CPS itu menyebalkan, tapi mungkin Anda maksud dengan kelanjutan? generator pada dasarnya adalah kasus khusus kelanjutan untuk python.Dalam praktiknya saya telah menemukan bahwa kinerja B-tree pada proyek saya telah bekerja lebih baik daripada melewatkan daftar. Melewati daftar memang tampak lebih mudah dipahami tetapi menerapkan B-tree tidak terlalu sulit.
Satu keuntungan yang saya tahu adalah bahwa beberapa orang pintar telah bekerja bagaimana menerapkan daftar lompatan bersamaan bebas-penguncian yang hanya menggunakan operasi atom. Misalnya, Java 6 berisi kelas ConcurrentSkipListMap, dan Anda dapat membaca kode sumbernya jika Anda gila.
Tetapi tidak terlalu sulit untuk menulis varian B-tree bersamaan - Saya pernah melihatnya dilakukan oleh orang lain - jika Anda terlebih dahulu membelah dan menggabungkan node "berjaga-jaga" saat Anda berjalan turun pohon maka Anda tidak perlu khawatir tentang kebuntuan dan hanya perlu memegang kunci pada dua tingkat pohon sekaligus. Sinkronisasi overhead akan sedikit lebih tinggi tetapi B-tree mungkin lebih cepat.
sumber
Dari artikel Wikipedia yang Anda kutip:
EDIT: jadi ini trade-off: Daftar Lewati menggunakan lebih sedikit memori dengan risiko bahwa mereka mungkin berubah menjadi pohon yang tidak seimbang.
sumber
Abaikan daftar diimplementasikan menggunakan daftar.
Solusi bebas kunci ada untuk daftar yang ditautkan secara tunggal dan ganda - tetapi tidak ada solusi bebas kunci yang langsung menggunakan hanya CAS untuk setiap struktur data O (logn).
Namun Anda dapat menggunakan daftar berbasis CAS untuk membuat daftar lewati.
(Perhatikan bahwa MCAS, yang dibuat menggunakan CAS, memungkinkan struktur data sewenang-wenang dan bukti konsep pohon merah-hitam telah dibuat menggunakan MCAS).
Jadi, anehnya, mereka ternyata sangat berguna :-)
sumber
Abaikan Daftar memang memiliki keuntungan dari pengupasan kunci. Tapi, waktu runtuhnya tergantung pada bagaimana tingkat node baru diputuskan. Biasanya ini dilakukan dengan menggunakan Random (). Pada kamus yang berisi 56.000 kata, daftar lompatan membutuhkan waktu lebih lama daripada pohon rentang dan pohon lebih banyak waktu daripada tabel hash. Dua yang pertama tidak dapat mencocokkan runtime tabel hash. Juga, array dari tabel hash dapat dikunci secara bersamaan juga.
Abaikan Daftar dan daftar berurutan serupa digunakan ketika lokalitas referensi diperlukan. Misalnya: mencari penerbangan berikutnya dan sebelum tanggal dalam aplikasi.
Pohon splay pencarian biner inemem hebat dan lebih sering digunakan.
Lewati Daftar Vs Splay Tree Vs Hash Table Runtime di kamus find op
sumber