- Crate angka acak utama Rust,
rand, menyebarkan operasi sehari-hari ke banyak trait, sehingga dikembangkan urandom dengan permukaan publik dan implementasi yang lebih kecil serta pengalaman penggunaan yang konsisten - Operasi tingkat tinggi dikumpulkan ke dalam satu struktur
Randomdan traitRngdisegel, sehingga kemudahan menemukan API dan optimasi internal diprioritaskan daripada dukungan generator acak sembarang - Tanpa memperkenalkan algoritme angka acak baru, fungsi output Xoshiro256 dipilih sesuai penggunaan, dan pada benchmark pembuatan 1.000
f64tercatat throughput sekitar 31% lebih tinggi dibandingrand0.10.2 - Sampling integer uniform menyatukan jalur yang dapat dipakai ulang dan sekali pakai dengan satu implementasi tak bias yang menghitung ambang secara tertunda, dan pada benchmark rentang
500..20_000lebih cepat daripada dua jalur milikrand - Output mentah dengan seed eksplisit menjamin reproduktibilitas di arsitektur yang didukung dan rilis kompatibel SemVer, tetapi penyambungan generator acak sembarang serta ekosistem distribusi dan integrasi pihak ketiga
randyang luas harus dikorbankan
API Random yang disatukan
- Operasi berguna di
randtersebar di beberapa trait- Untuk membuat angka acak dalam rentang diperlukan
RngExt, untuk memilih dari sekuens diperlukanIndexedRandom, dan untuk mengacak diperlukanSliceRandom rand0.10 menyediakan helper level-root sepertirand::random_rangeuntuk pemanggilan sekali pakai- Namun jika ingin mempertahankan handle RNG atau memakai operasi sekuens seperti memilih dan mengacak, Anda tetap harus mencari metode di beberapa trait
- Untuk membuat angka acak dalam rentang diperlukan
- Sekalipun impor dikurangi dengan prelude, Anda tetap harus tahu extension method itu berlaku pada tipe RNG, slice, atau iterator, sehingga sulit ditemukan hanya lewat autocomplete IDE
- urandom menempatkan API konsumen tingkat tinggi ke dalam satu struktur pembungkus
Randomurandom::new()membuatRandom<urandom::rng::Xoshiro256Rng>uniform,choose, danshuffledapat dipanggil dari objek yang sama- Lewat autocomplete Anda bisa melihat
random,uniform,chance,choose,shuffle,sample, dan lainnya - Semuanya adalah metode inheren, jadi tidak perlu mencari atau mengimpor trait ekstensi tingkat tinggi
Rng tersegel yang memilih optimasi dibanding ekstensibilitas
randmemperlakukan trait RNG tingkat rendah sebagai titik ekstensi publik, tetapi traitRngdiurandomdisegel, sehingga generator yang didukung dipilih dan diimplementasikan di dalam crate- Generator acak sembarang tidak bisa disambungkan ke
Random - Untuk menambahkan generator baru,
urandomsendiri harus diubah
- Generator acak sembarang tidak bisa disambungkan ke
- Jika tujuannya adalah algoritme yang lebih baik, saat ini Xoshiro256 dan ChaCha sudah mapan sebagai pilihan baku untuk peran masing-masing, dan rekomendasinya juga berubah secara lambat
- Jika ada pilihan yang lebih baik, itu bisa diadopsi pada rilis mayor mendatang
- Untuk kompatibilitas dengan proyek lain, bahasa pemrograman lain, algoritme lama, perangkat keras khusus, atau generator khusus simulasi, generator yang sama saja tidak cukup
- Algoritme terkait seperti sampling uniform dan pengacakan juga harus sama, jadi implementasi khusus yang mewujudkan seluruh kontrak lebih cocok
- Berkat trait yang disegel,
urandomhanya perlu menambahkan operasi mentah yang memang dibutuhkan, tanpa harus merancang dan mendokumentasikan kontrak implementasi untuk generator tak dikenal dan berbagai kondisi pengecualian- Generator dan algoritme bisa dispesialisasikan agar saling cocok, sehingga memungkinkan beberapa optimasi yang tidak dapat digunakan di
rand
- Generator dan algoritme bisa dispesialisasikan agar saling cocok, sehingga memungkinkan beberapa optimasi yang tidak dapat digunakan di
- Untuk sebagian besar aplikasi, pemilihan entropi lebih berguna daripada implementasi PRNG baru
- Generator konkret mengekspos konstruktor native
from_seed - Anda bisa membuat
Randomdengan seed eksplisit sepertiChaCha12Rng::from_seed(seed) - Meskipun tidak menerima implementasi RNG sembarang, titik ekstensi yang kemungkinan dibutuhkan pengguna tingkat lanjut tetap dipertahankan
- Generator konkret mengekspos konstruktor native
Peningkatan performa dari algoritme yang sama
urandomtidak memakai algoritme pembangkit angka acak yang baru- Pada sistem 64-bit,
urandom::new()untuk penggunaan non-kriptografis danrand::rngs::SmallRngsama-sama memakai keluarga Xoshiro256 - Untuk penggunaan kriptografis,
urandom::csprng()danrand::rngs::StdRngmemakai ChaCha12 - Generator internal dari fungsi praktis
rand::rng()juga ChaCha12
- Pada sistem 64-bit,
- Antarmuka generator
randmenyediakan word integer dan pengisian byte, sehingga distribusi yang membutuhkanf64pun meminta mulai dariu64penuh urandom::Rngmenyediakan bukan hanyanext_u32dannext_u64, tetapi juganext_f32dannext_f64- Angka acak floating-point membutuhkan lebih sedikit bit acak daripada satu word penuh
- Generator dapat menimpa metode-metode ini dengan fungsi output yang lebih murah
- Implementasi Xoshiro memisahkan jalur output sambil berbagi transisi state
- Untuk
u64, tetap memakai Xoshiro256++ - Untuk
u32dan floating-point, dipakai Xoshiro256+ yang lebih cepat, dengan bit atas yang dirancang untuk penggunaan tersebut
- Untuk
- Hasil microbenchmark pembuatan masing-masing 1.000 angka acak dengan
urandom1.0 danrand0.10.2 adalah sebagai berikut- Xoshiro
u64: keduanya 814ns - Xoshiro
u32:rand836ns,urandom788ns - Xoshiro
f64:rand1,033ns,urandom788ns - ChaCha12
f64:rand2,199ns,urandom2,011ns
- Xoshiro
- Throughput end-to-end untuk Xoshiro
f64sekitar 31% lebih tinggi dan waktu eksekusinya 24% lebih singkat, tetapi jaluru64yang melakukan pekerjaan serupa pada dasarnya imbang - Karena ChaCha12 tidak menimpa
next_f64, performanya secara umum mirip - Waktu pastinya bergantung pada mesin dan compiler, dan syarat detailnya dapat dilihat di catatan benchmark lengkap
Jalur sampling uniform yang disatukan
- Jika integer dipetakan ke panjang rentang hanya dengan operasi sisa sederhana, akan timbul bias, sehingga sampling integer uniform yang benar harus menolak sebagian output generator
- Menghitung ambang penolakan yang tepat membutuhkan operasi sisa yang mahal
- Jika sampler dipakai berulang kali, ini bisa ditanggung sebagai biaya setup awal
- Jika hanya membuat satu nilai, biaya ini menjadi relatif besar
randmengekspos perbedaan ini lewat traitUniformSamplerUniformIntyang dibuat akan menghitung ambang lebih dulu lalu mengambil sampel tanpa biasRng::random_rangememakai hooksample_singleatausample_single_inclusiveterpisah untuk menghindari setup awal- Dalam fitur default, jalur singkat sekali pakai memakai algoritme kedua yang sedikit bias
- Fitur opsional
unbiasedmenggantinya dengan versi berulang yang lebih kompleks
urandommenghitung ambang secara tertunda dan memakai satu implementasi perkalian-penolakan tak bias untuk rentang yang dapat dipakai ulang maupun sekali pakai- Mengikuti pendekatan yang dijelaskan dalam paper Daniel Lemire tahun 2018, Fast Random Integer Generation in an Interval
- Pada sebagian besar rentang praktis, kandidat pertama dikembalikan sebelum pembagian
- Jika kandidat pertama tidak bisa dikembalikan, ambang yang tepat dihitung lalu pengulangan dilakukan tanpa bias
- Kasus khusus
range == 0saat seluruh rentang diminta juga ditangani
- Distribusi yang dipakai ulang dan rentang sekali pakai ditangani dengan implementasi yang sama, tanpa metode terpisah, algoritme kedua, biaya setup di muka, atau jalur cepat yang bias
- Hasil benchmark pengambilan 1.000 sampel pada rentang
500..20_000adalah sebagai berikutUniformIntpakai ulang:rand1,098ns,urandom950ns- Rentang sekali pakai:
rand1,079ns,urandom942ns
- Hasil
randmenggunakan fitur default, jadi baris sekali pakai yang lebih cepat masih memakai jalur yang sedikit bias, sementaraurandomlebih cepat dari kedua jalur itu dalam keadaan tak bias
Reproduksibilitas lintas rilis dan arsitektur
urandommemperlakukan reproduksibilitas sebagai bagian dari kontrak publik- Dengan seed eksplisit yang sama dan urutan pemanggilan RNG tingkat rendah yang sama, output mentah dari generator deterministik dipertahankan
- Stabilitas dijamin di seluruh arsitektur yang didukung dan rilis yang kompatibel dengan SemVer
- Server 64-bit dan klien WebAssembly 32-bit dapat memakai basis generator yang sama untuk replay
- Demi menjaga kompatibilitas ini, performa di arsitektur 32-bit dikorbankan
- Ini adalah jaminan yang lebih kuat daripada kebijakan reproduksibilitas
rand- Output generator portabel dan algoritme sampling
randdapat berubah pada rilis minor SmallRngdanStdRngsecara eksplisit tidak portabel dan juga dapat berubah tergantung platform atau rilis pustaka
- Output generator portabel dan algoritme sampling
Biaya pilihan dan kapan cocok dipakai
urandommengumpulkan operasi umum ke dalamRandomsehingga mudah ditemukan tanpa trait ekstensi- Dengan merancang generator dan distribusi bersama-sama, ia mengimplementasikan jalur output Xoshiro yang lebih murah dan satu jalur sampling uniform tak bias
- Stream mentah yang stabil dari generator dengan seed eksplisit bisa dimanfaatkan untuk game dan simulasi deterministik
- Sebagai gantinya, generator acak sembarang tidak bisa dibawa masuk, dan ia juga tidak memiliki daftar distribusi yang lebih besar serta ekosistem integrasi pihak ketiga yang disediakan
rand - Jika membutuhkan ekosistem yang luas,
randlebih cocok; jika Anda lebih menyukai permukaan API yang kecil, kemudahan penemuan, optimasi yang terintegrasi, dan kebijakan reproduksibilitas yang kuat, Anda bisa memilihurandom - Paketnya dapat dilihat di crates.io, dokumentasi API, dan kode sumber GitHub
1 komentar
Komentar di Lobste.rs
Ada cukup alasan untuk mem-fork
rand, tetapi namaurandomterdengar seperti library yang terkait dengan/dev/urandomSaya setuju dengan masalah yang diangkat, tetapi tidak suka
pub fn new() -> Random<impl Rng + Clone>Jika seluruh aplikasi diparameterisasi sebagai
Random<T> where T: Rng, pekerjaan merepotkan akan bertambah, dan masalah terkait waktu kompilasi sertadynmenjadi serius. Saya lebih memilihstruct Randommemiliki tipe konkret, atau sebagai opsi kedua, memilihstruct Random<T = rng::Xoshiro256Rng>Karena frustrasi serupa, saya sudah pernah membuat sendiri, tetapi bukan fork, dan fiturnya jauh lebih sedikit daripada
randSenang melihat ada orang lain yang merasakan masalah yang sama seperti saya dan benar-benar mencoba menyelesaikannya. Rust tampaknya punya kecenderungan aneh untuk mendorong pembuatan library trait soup
Tipe data inti pada basis data yang saya tangani di pekerjaan harus mengimplementasikan setidaknya 15 trait, sehingga autocomplete berantakan dan dokumentasinya juga membingungkan. Kami sudah mengurangi sebagian jumlah trait, tetapi sering terhambat oleh dependensi siklik atau masalah yang membuat pengujian inti tidak bisa ditulis
Library ini mengingatkan saya pada deep interface dari APOSD dan pekerjaan kriptografi Filippo yang dirancang agar sulit disalahgunakan; keduanya merupakan pujian besar
urandom::new()tidak mengembalikan pembangkit bilangan acak yang aman secara kriptografis, desainnya belum sepenuhnya tidak mungkin disalahgunakan. Ini makin membingungkan terutama karena/dev/urandomdi Linux amanSebagai alternatif lain untuk
rand, adafastrand, pembangkit bilangan acak yang sederhana dan cepat. Lebih sederhana daripadaranddanurandom, tetapi fiturnya juga lebih sedikit