Bu uzun bir metindir. Lütfen bana eşlik et. Haşlanmış soru şu: Çalışılabilir bir yerinde radyant sıralama algoritması var mı?
Ön hazırlık
Sıralamak istediğim sadece “A”, “C”, “G” ve “T” harflerini kullanan çok sayıda sabit uzunluklu dizgim var (evet, tahmin ettiniz: DNA ).
Şu anda kullandığım std::sort
kullandığı içgözlemle sıralama tüm ortak uygulamalarda STL . Bu gayet iyi çalışıyor. Ancak, sayı tabanı sıralamasının sorun kümeme mükemmel bir şekilde uyduğuna ve uygulamada daha iyi çalışması gerektiğine inanıyorum .
ayrıntılar
Bu varsayımı çok naif bir uygulama ile test ettim ve nispeten küçük girdiler için (10.000 civarında) bu doğruydu (en az iki kat daha hızlı). Ancak, sorun boyutu büyüdüğünde ( N > 5.000.000) çalışma zamanı uçuruma uğrar .
Nedeni açıktır: sayı tabanı sıralaması tüm verilerin kopyalanmasını gerektirir (aslında benim naif uygulamamda birden fazla). Bu, ~ 4 GiB'yi ana belleğime koyduğum anlamına geliyor ve bu da performansı öldürüyor. Olmasa bile, sorun büyüklükleri daha da büyüdüğü için bu kadar belleği kullanamıyorum.
Kullanım Örnekleri
İdeal olarak, bu algoritma DNA ve DNA5 (ek bir joker karakter “N” karakterine izin verir) ve hatta IUPAC belirsizlik kodlu DNA (16 farklı değerle sonuçlanır ) için 2 ile 100 arasında herhangi bir dize uzunluğu ile çalışmalıdır . Ancak, tüm bu vakaların karşılanamayacağının farkındayım, bu yüzden aldığım herhangi bir hız iyileştirmesinden memnunum. Kod, hangi algoritmanın gönderileceğine dinamik olarak karar verebilir.
Araştırma
Ne yazık ki, sayı tabanı sıralaması hakkındaki Wikipedia makalesi işe yaramaz. Yerinde bir varyant ile ilgili bölüm tam bir çöptür. Radix üzerine NIST-BABALAR bölüm biraz varolmayan yanındadır. “MSL” algoritmasını açıklayan Efficient Adaptive In-Place Radix Sorting adında gelecek vaat eden bir kağıt var . Ne yazık ki, bu yazı da hayal kırıklığı yaratıyor.
Özellikle, aşağıdaki şeyler vardır.
İlk olarak, algoritma birkaç hata içeriyor ve çok fazla açıklanmıyor. Özellikle, özyineleme çağrısını ayrıntılandırmaz (sadece geçerli kaydırma ve maske değerlerini hesaplamak için bazı işaretçiyi arttırdığını veya azalttığını varsayıyorum). Ayrıca, işlevlerini kullanır dest_group
ve dest_address
tanımları vermeden. Bunların verimli bir şekilde nasıl uygulanacağını göremiyorum (yani O (1); en azından dest_address
önemsiz değil).
Sonuncu fakat son derece önemli olarak, algoritma dizi indekslerini girdi dizisinin içindeki elemanlarla değiştirerek yerinde gerçekleşir. Bu sadece sayısal dizilerde işe yarar. Dizelerde kullanmam gerekiyor. Tabii ki, güçlü yazmayı vidalayabilirim ve hafızanın ait olmadığı bir dizini depolamamı tolere edeceğini varsayarak devam edebilirim. Ancak bu sadece dizelerimi 32 bit belleğe sıkıştırabildiğim sürece çalışır (32 bit tamsayı varsayarak). Bu sadece 16 karakterdir (16> günlüğü (5.000.000) olduğu için yok sayalım).
Yazarlardan birinin başka bir makalesinde kesin bir açıklama yoktur, ancak MSL'nin çalışma zamanını alt doğrusal olarak verir ve bu da yanlıştır.
Özetlemek gerekirse : DNA dizeleri üzerinde çalışan bir çalışma referans uygulaması veya en azından iyi bir sözde kod / çalışan yerinde bir sayı tabanı açıklaması bulma umudu var mı?