- Rust’ın önde gelen rastgele sayı crate’i
rand, gündelik işlemleri birden fazla trait’e dağıttığı için; daha küçük bir açık/uygulama yüzeyi ve tutarlı bir kullanım deneyimi sunan urandom geliştirildi - Yüksek seviye işlemler tek bir
Randomyapısında toplandı veRngtrait’i mühürlenerek, rastgele üreteç desteğinden çok API keşfedilebilirliği ve iç optimizasyonlar önceliklendirildi - Yeni bir rastgele sayı algoritması eklemek yerine Xoshiro256’nın çıktı işlevleri kullanım amacına göre seçildi; 1.000 adet
f64üretim kıyaslamasındarand0.10.2’ye göre yaklaşık %31 daha yüksek throughput elde edildi - Eşit dağılımlı tamsayı örnekleme, eşik değerini gecikmeli hesaplayan tek bir önyargısız uygulama ile yeniden kullanım ve tek seferlik yolları birleştirdi;
500..20_000aralığı kıyaslamasındarand’in iki yolundan da daha hızlıydı - Açık seed ile ham çıktı, desteklenen mimariler ve SemVer uyumlu sürümler boyunca yeniden üretilebilirlik sağlar; ancak özel rastgele üreteç bağlama ile
rand’in geniş dağılım ve üçüncü taraf entegrasyon ekosisteminden vazgeçilir
Tek yerde toplanmış Random API’si
rand’in faydalı işlemleri birden fazla trait’e dağılmış durumda- Rastgele aralık üretimi için
RngExt, dizilerden seçim içinIndexedRandom, karıştırma içinSliceRandomgerekir rand0.10, tek seferlik çağrılar içinrand::random_rangegibi kök seviye yardımcılar sunar- Ancak bir RNG handle’ını elde tutmak ya da seçim/karıştırma gibi dizi işlemlerini kullanmak için hâlâ birden fazla trait’in metotlarını bulmanız gerekir
- Rastgele aralık üretimi için
- Prelude ile import sayısını azaltsanız bile, genişletme metotlarının RNG, slice veya iterator tiplerinden hangisine uygulandığını bilmeniz gerekir; bu yüzden yalnızca IDE otomatik tamamlama ile bulmak zordur
- urandom, yüksek seviye tüketici API’sini tek bir
Randomsarmalayıcı yapısı içinde toplarurandom::new()ileRandom<urandom::rng::Xoshiro256Rng>oluşturuluruniform,choose,shuffleaynı nesne üzerinden çağrılabilir- Otomatik tamamlamada
random,uniform,chance,choose,shuffle,samplegibi seçenekler görülebilir - Bunların hepsi özgün metotlardır; dolayısıyla yüksek seviye genişletme trait’lerini bulup import etmeniz gerekmez
Genişletilebilirlik yerine optimizasyonu seçen mühürlü Rng
rand, düşük seviye RNG trait’ini herkese açık bir genişletme noktası olarak ele alır; buna karşılıkurandom’dakiRngtrait’i mühürlüdür ve desteklenen üreteçler crate içinde seçilip uygulanır- İstediğiniz bir üreteci
Random’a bağlayamazsınız - Yeni bir üreteç eklemek için
urandom’ın kendisini değiştirmek gerekir
- İstediğiniz bir üreteci
- Amaç daha iyi bir algoritmaysa, Xoshiro256 ve ChaCha zaten bugün kendi rollerinde varsayılan tercih olarak yerleşmiş durumda ve öneriler de yavaş değişir
- Daha iyi bir seçenek ortaya çıkarsa, gelecekteki bir major sürümde benimsenebilir
- Başka projeler, programlama dilleri, eski algoritmalar, özel donanımlar veya yalnızca simülasyona yönelik üreteçlerle uyumluluk için yalnızca aynı üretece sahip olmak yetmez
- Eşit dağılımlı örnekleme ve karıştırma gibi ilgili algoritmaların da aynı olması gerekir; bu nedenle tüm sözleşmeyi uygulayan özel bir implementasyon daha uygundur
- Mühürlü trait sayesinde, bilinmeyen üreteçler ve istisna durumları için implementasyon sözleşmesi tasarlayıp belgelemeye gerek kalmadan
urandom’ın ihtiyaç duyduğu ham işlemler eklenebilir- Üreteçler ve algoritmalar birbirine göre özelleştirilebilir; böylece
rand’de mümkün olmayan bazı optimizasyonlar kullanılabilir
- Üreteçler ve algoritmalar birbirine göre özelleştirilebilir; böylece
- Çoğu uygulama için yeni bir PRNG implementasyonundan daha faydalı olan şey entropi seçimidir
- Somut üreteçler, yerel
from_seedkurucularını açık eder ChaCha12Rng::from_seed(seed)gibi açık seed kullanan birRandomoluşturabilirsiniz- Keyfi RNG implementasyonları kabul edilmez, ama ileri düzey kullanıcıların ihtiyaç duyacağı düşünülen genişletme noktaları korunur
- Somut üreteçler, yerel
Aynı algoritmadan gelen performans artışı
urandom, yeni bir rastgele sayı üretim algoritması kullanmaz- 64 bit sistemlerde, kriptografik olmayan kullanım için
urandom::new()ilerand::rngs::SmallRngaynı Xoshiro256 ailesini kullanır - Kriptografik kullanım için
urandom::csprng()ilerand::rngs::StdRng, ChaCha12 kullanır - Yardımcı işlev
rand::rng()de içeride ChaCha12 kullanır
- 64 bit sistemlerde, kriptografik olmayan kullanım için
rand’in üreteç arayüzü, tamsayı word’leri ve bayt doldurmayı sağlar; bu yüzdenf64gerektiren dağılımlar bile tam biru64isterurandom::Rng,next_u32venext_u64’ün yanı sıranext_f32venext_f64de sağlar- Kayan noktalı rastgele sayılar, tam bir word’den daha az rastgele bit gerektirir
- Üreteçler bu metotları daha ucuz çıktı işlevleriyle override edebilir
- Xoshiro implementasyonu, durum geçişini paylaşırken çıktı yollarını ayırır
u64için Xoshiro256++ korunuru32ve kayan nokta için, üst bitleri bu kullanım amaçlarına uygun tasarlanmış daha hızlı Xoshiro256+ kullanılır
urandom1.0 verand0.10.2 ile sırasıyla 1.000 rastgele sayı üreten mikro kıyaslamaların sonuçları şöyleydi- Xoshiro
u64: her iki tarafta da 814ns - Xoshiro
u32:rand836ns,urandom788ns - Xoshiro
f64:rand1,033ns,urandom788ns - ChaCha12
f64:rand2,199ns,urandom2,011ns
- Xoshiro
- Xoshiro
f64için uçtan uca throughput yaklaşık %31 daha yüksek, çalışma süresi ise %24 daha kısaydı; ancak aynı işi yapanu64yolu pratikte başa baştı - ChaCha12,
next_f64’ü override etmediği için performans büyük ölçüde benzerdir - Kesin süreler makineye ve derleyiciye göre değişir; ayrıntılı koşullar için tam benchmark notlarına bakılabilir
Tekleştirilmiş eşit dağılımlı örnekleme yolu
- Tamsayıları aralık uzunluğuna göre basitçe mod almak önyargı üretir; bu yüzden doğru eşit dağılımlı tamsayı örnekleme, üreteç çıktısının bir kısmını reddetmelidir
- Doğru reddetme eşiğini hesaplamak, maliyetli bir mod işlemi gerektirir
- Örnekleyici tekrar tekrar kullanılacaksa bu, başlangıç kurulum maliyeti olarak tolere edilebilir
- Yalnızca tek bir değer üretildiğinde ise bu maliyet görece büyür
rand, bu farkıUniformSamplertrait’i üzerinden açığa çıkarır- Oluşturulan
UniformInt, eşiği önceden hesaplayarak önyargısız örnekleme yapar Rng::random_range, kurulum maliyetinden kaçınmak için ayrısample_singleveyasample_single_inclusivehook’larını kullanır- Varsayılan özelliklerde tek seferlik kısa yol, biraz önyargılı ikinci bir algoritma kullanır
- İsteğe bağlı
unbiasedözelliği bunu daha karmaşık yinelemeli bir sürümle değiştirir
- Oluşturulan
urandom, eşiği gecikmeli hesaplayarak hem yeniden kullanım hem de tek seferlik aralıklar için tek bir önyargısız çarpma-reddetme implementasyonu kullanır- Daniel Lemire’in 2018 tarihli Fast Random Integer Generation in an Interval makalesinde anlatılan yaklaşımı izler
- Pratikteki çoğu aralıkta ilk aday, bölme işleminden önce döndürülür
- İlk aday döndürülemiyorsa, doğru eşik hesaplanır ve ardından önyargısız biçimde yineleme yapılır
- Tüm aralığın istendiği
range == 0istisnası da ele alınır
- Ayrı bir metot, ikinci bir algoritma, ön kurulum maliyeti veya önyargılı hızlı yol olmadan; aynı implementasyon hem yeniden kullanılan dağılımları hem de tek seferlik aralıkları işler
500..20_000aralığında 1.000 örnek çeken benchmark sonuçları şöyleydi- Yeniden kullanılan
UniformInt:rand1,098ns,urandom950ns - Tek seferlik aralık:
rand1,079ns,urandom942ns
- Yeniden kullanılan
randsonuçları varsayılan özelliklere göredir; bu yüzden daha hızlı tek seferlik satır hafif önyargılı yolu kullanırken,urandomönyargısız durumda her iki yoldan da daha hızlıydı
Sürümler ve mimariler arasında yeniden üretilebilirlik
urandom, yeniden üretilebilirliği kamusal sözleşmenin bir parçası olarak görür- Aynı açık seed ve aynı düşük seviye RNG çağrı sırası verildiğinde, deterministik üreteçlerin ham çıktısı korunur
- Desteklenen mimariler ve SemVer uyumlu sürümler boyunca kararlılık garanti edilir
- 64 bit bir sunucu ile 32 bit WebAssembly istemcisi, replay için aynı üreteç tabanını kullanabilir
- Bu uyumluluğu korumak için 32 bit mimarilerde performanstan ödün verilir
- Bu,
rand’in yeniden üretilebilirlik politikasından daha güçlü bir garantidirrand’in taşınabilir üreteçleri ve örnekleme algoritmaları, minor sürümlerde farklı çıktı verebilirSmallRngveStdRngaçıkça taşınabilir değildir; platforma veya kütüphane sürümüne göre de değişebilir
Tercihin bedeli ve hangi durumda uygun olduğu
urandom, genel işlemleriRandomiçinde toplayarak genişletme trait’leri olmadan kolayca bulunabilir hâle getirir- Üreteçler ve dağılımlar birlikte tasarlanarak daha ucuz Xoshiro çıktı yolları ve tek bir önyargısız eşit dağılımlı örnekleme yolu uygulanır
- Açık seed ile başlatılan üreteçlerin kararlı ham akışı, deterministik oyunlar ve simülasyonlar için kullanılabilir
- Buna karşılık, keyfi üreteçler içe aktarılamaz; ayrıca
rand’in sunduğu daha geniş dağılım listesi ve üçüncü taraf entegrasyon ekosistemi de yoktur - Geniş bir ekosistem gerekiyorsa
randdaha uygundur; daha küçük API yüzeyi, keşfedilebilirlik, bütünleşik optimizasyonlar ve güçlü yeniden üretilebilirlik politikasını tercih ediyorsanızurandomseçilebilir - Pakete crates.io, API belgeleri ve GitHub kaynak kodu üzerinden ulaşılabilir
1 yorum
Lobste.rs yorumları
randi fork etmek için yeterince neden var, ancakurandomadı/dev/urandomile ilgili bir kütüphane gibi duyuluyorSorunun farkındalığına katılıyorum, ama
pub fn new() -> Random<impl Rng + Clone>hoşuma gitmiyorTüm uygulamayı
Random<T> where T: Rngile parametrelemek zahmetli işleri artırır; derleme süresi vedynile ilgili sorunlar ciddileşir. Bunun yerinestruct Randomın somut bir tipe sahip olmasını, ya da ikinci seçenek olarakstruct Random<T = rng::Xoshiro256Rng>ı tercih ederdimBenzer bir sıkıntı yüzünden ben de daha önce kendim bir şey yapmıştım; ancak bu bir fork değil ve
randden çok daha az işlev sunuyorBenimle aynı sorunu hisseden birinin gerçekten çözüm üretmeye girişmesine sevindim. Rust’ta tuhaf biçimde trait çorbası kütüphaneleri yazdıran bir eğilim var gibi
İşte kullandığım veritabanının çekirdek veri türlerinin en az 15 trait uygulaması gerekiyor; bu yüzden otomatik tamamlama berbat, dokümantasyon da kafa karıştırıcı. Trait sayısını biraz azalttık ama sık sık döngüsel bağımlılıklar ya da çekirdek testleri yazamama gibi sorunlara takılıyoruz
Bu kütüphane bana hem APOSD’nin derin arayüzlerini hem de Filippo’nun hata yapmayı zorlaştıracak şekilde tasarlanmış kriptografi çalışmalarını hatırlatıyor; ikisi de büyük övgü
urandom::new()kriptografik olarak güvenli bir rastgele sayı üreteci döndürmediği için tasarım tamamen hataya kapalı değil. Özellikle Linux’taki/dev/urandomgüvenli olduğundan bu daha da kafa karıştırıcıBir başka
randalternatifi olarak basit ve hızlı bir rastgele sayı üreteci olanfastrandvar.randveurandomdan daha basit, ama daha az özellik sunuyor