Numpy: Tentukan default baru BitGenerator PRNG

Dibuat pada 27 Mei 2019  ·  166Komentar  ·  Sumber: numpy/numpy

13163 akan membawa penggantian infrastruktur PRNG numpy yang telah lama ditunggu-tunggu. Untuk menjaga agar PR dapat dikelola, kami akan menggabungkannya menjadi master sebelum semua keputusan diselesaikan, seperti BitGenerator akan dinominasikan sebagai default.

Kami harus membuat keputusan sebelum rilis pertama dengan infrastruktur baru. Setelah dibebaskan, kami akan terjebak dengan pilihan kami untuk sementara waktu, jadi kami harus yakin bahwa kami nyaman dengan keputusan kami.

Di sisi lain, pilihan default tidak memiliki banyak konsekuensi. Kita tidak sedang membicarakan tentang default BitGenerator mendasari fungsi kenyamanan numpy.random.* . Per NEP 19, ini tetap alias RandomState warisan, yang BitGenerator tetap MT19937 . Satu-satunya tempat di mana default masuk adalah ketika Generator() dibuat tanpa argumen; yaitu ketika seorang pengguna meminta Generator dengan status arbitrer, mungkin untuk memanggil metode .seed() di atasnya. Ini mungkin sangat jarang, karena akan semudah membuat instance secara eksplisit dengan seeded BitGenerator yang sebenarnya mereka inginkan. Pilihan yang sah di sini mungkin sebenarnya adalah menominasikan tanpa default dan selalu meminta pengguna untuk menentukan BitGenerator .

Meskipun demikian, kami akan memiliki rekomendasi tentang BitGenerator harus digunakan sebagian besar waktu, dan sementara kami dapat mengubah rekomendasi dengan cukup bebas, mana pun yang memiliki tempat kebanggaan mungkin akan banyak ditulis di buku, blog, tutorial , dan seperti.

IMO, ada beberapa opsi utama (dengan komentar saya, jangan ragu untuk tidak setuju; Saya belum mencoba mentransfer semua komentar relevan dari # 13163):

Tidak ada default

Selalu membutuhkan Generator(ChosenBitGenerator(maybe_seed)) . Ini sedikit tidak bersahabat, tetapi karena ini adalah cara yang cukup nyaman untuk mendapatkan generator yang diinisialisasi dengan benar agar dapat direproduksi, orang mungkin akhirnya melakukan ini, meskipun kami memiliki default.

MT19937

Ini akan menjadi pilihan konservatif yang baik. Ini tentu tidak lebih buruk dari status quo. Karena Mersenne Twister masih secara luas dianggap sebagai pilihan "standar", ini mungkin membantu pengguna akademis yang membutuhkan makalah mereka untuk ditinjau oleh orang-orang yang mungkin mempertanyakan pilihan "non-standar", terlepas dari kualitas spesifik PRNG. "Tidak ada yang pernah dipecat karena mempekerjakan IBM." Kelemahan utama MT19937 sebagian besar adalah lebih lambat daripada beberapa alternatif yang tersedia, karena statusnya yang sangat besar, dan gagal dalam beberapa uji kualitas statistik. Dalam memilih PRNG lain, kami memiliki _opportunity_ (tetapi bukan _obligation_, IMO) untuk didiskusikan di sini dan mencoba untuk memindahkan "standar", jika kami mau.

PCG64

Ini mungkin yang paling sering saya gunakan, secara pribadi. Kelemahan utamanya adalah ia menggunakan aritmatika integer 128-bit, yang diemulasikan dalam C jika kompiler tidak menyediakan tipe integer seperti itu. Dua platform utama yang merupakan kasus ini adalah CPU 32-bit dan MSVC 64-bit, yang tidak mendukung integer 128-bit bahkan ketika CPU mendukungnya. Secara pribadi, saya tidak menyarankan membiarkan kinerja CPU 32-bit yang semakin langka menentukan pilihan kita. Tetapi kinerja MSVC penting, karena Windows build kita membutuhkan kompiler itu dan bukan kompiler Windows lainnya. Ini mungkin dapat diatasi dengan beberapa intrinsik assembly / compiler, tetapi seseorang harus menuliskannya. Fakta bahwa _hanya_ MSVC yang harus kita lakukan ini membuat ini agak lebih enak daripada waktu lain ketika kita dihadapkan pada perakitan.

Xoshiro256

Pilihan modern lainnya untuk PRNG kecil dan cepat. Itu memang memiliki beberapa kebiasaan statistik yang diketahui, tetapi mereka tidak mungkin menjadi faktor utama untuk sebagian besar penggunaan. Keunikan itu membuat saya menghindar darinya, tetapi itu adalah pilihan pribadi saya untuk kode yang akan saya tulis.

15 - Discussion numpy.random

Komentar yang paling membantu

Sangat terinspirasi oleh utas ini, saya memiliki beberapa berita untuk dilaporkan…

Latar Belakang

Dengan banyak ukuran pcg64 cukup bagus; misalnya, di bawah ukuran kualitas statistik yang biasa, ia mendapat tagihan kesehatan yang bersih. Ini telah diuji dengan berbagai cara; baru-baru ini saya telah menjalankannya hingga setengah petabyte dengan PractRand. Ini berfungsi dengan baik dalam kasus penggunaan normal.

TAPI, patologi yang muncul di utas ini tidak cocok dengan saya. Tentu, saya bisa mengatakan " baik, jangan anggap seperti itu ", tetapi inti dari tujuan umum PRNG adalah bahwa itu harus kuat. Saya ingin melakukan yang lebih baik ...

Jadi, sekitar 25 hari yang lalu saya mulai berpikir untuk merancang anggota baru keluarga PCG…

Tujuan

Tujuan saya adalah merancang anggota keluarga PCG baru yang bisa menjadi pengganti varian pcg64 . Dengan demikian:

  • Fungsi output harus mengacak bit lebih dari XSL RR (karena hal itu akan menghindari masalah yang muncul di utas ini).
  • Kinerja harus secepat (atau lebih cepat) dari pcg64 .
  • Desain harus PCG-ish (yaitu, jangan mudah diprediksi, dan dengan demikian tidak mengizinkan _ apa pun_ pekerjaan fungsi keluaran dengan mudah dibatalkan).

Seperti biasa, selalu ada kompromi saat kami berusaha mendapatkan kualitas terbaik secepat mungkin. Jika kita tidak peduli sama sekali tentang kecepatan, kita dapat memiliki lebih banyak langkah dalam fungsi keluaran untuk menghasilkan keluaran yang lebih teracak, tetapi inti dari PCG adalah bahwa LCG yang mendasarinya "hampir cukup baik" dan jadi kita tidak perlu untuk melakukan upaya sebanyak yang kami lakukan dengan sesuatu seperti penghitung yang bertambah 1.

Spoiler

Saya senang melaporkan kesuksesan! Sekitar 25 hari yang lalu ketika saya pertama kali memikirkan hal ini, saya sebenarnya sedang berlibur. Ketika saya kembali sekitar sepuluh hari yang lalu, saya mencoba ide-ide yang saya miliki dan senang menemukan bahwa ide-ide itu bekerja dengan baik. Waktu berikutnya sebagian besar dihabiskan untuk berbagai jenis pengujian. Kemarin sudah cukup puas bahwa saya mendorong kode ke versi C ++ dari PCG. Pengujian pada ukuran kecil menunjukkan bahwa itu jauh lebih baik daripada XSL RR, dan bersaing dengan RXS M, tetapi sebenarnya bersinar pada ukuran yang lebih besar. Itu memenuhi semua tujuan lainnya juga.

Detail

FWIW, fungsi keluaran baru adalah (untuk kasus keluaran 64-bit):

uint64_t output(__uint128_t internal)
{
    uint64_t hi = internal >> 64;
    uint64_t lo = internal;

    lo |= 1;
    hi ^= hi >> 32;
    hi *= 0xda942042e4dd58b5ULL;
    hi ^= hi >> 48;
    hi *= lo;
    return hi;
}

Fungsi keluaran ini terinspirasi oleh xorshift-multiply, yang banyak digunakan. Pilihan pengali adalah (a) untuk menekan jumlah konstanta ajaib, dan (b) untuk mencegah permutasi dibatalkan (jika Anda tidak memiliki akses ke bit orde rendah), dan juga menyediakan keseluruhan "acak- kualitas dengan sendirinya ”yang biasanya dimiliki oleh fungsi keluaran PCG.

Perubahan lainnya

Ini juga merupakan kasus bahwa 0xda942042e4dd58b5 adalah pengganda LCG untuk PRNG ini (dan semua generator PCG 128-bit-state cm_ diawali). Dibandingkan dengan 0x2360ed051fc65da44385df649fccf645 digunakan oleh pcg64 , konstanta ini sebenarnya masih cukup baik dalam hal properti uji spektral, tetapi lebih murah untuk dikalikan karena 128-bit × 64-bit lebih mudah daripada 128-bit × 128-bit. Saya telah menggunakan konstanta LCG ini selama beberapa tahun tanpa masalah. Saat menggunakan varian pengganda-murah, saya menjalankan fungsi keluaran pada keadaan pra-iterasi daripada status pasca-iterasi untuk paralelisme tingkat instruksi yang lebih besar.

Menguji

Saya telah mengujinya secara menyeluruh (PractRand dan TestU01) dan saya senang dengannya. Tes termasuk skenario yang diuraikan dalam utas ini (misalnya, mengambil generator geng baik pada uap berurutan atau maju dengan 2 ^ 64 dan menyisipkan output mereka - Saya menguji sekelompok empat dan sekelompok 8192 hingga 8 TB tanpa masalah, juga sebagai sungai dan lawan daratannya).

Kecepatan

Saya bisa panjang lebar tentang tes kecepatan dan benchmark. Ada berbagai macam faktor yang memengaruhi apakah satu PRNG berjalan lebih cepat daripada yang lain dalam tolok ukur tertentu, tetapi secara keseluruhan, varian ini tampaknya sering kali sedikit lebih cepat, terkadang jauh lebih cepat, dan terkadang sedikit lebih lambat. Faktor-faktor seperti compiler dan aplikasi memiliki pengaruh yang jauh lebih besar pada variabilitas benchmark.

Ketersediaan

Pengguna dengan header C ++ dapat mengakses anggota keluarga baru ini _now_ sebagai pcg_engines::cm_setseq_dxsm_128_64 ; di masa mendatang, saya akan mengalihkan pcg64 dari pcg_engines::setseq_xsl_rr_128_64 ke skema baru ini. Rencana saya saat ini adalah melakukannya musim panas ini sebagai bagian dari benjolan versi PCG 2.0.

Pengumuman Resmi

Secara keseluruhan, saya sangat senang dengan anggota keluarga baru ini dan pada suatu saat nanti di musim panas, akan ada postingan blog dengan detail lebih lanjut, kemungkinan merujuk pada utas ini.

Pilihan Anda ...

Tentu saja, Anda harus memikirkan apa yang harus dilakukan dengan ini. Terlepas dari apakah Anda akan menggunakannya atau tidak, saya sebenarnya akan sangat penasaran untuk melihat apakah itu lebih baik atau lebih buruk dalam tolok ukur kecepatan Anda.

Semua 166 komentar

Apa yang dilakukan kompiler Windows Intel untuk bilangan bulat 128 bit? Seberapa lambat PCG64 dikompilasi dengan MSVC dibandingkan dengan MT1993 di Windows? Saya curiga bahwa fitur lompat ke depan akan banyak digunakan, jadi mungkin lebih baik untuk memilikinya secara default.

Apa yang dilakukan kompiler Windows Intel untuk bilangan bulat 128 bit?

Tidak sepenuhnya yakin; Saya tidak tahu apakah ada implikasi ABI yang akan membuat ICC peduli untuk dibatasi. Jika kita hanya ingin mendapatkan ide tentang perakitan yang dihasilkan yang dapat kita gunakan, maka ini adalah sumber yang berguna: https://godbolt.org/z/kBntXH

Saya curiga bahwa fitur lompat ke depan akan banyak digunakan, jadi mungkin lebih baik untuk memilikinya secara default.

Apakah yang Anda maksud adalah aliran yang dapat diatur? Itu poin yang bagus, tapi saya bertanya-tanya apakah itu mungkin tidak memotong ke arah lain. Jika pilihan default kita benar-benar penting, maka mungkin jika kita memilih salah satu dari PRNG berfitur lengkap ini, orang akan menggunakan fitur tersebut secara lebih luas dalam kode perpustakaan tanpa mendokumentasikan bahwa mereka memerlukan fitur "lanjutan" tersebut, karena, bagaimanapun, mereka tersedia "standar". Tapi kemudian jika pengguna lain mencoba menggunakan perpustakaan itu dengan fitur BitGenerator kurang fitur untuk kecepatan atau alasan lain, maka mereka akan menemui jalan buntu. Di dunia No default atau MT19937 , perpustakaan akan lebih cenderung memikirkan dan mendokumentasikan fitur-fitur canggih yang mereka butuhkan.

Di sisi yang mencengkeram, kemungkinan itu akan membuat BitGenerator s tanpa aliran yang dapat diatur terlihat kurang diinginkan, dan saya _do_ menyukai gagasan untuk memajukan apa yang dianggap sebagai praktik terbaik ke arah itu (murni secara pribadi; Saya tidak merasa kewajiban untuk membuat NumPy-the-project berbagi gagasan itu). Ini mungkin membantu menghindari beberapa penyalahgunaan yang saya lihat pada orang .seed() di tengah kode mereka. Tetapi sekali lagi, semua itu didasarkan pada anggapan bahwa memiliki default akan mengubah perilaku orang secara signifikan, jadi semua kekhawatiran ini kemungkinan besar cukup dilemahkan.

Seberapa lambat PCG64 dikompilasi dengan MSVC dibandingkan dengan MT1993 di Windows?

Dalam benchmark yang diposting oleh @bashtage di # 13163, PCG64 hampir setengah dari kecepatan MT19937, yang merupakan kinerja yang cukup mengecewakan dari MSVC dan kawan-kawan. Dibandingkan dengan 23% lebih cepat di Linux.

Apa yang dilakukan kompiler Windows Intel untuk bilangan bulat 128 bit?

Kompiler lain seperti Clang, GCC, dan kompiler Intel mengimplementasikan integer 128-bit pada sistem 64-bit dengan cara yang sama seperti mereka mengimplementasikan integer 64-bit pada sistem 32-bit. Semua teknik yang sama tanpa memerlukan ide baru. Microsoft tidak repot-repot melakukan itu untuk MSVC sehingga tidak ada bilangan bulat 128-bit yang didukung langsung oleh kompiler.

Akibatnya, untuk MSVC, implementasi PCG64 yang ada di # 13163 menerapkan matematika 128-bit secara manual dengan memanggil intrinsik Microsoft seperti _umul128 di x86_64 (dan mungkin juga dapat menggunakan intrinsik Intel yang setara dan lebih portabel seperti _mulx_u64 sebagai gantinya), dengan demikian mengkodekan apa yang GCC, Clang dan kompiler Intel akan lakukan sendiri. Masalah terbesar kemungkinan kompiler Microsoft tidak mengoptimalkan intrinsik ini dengan sangat baik (semoga mereka setidaknya inline?). Ada kemungkinan bahwa assembler yang dikodekan dengan tangan mungkin berjalan lebih cepat tetapi perbaikan yang tepat adalah agar kompiler tidak begitu buruk secara kejam.

Saya curiga bahwa fitur lompat ke depan akan banyak digunakan, jadi mungkin lebih baik untuk memilikinya secara default.

Saya senang Anda suka melompat ke depan, tetapi saya ingin tahu mengapa menurut Anda ini akan digunakan secara luas. (Secara pribadi, saya sangat suka distance , yang memberi tahu Anda seberapa jauh jarak dua PRNG. Itu ada di versi C ++ dari PCG, tetapi bukan versi C. Itu akan cukup sepele untuk menambahkannya meskipun jika ada bunga.)

Saya senang Anda suka melompat ke depan, tetapi saya ingin tahu mengapa menurut Anda ini akan digunakan secara luas.

Mungkin ketidaktahuan dengan terminologi saat ini. Yang saya maksud adalah dengan mudah memperoleh aliran independen yang dapat digunakan untuk menjalankan simulasi secara paralel. Saya tidak tahu berapa banyak masalah simulasi yang dapat diparalelkan, tetapi saya curiga itu banyak dan mengingat jumlah core yang didapat orang pada sebuah chip hari ini, yang dapat dengan mudah mengganti kerugian kecepatan.

Microsoft tidak repot-repot melakukan itu untuk MSVC sehingga tidak ada bilangan bulat 128-bit yang didukung langsung oleh kompiler.

Jadi itu akan merugikan roda kami, OTOH, banyak orang di Windows mendapatkan paket mereka dari Anaconda atau Enthought, keduanya menggunakan Intel, dan orang-orang yang benar-benar peduli dengan kinerja mungkin menggunakan Linux, Mac, atau mungkin AIX.

EDIT: Dan mungkin jika Microsoft khawatir, mereka dapat menawarkan hadiah untuk memperbaiki masalah.

FWIW, berikut perakitan yang akan dihasilkan clang untuk fungsi kritis, termasuk bit yang diperlukan untuk membongkar / mengemas kembali uint128_t ke dalam struct uint64_t s: https: // godbolt.org/z/Gtp3os

Keren banget, @rkern. Adakah kemungkinan Anda dapat melakukan hal yang sama untuk melihat apa yang dilakukan MSVC dengan kode 128-bit yang ditulis tangan?

Keren banget, @rkern. Adakah kemungkinan Anda dapat melakukan hal yang sama untuk melihat apa yang dilakukan MSVC dengan kode 128-bit yang ditulis tangan?

Ini, eh, tidak cantik. ~ https://godbolt.org/z/a5L5Gz~

Ups, lupa menambahkan -O3 , tapi masih jelek: https://godbolt.org/z/yiQRhd

Tidak terlalu buruk. Anda tidak mengaktifkan pengoptimalan, jadi tidak ada yang sebaris. Saya telah menambahkan /Ox (mungkin ada pilihan yang lebih baik?). Saya juga memperbaiki kode untuk menggunakan built-in rotate intrinsic ( _rotr64 ) karena ternyata MSVC tidak mampu menemukan idiom C rotate.

Masih seperti kecelakaan kereta api. Tapi saya pikir adil untuk mengatakan bahwa dengan sedikit perhatian, kode PCG64 dapat diubah untuk dikompilasi di MSVC menjadi sesuatu yang tidak terlalu memalukan bagi semua orang.

Untuk mengizinkan semua yang lain digabungkan, mengapa tidak memilih "tidak ada default" untuk saat ini? Itu membuat kami bebas untuk membuat keputusan tentang default nanti (bahkan setelah satu atau beberapa rilis) tanpa merusak kompatibilitas.

Sebagian besar pengguna kami bukan ahli angka acak, kami harus menyediakan default untuk mereka.

Di luar biasa "sekarang mereka perlu mengetik lebih banyak kode", apa yang terjadi ketika kita mengubah sesuatu? Dalam kasus di mana BitGenerator dikodekan dengan keras, (karena kami tidak menyediakan default), setiap pengguna yang tidak canggih sekarang harus memfaktorkan ulang kode mereka, dan mudah-mudahan memahami nuansa pilihan mereka (perhatikan bahwa kami bahkan tidak dapat menyetujui di antara kami sendiri apa paling baik). Namun jika kami menyediakan default, kami mungkin akan merusak pengujian mereka karena default baru atau versi baru tidak kompatibel dengan bit-stream.

Antara asumsi bahwa aliran bit akan selalu konstan versus asumsi bahwa pengembang NumPy tahu apa yang mereka lakukan dan nilai default harus merek terbaik, saya akan keliru di sisi asumsi kedua, bahkan jika itu istirahat dulu.

Edit: mengklarifikasi pengembang mana yang harus tahu apa yang mereka lakukan

Sebagian besar pengguna kami bukan ahli angka acak, kami harus menyediakan default untuk mereka.

Yah, kami pasti akan mendokumentasikan rekomendasi, paling tidak, terlepas dari apakah kami memiliki default atau tidak atau apa defaultnya.

Di luar biasa "sekarang mereka perlu mengetik lebih banyak kode", apa yang terjadi ketika kita mengubah sesuatu?

Apa "sesuatu" yang kamu pikirkan? Saya tidak bisa mengikuti argumen Anda.

Di luar biasa "sekarang mereka perlu mengetik lebih banyak kode", apa yang terjadi ketika kita mengubah sesuatu?

Apa "sesuatu" yang kamu pikirkan? Saya tidak bisa mengikuti argumen Anda.

@ Mattip mengacu pada mengubah generator bit default.

Ini akan membuat pengguna yang telah mengadopsinya marah, dan dapat memerlukan beberapa perubahan kode.

Misalnya, jika Anda dulu

g = Generator()
g.bit_generator.seed(1234)

dan pembuat bit yang mendasarinya diubah, maka ini akan menjadi salah.

Jika Anda melakukan hal yang lebih waras dan digunakan

Generator(BitGenerator(1234))

maka Anda tidak akan melihatnya.

IMO, Ketika mempertimbangkan pilihan default, kita harus berpikir itu diperbaiki sampai kesalahan fatal ditemukan di pembuat bit yang mendasarinya atau Intel menambahkan QUANTUM_NI ke chipnya, yang menghasilkan banyak peningkatan OOM dalam kinerja acak.

Saya menyadari bahwa saya sedikit orang luar di sini, tetapi menurut saya tidak masuk akal untuk mengharapkan bahwa PRNG sebagai pilihan default diperbaiki selamanya dan tidak pernah berubah. (Dalam C ++, misalnya, std::default_random_engine adalah kebijaksanaan implementasinya dan dapat berubah dari rilis ke rilis.)

Sebaliknya, perlu ada mekanisme untuk mereproduksi hasil sebelumnya. Jadi, sekali implementasi tertentu ada, sangat tidak keren untuk mengubahnya (misalnya, MT19937 _is_ MT19937, Anda tidak dapat men-tweaknya untuk memberikan keluaran yang berbeda). [Dan juga tidak keren untuk menghapus implementasi yang sudah ada.]

Saat default berubah, orang yang ingin tetap mereproduksi hasil lama perlu meminta default sebelumnya berdasarkan nama. (Anda dapat membuatnya dengan menyediakan mekanisme untuk memilih default yang sesuai dengan rilis sebelumnya.)

Meskipun demikian, meskipun Anda diizinkan untuk menukar generator default dengan yang lain, itu benar-benar harus benar-benar lebih baik - fitur apa pun yang ada di generator default mewakili komitmen untuk mendukung fitur itu di masa mendatang. Jika generator default Anda memiliki advance efisien, Anda tidak dapat mengambilnya lagi nanti. (Anda berpotensi menutup fungsionalitas lanjutan di generator default untuk menghindari masalah ini.)

Singkatnya, ada cara untuk memastikan penggunaan dapat menghasilkan hasil yang dapat direproduksi tanpa mencoba mengunci diri Anda sendiri ke dalam kontrak di mana default tidak berubah selamanya. Ini juga akan mengurangi taruhan untuk pilihan yang Anda buat.

(FWIW, inilah yang saya lakukan di PCG. PCG 32-bit PRNG default saat ini adalah varian XSH-RR [diakses sebagai pcg_setseq_64_xsh_rr_32_random_r di perpustakaan C dan kelas pcg_engines::setseq_xsh_rr_64_32 di C ++ library], tetapi pada prinsipnya jika Anda benar-benar ingin reproduktifitas yang tahan masa depan Anda harus menentukan XSH-RR secara eksplisit, daripada menggunakan pcg32_random_r atau pcg32 yang merupakan alias dan pada prinsipnya dapat ditingkatkan ke yang lain .)

Ini tidak benar-benar selamanya (seluruh proyek ini 90% didorong oleh janji yang nyata, asli, dan dihormati selamanya yang dibuat sekitar 14 tahun yang lalu), tetapi seperti yang Anda katakan, mengganti kebutuhan (a) alasan yang kuat untuk berubah dan (b) akan mengambil setidaknya beberapa tahun memberikan siklus depresiasi.

Jauh lebih baik untuk berusaha keras hari ini untuk membuatnya sedekat mungkin.

Satu hal yang tidak dilarang, tentu saja, adalah meningkatkan kode PRNG setelah rilis sebagai logn karena menghasilkan nilai yang sama. Misalnya, jika kami menggunakan PRNG yang menggunakan uint128, kami dapat mengizinkan MS menambahkan dukungan uint128 (kemungkinan besar) atau menambahkan assembly untuk Win64 di versi mendatang.

Misalnya, jika Anda dulu

g = Generator()
g.bit_generator.seed(1234)

dan pembuat bit yang mendasarinya diubah, maka ini akan menjadi salah.

Benar, itu sepertinya memperdebatkan, dengan @ eric-wieser, untuk opsi "Tidak ada default", yang saya tidak bisa kuadratkan dengan pernyataan awal "Sebagian besar pengguna kami bukan ahli angka acak, kami harus menyediakan default untuk mereka . "

Antara tidak ada default dan default yang bersahabat, dengan asumsi penuh, saya akan selalu memilih yang terakhir:

Sekarang:

Generator() # OK
Generator(DefaultBitGenerator(seed)) # OK
Generator(seed) # error

preferensi _my_:

Generator(1234) == Generator(DefaultBitGenerator(1234)
Generator(*args**kwargs) == Generator(DefaultBitGenerator(*args, **kwargs))

Sekarang saya tidak berpikir ini akan masuk, tetapi saya pikir salah satu cara untuk memperpanjang penggunaan RandomState adalah membuat ini hanya tersedia untuk pengguna yang merasa mereka cukup ahli untuk memilih generator bit.

Singkatnya, ada cara untuk memastikan penggunaan dapat menghasilkan hasil yang dapat direproduksi tanpa mencoba mengunci diri Anda sendiri ke dalam kontrak di mana default tidak berubah selamanya. Ini juga akan mengurangi taruhan untuk pilihan yang Anda buat.

Ya, kami punya itu. Pengguna dapat mengambil BitGenerator s berdasarkan nama (misalnya MT19937 , PCG64 , dll.) Dan membuat contoh dengan seed. BitGenerator objek mengimplementasikan algoritma PRNG seragam inti dengan serangkaian metode terbatas untuk menggambar seragam [0..1) float64 s dan bilangan bulat (serta kemampuan jumpahead / stream menyenangkan apa pun yang mereka miliki) . Kelas Generator yang kita bicarakan mengambil objek BitGenerator disediakan dan membungkusnya untuk menyediakan semua distribusi yang tidak seragam, Gaussians, gammas, binomial, dll. Kita punya jaminan kompatibilitas streaming yang ketat untuk BitGenerator s. Kami tidak akan menyingkirkan apa pun (yang membuatnya dirilis), dan juga tidak akan mengubahnya.

Pertanyaan sentral tentang default adalah "Apa yang dilakukan kode g = Generator() , tanpa argumen?" Saat ini, dalam PR, ia membuat Xoshiro256 BitGenerator dengan status arbitrer (yaitu diambil dari sumber entropi yang baik seperti /dev/urandom ). Opsi "Tidak ada default" akan membuatnya menjadi kesalahan; pengguna harus secara eksplisit memberi nama BitGenerator yang mereka inginkan. Poin @eric-wieser adalah bahwa "Tidak ada default" adalah pilihan _safe_ kategoris untuk rilis pertama. Rilis selanjutnya yang menyediakan default tidak akan menyebabkan masalah dengan cara yang sama seperti mengubah default yang ada.

@rkern , Jika Anda hanya peduli tentang kasus tanpa argumen di mana seed dibuat secara otomatis dari entropi yang tersedia, maka tidak masalah apa generator yang mendasarinya - itu dapat berubah setiap jam karena hasilnya tidak akan pernah dapat direproduksi ( lari yang berbeda akan mendapatkan benih yang berbeda).

Sebaliknya, @bashtage tampaknya peduli dengan generator default yang disediakan dengan seed.

@rkern , Jika Anda hanya peduli tentang kasus _no arguments_ di mana seed dibuat secara otomatis dari entropi yang tersedia, maka tidak terlalu menjadi masalah apa generator yang mendasarinya - itu dapat berubah setiap jam karena hasilnya tidak akan pernah dapat direproduksi ( lari yang berbeda akan menghasilkan benih yang berbeda).

Anda dapat mengirim ulang BitGenerator setelah dibuat. Jadi jika Generator() berfungsi, yang saya perkirakan sepenuhnya akan terjadi adalah bahwa orang yang menginginkan PRNG yang diunggulkan hanya akan memasukkannya ke baris berikutnya, seperti dalam contoh @bashtage :

g = Generator()
g.bit_generator.seed(seed)

Itu agak membosankan, itulah sebabnya saya menyarankan di atas bahwa mungkin kebanyakan orang biasanya akan memilih Generator(PCG64(<seed>)) lagian, karena ini sama nyamannya mengetik. Namun, @bashtage dengan tepat mencatat beberapa penolakan saat dihadapkan pada pengambilan keputusan tambahan.

Jadi saya rasa kita _juga_ memiliki pertanyaan yang lebih luas di depan kita: "Apa saja cara yang kita inginkan agar pengguna membuat salah satu cara ini? Dan jika cara tersebut memiliki pengaturan default, apa yang seharusnya menjadi default?" Kami memiliki beberapa ruang desain terbuka dan saran @bashtage untuk Generator(<seed>) atau Generator(DefaultBitGenerator(<seed>)) masih memungkinkan.

@bashtage Menurut Anda, seberapa besar dokumentasi akan membantu? Artinya, jika kami mengatakan di bagian atas " PCG64 adalah default pilihan kami BitGenerator " dan menggunakan Generator(PCG64(seed)) secara konsisten di semua contoh (ketika tidak secara khusus mendemonstrasikan algoritme lain)?

Saya mungkin lebih yakin untuk memiliki default_generator(<seed>) _function_ lebih dari Generator(<seed>) atau g=Generator();g.seed(<seed>) . Kemudian jika kita benar-benar perlu mengubahnya dan tidak ingin merusak barang, kita bisa menambahkan fungsi baru dan menambahkan peringatan ke yang lama. Saya mungkin merekomendasikan untuk menandainya experimental untuk rilis pertama, memberi kami waktu untuk menonton infrastruktur ini di alam liar sebelum membuat komitmen yang kuat.

Bagaimana dengan benar-benar membuat objek DefaultBitGenerator yang tidak memperlihatkan detail apa pun dari status internalnya? Ini akan menjadi proxy untuk salah satu objek pembuat bit lainnya, tetapi pada prinsipnya dapat membungkus salah satu dari mereka - kecuali tentu saja untuk urutan spesifik dari bilangan yang dihasilkan. Hal ini diharapkan dapat membuat pengguna enggan membuat asumsi terprogram tentang apa yang dapat mereka lakukan dengan BitGenerator default, sambil memungkinkan kami untuk tetap menggunakan algoritme yang ditingkatkan.

Saya setuju dengan @bashtage bahwa akan jauh lebih bersahabat untuk mendukung langsung seed integer sebagai argumen ke Generator , misalnya, np.random.Generator(1234) . Ini tentu saja akan menggunakan DefaultBitGenerator .

Dalam dokumentasi untuk Generator , kami dapat memberikan riwayat lengkap tentang apa pembuat bit default di setiap versi NumPy sebelumnya. Ini pada dasarnya adalah saran @imneme , dan menurut saya akan cukup untuk tujuan reproduktifitas.

(Baru saja melihat hasil edit ini pada komentar sebelumnya)

Ups, lupa menambahkan -O3 , tapi masih jelek: https://godbolt.org/z/yiQRhd

Untuk MSVC, ini bukan -O3 , itu /O2 atau /Ox (tapi bukan /O3 !).

Dalam dokumentasi untuk Generator , kami dapat memberikan riwayat lengkap tentang apa pembuat bit default di setiap versi NumPy sebelumnya. Ini pada dasarnya adalah saran @imneme , dan menurut saya akan cukup untuk tujuan reproduktifitas.

Sebenarnya, lebih baik lagi memasukkan argumen eksplisit version , seperti argumen acar protocol , dalam Generator / DefaultBitGenerator . Kemudian Anda dapat menulis sesuatu seperti np.random.Generator(123, version=1) untuk menunjukkan bahwa Anda menginginkan nomor acak "versi 1" (apa pun itu) atau np.random.Generator(123, version=np.random.HIGHEST_VERSION) (perilaku default) untuk menunjukkan bahwa Anda menginginkan pembuat bit terbaru / terhebat (apapun itu).

Agaknya version=0 akan menjadi MT19937 yang telah digunakan NumPy sampai sekarang, dan version=1 bisa menjadi default baru apapun yang kita pilih.

Bagaimana dengan membuat objek DefaultBitGenerator yang tidak memperlihatkan detail apa pun dari status internalnya? Ini akan menjadi proxy untuk salah satu objek pembuat bit lainnya, tetapi pada prinsipnya dapat membungkus salah satu dari mereka - kecuali tentu saja untuk urutan spesifik dari bilangan yang dihasilkan. Hal ini diharapkan dapat membuat pengguna enggan membuat asumsi terprogram tentang apa yang dapat mereka lakukan dengan BitGenerator default, sambil memungkinkan kami untuk tetap menggunakan algoritme yang ditingkatkan.

Hmmm. Itu menarik. Itu _feels_ seperti hal-hal yang terlalu rumit dan menambahkan loop lain ke simpul Gordian ini (dan bahwa _harus_ ada lebih banyak goresan Alexander-esque yang tersedia bagi kita), tetapi itu benar-benar satu-satunya hal buruk yang harus saya katakan tentang itu. Itu _tidak membuat keputusan yang tersisa lebih mudah: kami dapat fokus pada kualitas dan kinerja statistik.

Sebenarnya, yang lebih baik adalah menyertakan argumen eksplisit version , seperti pickle , dalam Generator / DefaultBitGenerator .

Saya kurang penggemar ini. Tidak seperti kasus pickle , benda-benda ini memiliki nama yang berarti yang dapat kita gunakan, dan kita telah menerapkan mekanismenya.

Saya kurang penggemar ini. Tidak seperti case pickle , benda-benda ini memiliki nama yang berarti yang dapat kita gunakan, dan kita telah menerapkan mekanismenya.

Pertimbangkan hal berikut dari perspektif pengguna NumPy biasa:

  • np.random.Generator(seed, version=0) vs np.random.Generator(seed, version=1)
  • np.random.Generator(MT19937(seed)) vs np.random.Generator(PCG64(seed))

Saya rasa aman untuk mengasumsikan bahwa sebagian besar pengguna kami hanya mengetahui sedikit tentang manfaat relatif dari algoritme RNG. Tetapi bahkan tanpa membaca dokumen apa pun, mereka dapat dengan aman menebak bahwa version=1 (default yang lebih baru) pasti lebih baik dalam banyak kasus daripada version=0 . Bagi sebagian besar pengguna, hanya itu yang perlu mereka ketahui.

Sebaliknya, nama-nama seperti MT19937 dan PCG64 benar-benar hanya berarti bagi para ahli, atau orang-orang yang telah membaca dokumentasi kami :).

Dalam kasus penggunaan Anda, tidak ada yang memilih version yang mereka _want_. Mereka hanya memilih version yang mereka _n butuhkan_ untuk mereplikasi hasil dari versi yang dikenal. Mereka selalu mencari nilai spesifik yang digunakan (secara implisit, karena kami mengizinkannya menjadi implisit) dalam hasil yang ingin mereka tiru; mereka tidak perlu bernalar tentang hubungan antara banyak nilai.

Dan bagaimanapun, tingkat reproduktifitas pelepasan silang itu adalah sesuatu yang telah kami sangkal di NEP 19 . Argumen yang menentang pembuatan versi distribusi berlaku juga di sini.

Beberapa pemikiran tentang default:

  • 99,9% pengguna tidak akan peduli atau ingin tahu tentang algoritme yang mendasarinya, mereka hanya ingin nomor acak. Jadi +1 untuk membuat pilihan beropini sebagai default, tolong jangan buat pengguna memilih.
  • dSFMT tampaknya merupakan versi yang lebih cepat dari MT19937 (akan menyenangkan untuk menyatakan di dokumen seberapa cepat dan menghapus "SSE2"). Karena kami tidak menjamin reproduktifitas bitstream, perbedaan status internal tidak terlalu menarik dan dSFTM sebaiknya lebih disukai daripada MT19937 meskipun argumen yang menang di sini adalah "membuat hidup lebih mudah selama review artikel" .
  • Kinerja penting bagi sebagian besar basis pengguna. Properti statistik generator hanya penting bagi _very_ sebagian kecil pengguna. Semua generator yang disertakan baik-baik saja untuk kasus penggunaan normal. Jadi +1 untuk memilih yang tercepat sebagai default.

Mohon maaf - tapi 32-bit masih penting di Windows - lihat https://github.com/pypa/manylinux/issues/118#issuecomment -481404761

Saya pikir kita harus sangat peduli tentang properti statistik, karena kita sedang dalam proses perubahan besar menuju penggunaan metode resampling yang lebih besar dalam analisis data. Jika Python mendapat reputasi sebagai sedikit ceroboh dalam masalah ini, bahkan jika itu hanya secara default, itu mungkin menjadi penghalang untuk diambil oleh orang-orang yang mempertimbangkan Python untuk analisis data. Saya akan sangat senang jika Python adalah paket pilihan bagi orang-orang yang menganggap permutasi dan simulasi dengan serius.

Saya pikir tidak apa-apa untuk menawarkan algoritma non-state-of-art yang lebih cepat, tetapi tidak secara default, sejauh kita dapat menghindarinya dan mempertahankan kompatibilitas kembali.

Untuk beberapa forensik dan diskusi, lihat: https://arxiv.org/pdf/1810.10985.pdf

Buku teks memberikan metode yang secara implisit atau eksplisit mengasumsikan bahwa PRNG dapat diganti dengan variabel IIDU [0,1) yang sebenarnya tanpa memasukkan kesalahan material [20, 7, 2, 16, 15]. Kami menunjukkan di sini bahwa asumsi ini salah untuk algoritme di banyak paket statistik yang umum digunakan, termasuk MATLAB, modul acak Python, R, SPSS, dan Stata.

@kellieotto , @pbstark - apakah kalian punya pendapat tentang PRNG apa yang harus kita pilih di sini, untuk memberikan dasar terbaik untuk permutasi dan bootstrap?

Saya pikir kita harus sangat peduli tentang properti statistik, karena kita sedang dalam proses perubahan besar menuju penggunaan metode resampling yang lebih besar dalam analisis data.

Sepakat. Selama properti tersebut relevan untuk beberapa kasus penggunaan dunia nyata, itu sangat penting. Kekhawatiran yang biasanya diangkat selalu sangat akademis.

Untuk beberapa forensik dan diskusi, lihat: https://arxiv.org/pdf/1810.10985.pdf

Artikel yang sangat menarik. Itu menyimpulkan bahwa NumPy adalah satu-satunya pustaka yang melakukannya dengan benar (atas halaman 9), tidak seperti R, Python stdlib & co.

Akan sangat berguna untuk mendapatkan lebih banyak contoh konkret daripada di koran. Jika generator default kita saat ini juga rusak di beberapa titik, kapan itu? Contoh seperti fungsi R sample menghasilkan 40% bilangan genap dan 60% bilangan ganjil saat menggambar ~ 1,7 miliar sampel. Apa yang setara dengan bootstrap / resampling di sini?

Rilis terbaru dari R (3.6) memperbaiki pendekatan pemotongan vs. bit acak
untuk menghasilkan bilangan bulat acak. Mersenne Twister tetap menjadi default
PRNG, meskipun.

@Kellie Ottoboni [email protected] dan saya pikir PRNG default di
bahasa ilmiah dan paket statistik harus secara kriptografik
aman (CS-PRNG, misalnya, SHA256 dalam mode penghitung), dengan opsi jatuh
kembali ke sesuatu yang lebih cepat tetapi kualitasnya lebih rendah (mis., Mersenne Twister)
jika kecepatan membutuhkannya.

Kami telah mengerjakan CS-PRNG untuk Python:
https://github.com/statlab/cryptorandom

Performanya belum bagus (belum). Hambatan tampaknya menjadi jenis konversi
dalam Python untuk mentransmisikan string biner (keluaran hash) sebagai bilangan bulat. Kami
mengerjakan implementasi yang memindahkan lebih banyak pekerjaan ke C.

Bersulang,
Philip

Pada hari Senin, 27 Mei 2019 pukul 06.27 Ralf Gommers [email protected]
menulis:

Saya pikir kita harus sangat peduli tentang properti statistik, karena memang demikian
dalam proses perubahan besar menuju penggunaan metode resampling yang lebih besar di
analisis data

Sepakat. Selama properti tersebut relevan untuk beberapa penggunaan di dunia nyata
kasus, itu sangat penting. Kekhawatiran yang biasanya diangkat adalah
selalu sangat akademis.

Untuk beberapa forensik dan diskusi, lihat:
https://arxiv.org/pdf/1810.10985.pdf

Artikel yang sangat menarik. Itu menyimpulkan bahwa NumPy adalah satu-satunya
perpustakaan yang benar (atas halaman 9), tidak seperti R, Python stdlib & co.

Akan sangat berguna untuk mendapatkan lebih banyak contoh konkret daripada di
kertas. Jika generator default kami saat ini juga rusak di beberapa titik,
kapan itu? Contoh seperti fungsi sampel R menghasilkan 40% genap
angka dan 60% angka ganjil saat menggambar ~ 1,7 miliar sampel. Apa itu
setara bootstrap / resampling di sini?

-
Anda menerima ini karena Anda disebutkan.
Balas email ini secara langsung, lihat di GitHub
https://github.com/numpy/numpy/issues/13635?email_source=notifications&email_token=AANFDWJEIA4CTLLHVGZVKBLPXPOUFA5CNFSM4HPX3CHKYY3PNVWWK3TUL5252HS4DFVREXG43VMVBW85S4DFVREXG43VMVBW85S4DFVREXG43VMVBW85S4DFVREXG43VMVBW85S4DFVREXG43VMVBW85S4DFVREXG43VMVBW85S4DFVREXG43VMVBW85S4DFVREXG43VMVBW85S4CNFSM4HPX3CHKYY3PNVWWK3TUL52S4DFVREXG43VMVBW85S4DFVREXG43VMVBVW6S4DFVREXG43VMVBVW6S4DFVREXG43VMVBVW6DF
atau nonaktifkan utasnya
https://github.com/notifications/unsubscribe-auth/AANFDWJW445QDPGZDGXMPA3PXPOUFANCNFSM4HPX3CHA
.

-
Philip B. Stark | Associate Dean, Matematika dan Ilmu Fisika |
Profesor, Departemen Statistik |
Universitas California
Berkeley, CA 94720-3860 | 510-394-5077 | Statistics.berkeley.edu/~stark |
@tokopedia

Kinerja penting bagi sebagian besar basis pengguna. Properti statistik generator hanya penting bagi _very_ sebagian kecil pengguna. Semua generator yang disertakan baik-baik saja untuk kasus penggunaan normal. Jadi 1 untuk memilih yang tercepat sebagai default

Pertama, tidak ada cara untuk memilih "yang tercepat". @bashtage menjalankan beberapa tolok ukur pada kode saat ini di # 13163 dan itu ada di seluruh peta, dengan dSFMT menang di Windows dan dipukuli dengan keras oleh PCG-64 dan Xoroshiro 256 di Linux. Dan ini semua ada di mesin yang sama dengan tolok ukur yang sama. Arsitektur hardware yang berbeda (bahkan revisi dalam X86) akan membuat perbedaan seperti halnya benchmark yang berbeda. (Seperti yang telah dibahas di utas ini, PCG bekerja dengan buruk dalam tolok ukur Windows karena masalah dengan MSVC, yang juga cenderung bersifat sementara, karena MSVC dapat meningkat atau orang dapat mengatasi masalahnya. Mungkin masalah MSVC serupa menjelaskan mengapa Xoshiro dipukuli.)

Saya juga bertanya-tanya seberapa besar “fraksi signifikan” pengguna yang peduli dengan kecepatan. Python sendiri rata-rata menjadi sekitar 50 × lebih lambat dari C. Bagian mana dari basis pengguna NumPy yang menjalankannya di PyPy (yang akan memberikan peningkatan kecepatan 4x)? Beberapa, tentu, tapi saya kira bukan angka yang terlalu tinggi.

Dan untuk “pecahan signifikan” yang peduli dengan kecepatan, dengan semua variabilitas yang diuraikan di atas, siapa yang akan percaya bahwa PRNG default akan berjalan paling cepat untuk aplikasi mereka? Hal yang masuk akal untuk dilakukan (yang juga cukup menyenangkan dan dalam jangkauan sebagian besar pengguna) adalah melakukan tolok ukur PRNG berbeda yang tersedia dan melihat mana yang tercepat _untuk mereka_.

Sebaliknya, meskipun mereka mungkin menemukan petunjuk dalam dokumentasi, mengetahui kualitas statistik PRNG tertentu, seperti yang Anda catat, tidak ada di radar sebagian besar pengguna (dan menantang bahkan bagi para ahli). Sebagian besar bahkan tidak tahu kapan / apakah mereka harus peduli atau tidak. Saya berpendapat bahwa ini adalah tempat untuk beberapa paternalisme - fakta bahwa sebagian besar pengguna tidak peduli tentang sesuatu tidak berarti bahwa pengelola tidak boleh peduli tentang itu.

Memang benar bahwa semua PRNG yang disertakan baik-baik saja untuk sebagian besar kasus penggunaan, tetapi itu adalah batasan yang cukup rendah. Sistem Unix telah dikirimkan dengan hamparan C-library PRNG yang secara statistik mengerikan, namun mereka telah digunakan secara luas selama bertahun-tahun tanpa dunia memutarbalikkan sumbunya.

Di luar properti statistik, ada properti lain yang mungkin tidak diinginkan pengguna untuk dirinya sendiri, tetapi saya mungkin menginginkannya. Secara pribadi, sebagai penyedia PRNG saya ingin menghindari prediktabilitas sepele - saya tidak ingin seseorang melihat beberapa output dari PRNG dan kemudian dapat mengatakan seperti apa semua output di masa depan. Dalam sebagian besar konteks di mana NumPy digunakan, prediktabilitas bukanlah masalah - tidak ada musuh yang diuntungkan karena dapat dengan mudah memprediksi urutannya. Tetapi seseorang di suatu tempat akan menggunakan PRNG NumPy bukan karena mereka membutuhkan NumPy untuk melakukan statistik, tetapi karena di situlah mereka telah menemukan PRNG sebelumnya; kode itu mungkin menghadapi musuh yang sebenarnya yang akan mendapat manfaat dari dapat memprediksi PRNG. Membayar banyak (misalnya, kehilangan kecepatan yang signifikan) untuk memastikan dengan kuat terhadap situasi pencilan ini tidak sepadan, tetapi asuransi sederhana mungkin sepadan.

Untuk beberapa forensik dan diskusi, lihat: https://arxiv.org/pdf/1810.10985.pdf

Buku teks memberikan metode yang secara implisit atau eksplisit mengasumsikan bahwa PRNG dapat diganti dengan variabel IIDU [0,1) yang sebenarnya tanpa memasukkan kesalahan material [20, 7, 2, 16, 15]. Kami menunjukkan di sini bahwa asumsi ini salah untuk algoritme di banyak paket statistik yang umum digunakan, termasuk MATLAB, modul acak Python, R, SPSS, dan Stata.

FWIW, ada makalah bagus oleh @lemire tentang secara efisien menghasilkan angka dalam kisaran tanpa bias. Saya menggunakannya sebagai titik awal untuk menjelajahi dan menjalankan beberapa tolok ukur juga di artikel saya sendiri . (Saat membuat 64-bit, metode Lemire memang menggunakan perkalian 128-bit untuk menghindari pembagian 64-bit yang lambat, dengan semua masalah umum yang mungkin timbul bagi pengguna MSVC.)

@pbstark @kellieotto Saya membaca makalah Anda dengan penuh minat ketika muncul di arXiv. Saya mengunjungi beberapa teman di BIDS, dan mereka menyebutkan pekerjaan Anda. Bagian Diskusi mencatat bahwa "sejauh ini, kami belum menemukan statistik dengan bias konsisten yang cukup besar untuk dideteksi dalam ulangan O (10 ^ 5)" untuk MT19937. Apakah kamu sudah menemukannya? Sudahkah Anda menemukan contoh konkret untuk PRNG 128-bit-state seperti PCG64? Bagi saya itu menjadi ambang batas relevansi praktis yang masuk akal, di mana pertimbangan ini mungkin mulai melebihi yang lain (IMO), setidaknya untuk tujuan memilih default tujuan umum.

Fitur bagus dari kerangka kerja PRNG baru # 13163 kami adalah memungkinkan siapa saja untuk menyediakan BitGenerator mereka sendiri yang dapat dicolokkan begitu saja. Bahkan tidak harus rumit agar orang dapat menggunakannya di numpy mereka kode. Saya akan mendorong Anda untuk melihat penerapan cryptorandom sebagai BitGenerator dalam C sehingga kita dapat membandingkannya langsung dengan opsi lainnya.

Secara pribadi, saya berharap mereka yang benar-benar peduli dengan kecepatan bekerja ekstra jika perlu (tidak banyak di sini). Kita harus memberikan default yang aman , dan tebakan terbaik saya saat ini adalah bahwa ini berarti default yang aman untuk semua tujuan dengan pengecualian kriptografi (kita mungkin harus memiliki peringatan tentang itu di dokumen). Banyak pengguna peduli dengan kecepatan, tetapi terus terang itulah mengapa saya enggan memberikannya prioritas yang terlalu tinggi.
Artikel di mana Numpy melakukannya dengan baik tampaknya menarik (pujian untuk Robert mungkin karena melakukannya dengan benar!), Tetapi sebenarnya adalah sampler bukan pembuat bit.

@pbstark mungkin Anda ingin menerapkan ini sebagai BitGenerator yang kompatibel dengan numpy / randomgen? Itu mungkin cara termudah untuk mempercepatnya dan membuatnya tersedia untuk khalayak luas dalam bentuk yang jauh lebih berguna. Karena sepertinya Anda dan Kellie Ottoboni ada di Berkeley, kita bisa bertemu beberapa saat untuk mewujudkannya? (Hanya tawaran, saya harus melihat lebih dekat kodenya sendiri terlebih dahulu).

Mengenai kertas _Random Sampling: Practice Makes Imperfect_, ini adalah bacaan yang bagus, tetapi perlu diingat bahwa jika kita memiliki 1 triliun inti yang menghasilkan satu angka per nanodetik selama 100 tahun, kita akan menghasilkan kurang dari 2 ^ 102 angka.

Untuk PRNG yang dapat diprediksi secara sepele (bahkan yang memiliki ruang status besar seperti Mersenne Twister), kita sebenarnya dapat mengetahui apakah beberapa urutan keluaran tertentu dapat diproduksi (dan menemukan benih yang akan menghasilkannya jika ada atau merasa sedih jika tidak ada. ), tetapi untuk PRNG lain yang tidak dapat diprediksi secara sepele, kami tidak dapat (dengan mudah) mengetahui urutan keluaran mana yang tidak pernah dapat diproduksi dan mana yang ada tetapi cukup langka sehingga kami hampir tidak mungkin menemukannya dalam ribuan tahun pencarian. (Seperti yang mungkin Anda ketahui, saya memiliki PRNG yang saya tahu akan mengeluarkan file zip dengan _Twelth Night_ di dalamnya dalam 2 ^ 80 keluaran, tapi semoga berhasil menemukannya.)

Jika Anda benar-benar menginginkan cryptoprng maka satu-satunya pilihan pada perangkat keras modern adalah
AES karena memiliki instruksi khusus. @lemire memiliki implementasi
di sini https://github.com/lemire/testingRNG/blob/master/source/aesctr.h itu
secepat generator nonkripto. Ada juga ChaCha20 yang bisa pergi
cepat dengan SIMD. Keduanya akan menjadi anjing lambat pada perangkat keras lama sekalipun. ThreeFry dan
Philox sudah disertakan dan merupakan prngs penghitung cryptolite.

Crypto IMO dinilai terlalu tinggi dalam hal manfaat biaya. Saya tidak menyadarinya
pencabutan penting karena masalah PRNG dengan Mt, yang menurut saya telah terjadi
digunakan untuk 10e6 makalah yang diterbitkan. Satu-satunya aplikasi yang pernah saya lihat
dimana PRNG benar-benar bermasalah adalah kasus-kasus yang periodenya demikian
kecil sehingga generator menyelesaikan siklus penuh. Bahkan disini satu-satunya
efeknya adalah mengurangi ukuran sampel penelitian, yang mereplikasi utama
hasil sekali dijalankan kembali pada sistem dengan periode yang lebih besar.

Pada hari Senin, 27 Mei 2019, 19:50 Robert Kern [email protected] menulis:

@pbstark https://github.com/pbstark @kellieotto
https://github.com/kellieotto Saya membaca makalah Anda dengan penuh minat saat itu
muncul di arXiv. Saya mengunjungi beberapa teman di BIDS, dan mereka melakukannya
menyebutkan pekerjaan Anda. Bagian Diskusi mencatat bahwa "sejauh ini, kami belum
menemukan statistik dengan bias konsisten yang cukup besar untuk dideteksi
O (10 ^ 5) replikasi "untuk MT19937. Apakah Anda sudah menemukannya? Sudahkah Anda menemukan a
contoh konkret untuk PRNG 128-bit-state seperti PCG64? Itu menurut saya
menjadi ambang batas relevansi praktis yang wajar, di mana pertimbangan ini
mungkin mulai melebihi orang lain (IMO), setidaknya untuk tujuan memilih
default tujuan umum.

Fitur bagus dari kerangka PRNG baru kami # 13163
https://github.com/numpy/numpy/pull/13163 adalah memungkinkan siapa saja untuk melakukannya
menyediakan BitGenerator mereka sendiri yang dapat langsung dicolokkan. Tidak
bahkan harus berada di numpy agar orang dapat menggunakannya dalam kode numpy mereka. saya akan
mendorong Anda untuk melihat penerapan cryptorandom sebagai BitGenerator di C
sehingga kita dapat membandingkannya langsung dengan opsi lainnya.

-
Anda menerima ini karena Anda disebutkan.
Balas email ini secara langsung, lihat di GitHub
https://github.com/numpy/numpy/issues/13635?email_source=notifications&email_token=ABKTSRO5PKW4MRFSBGUFUNTPXQUOLA5CNFSM4HPX3CHKYY3PNVWWK3TUL52HS4DFVREXG43VMVWXH63ZGDFVREXG43VWKLICH63ZGDFVREXG43VWVWXH63ZGDFXG43
atau nonaktifkan utasnya
https://github.com/notifications/unsubscribe-auth/ABKTSRMRIHC4OYDR52HLTHDPXQUOLANCNFSM4HPX3CHA
.

Saya juga bertanya-tanya seberapa besar “fraksi signifikan” pengguna yang peduli dengan kecepatan. Python sendiri rata-rata menjadi sekitar 50 × lebih lambat dari C. Berapa fraksi dari basis pengguna NumPy yang menjalankannya di PyPy (yang akan memberikan peningkatan kecepatan 4 ×)? Beberapa, tentu, tapi saya kira bukan angka yang terlalu tinggi.

Saya menduga Anda bukan pengguna biasa :) NumPy sebagian besar adalah C di bawah tenda, dan secepat melakukan hal Anda sendiri di C (yah, kebanyakan lebih cepat). Selain itu, PyPy tidak siap produksi untuk aplikasi ilmiah, dan lebih lambat dalam hal apa pun (karena terbatas pada penggunaan API CPython yang digunakan NumPy, sehingga tidak dapat memperoleh manfaat dari JIT-nya).

Bagaimanapun, ini di luar topik. Menegaskan bahwa soal kecepatan tidaklah kontroversial.

@imneme kami menggunakan metode lemires untuk integer terbatas. Sejak ini a
awal yang baru tanpa warisan atau depresiasi, kami telah berusaha keras untuk memulai
algoritma yang bagus.

Pada hari Senin, 27 Mei 2019, 19:46 imneme [email protected] menulis:

Untuk beberapa forensik dan diskusi, lihat:
https://arxiv.org/pdf/1810.10985.pdf

Buku teks memberikan metode yang secara implisit atau eksplisit mengasumsikan bahwa PRNG bisa
diganti dengan variabel IIDU [0,1) yang sebenarnya tanpa memasukkan materi
kesalahan [20, 7, 2, 16, 15]. Kami menunjukkan di sini bahwa asumsi ini salah
algoritma dalam banyak paket statistik yang umum digunakan, termasuk MATLAB,
Modul acak Python, R, SPSS, dan Stata.

FWIW, ada makalah yang bagus https://arxiv.org/abs/1805.10941 oleh @lemire
https://github.com/lemire tentang menghasilkan angka secara efisien dalam jarak tertentu
tanpa bias. Saya menggunakannya sebagai titik awal untuk menjelajahi dan menjalankan beberapa
tolok ukur juga di artikel saya sendiri
http://www.pcg-random.org/posts/bounded-rands.html . (Saat membuat
64-bit, metode Lemire memang menggunakan perkalian 128-bit untuk menghindari lambat
Divisi 64-bit, dengan semua masalah umum yang mungkin timbul untuk MSVC
pengguna.)

-
Anda menerima ini karena Anda disebutkan.
Balas email ini secara langsung, lihat di GitHub
https://github.com/numpy/numpy/issues/13635?email_source=notifications&email_token=ABKTSRKNAQAK4WIXG5SVLO3PXQUA3A5CNFSM4HPX3CHKYY3PNVWWK3TUL52HS4DFVREXG43VMVBW2HS4DFVREXG42
atau nonaktifkan utasnya
https://github.com/notifications/unsubscribe-auth/ABKTSRKV3KYKRLNMBKNU4JLPXQUA3ANCNFSM4HPX3CHA
.

Kami harus menyediakan _safe_ defaults, dan tebakan terbaik saya saat ini adalah bahwa ini berarti default yang aman untuk semua tujuan dengan pengecualian kriptografi

Itu sulit untuk diperdebatkan. Pertanyaan saya adalah - apa yang aman? Hanya ada berbagai tingkat keacakan semu dengan berbagai properti. Sejauh ini saya belum melihat ada yang memberikan contoh konkret, baik di sini tidak di masalah lain, PR atau utas. Hanya berbicara tentang properti statistik abstrak tidak membantu.

Menurut saya, PCG64 akan menjadi default yang bagus. Kerugian kecepatan pada Windows tidak akan terlihat oleh orang-orang yang menggunakan Anaconda et. al., dan kemungkinan besar akan diperbaiki di beberapa titik. Dengan eksekusi paralel menjadi hal baru di Python, saya juga berpikir memiliki aliran yang dapat diatur adalah properti yang diinginkan.

Saya sangat skeptis bahwa penalti kecepatan PCG64 di bawah Visual Studio adalah sesuatu yang tidak dapat dihapuskan.

Apakah ini dinilai dengan cermat di suatu tempat?

Menegaskan bahwa soal kecepatan tidaklah kontroversial.

Pertanyaan saya adalah - apa yang aman?

Terapkan logika secara konsisten: "apa yang cepat"? Saya tidak tahu apa program numpy yang sebenarnya memiliki kinerja BitGenerator sebagai hambatan yang signifikan. Jika saya menggunakan BitGenerator yang dua kali lebih cepat, apakah saya akan mendapatkan 5% percepatan dalam perhitungan penuh saya? Bahkan mungkin bukan itu. Python-not-being-as-fast-as-C bukanlah masalahnya; hanya saja program berat PRNG yang sebenarnya berguna tidak menghabiskan banyak waktu di BitGenerator . Mungkin salah satu dari pilihan yang tersedia sudah cukup.

Saya sangat skeptis bahwa penalti kecepatan PCG64 di bawah Visual Studio adalah sesuatu yang tidak dapat dihapuskan.

Up-thread Saya menunjukkan bagaimana clang mengkompilasi PCG64 ke dalam perakitan yang dapat kita curi untuk MSVC 64-bit, jadi tidak, saya rasa MSVC pada Windows 64-bit bukanlah masalah yang tidak dapat diatasi.

Yang mungkin lebih rumit adalah PCG64 pada sistem 32-bit, di mana hanya Windows 32-bit yang mungkin masih penting bagi kita. Dalam hal ini, ini bukan tentang MSVC tetapi tentang membatasi diri kita pada ISA 32-bit.

Apa @Kellie Ottoboni [email protected] dan saya menunjukkan adalah bahwa
bahkan untuk masalah ukuran sedang, ruang status MT terlalu kecil untuk diperkirakan
permutasi seragam (n <2100) atau sampel acak seragam (n = 4e8, k = 1000).

Itu mempengaruhi segalanya mulai dari bootstrap hingga tes permutasi hingga MCMC.
Perbedaan antara distribusi yang diinginkan dan yang sebenarnya
distribusi bisa sangat besar (jarak variasi total mendekati
2). Besar dan serius.

Kami belum berupaya untuk memecah MT pada fungsi "statistik" di a
beberapa tahun. Saya cukup yakin ada cara sistematis untuk memecahkannya
(karena jarak distribusi begitu besar).

Bersulang,
Philip

Pada hari Senin, 27 Mei 2019 pukul 12.26 Robert Kern [email protected]
menulis:

Menegaskan bahwa soal kecepatan tidaklah kontroversial.

Pertanyaan saya adalah - apa yang aman?

Terapkan logika secara konsisten: "apa yang cepat"? Saya tidak punya ide bagus
program numpy apa yang sebenarnya memiliki kinerja BitGenerator sebagai
hambatan yang signifikan. Jika saya menggunakan BitGenerator dua kali lebih cepat,
akankah saya mendapatkan kecepatan 5% dalam perhitungan penuh saya? Bahkan mungkin bukan itu.
Python-not-being-as-fast-as-C bukanlah masalahnya; hanya itu saja
Program berat-PRNG yang sebenarnya berguna tidak menghabiskan banyak uang
waktu di BitGenerator. Mungkin salah satu pilihan yang tersedia adalah
cukup.

-
Anda menerima ini karena Anda disebutkan.
Balas email ini secara langsung, lihat di GitHub
https://github.com/numpy/numpy/issues/13635?email_source=notifications&email_token=AANFDWKSMPAG3GFUCUFRXCDPXQYVRA5CNFSM4HPX3CHKYY3PNVWWK3TUL52UVZJKLTD-42VMVBW2HS4DFVREXG43VMVBW2HS4DFVREXG43VMVBW2HS4DFVREXG43VMVBW2HS4DFVREXG43VMVBVBW3DFVREXG43VMVBW2HS4DFVREXG43
atau nonaktifkan utasnya
https://github.com/notifications/unsubscribe-auth/AANFDWIDCPAJJ6DJ3RO332LPXQYVRANCNFSM4HPX3CHA
.

-
Philip B. Stark | Associate Dean, Matematika dan Ilmu Fisika |
Profesor, Departemen Statistik |
Universitas California
Berkeley, CA 94720-3860 | 510-394-5077 | Statistics.berkeley.edu/~stark |
@tokopedia

@pbstark Yang ingin saya lihat adalah implementasi konkret dari masalah (bisa dibuat-buat, tetapi tidak terlalu dibuat-buat) di mana MT atau PRNG 128-bit gagal dan cryptorandom akan bekerja. Dapatkah Anda menunjukkan kumpulan data di luar sana di mana metode resampling memberikan kesimpulan yang salah dengan 128-bit PRNG dan mengoreksi kesimpulan dengan cryptorandom ?

Pindah ke PCG64 membuat batas bawah ukuran masalah menjadi lebih buruk,
karena ruang negaranya bahkan lebih kecil dari MT. Tentu saja bisa
masih menghasilkan keacakan yang "lebih baik" karena dapat mengambil sampel subkelompok
grup permutasi lebih merata daripada MT. Tapi itu harus rusak sebelumnya
500 pilih 10, dan sebelum 21 !.

Bersulang,
Philip

Pada hari Sen, 27 Mei 2019 pukul 12.30 Robert Kern [email protected]
menulis:

Saya sangat skeptis bahwa penalti kecepatan PCG64 di bawah Visual Studio adalah
sesuatu yang tidak bisa dihapus.

Up-thread saya tunjukkan bagaimana clang mengkompilasi PCG64 menjadi assembly yang bisa kita curi
untuk 64-bit MSVC, jadi tidak, saya rasa MSVC pada 64-bit Windows adalah file
masalah yang tidak dapat diatasi.

Yang mungkin lebih rumit adalah PCG64 pada sistem 32-bit, yang hanya 32-bit
Windows mungkin masih penting bagi kita. Dalam hal ini kurang
tentang MSVC daripada tentang membatasi diri pada ISA 32-bit.

-
Anda menerima ini karena Anda disebutkan.
Balas email ini secara langsung, lihat di GitHub
https://github.com/numpy/numpy/issues/13635?email_source=notifications&email_token=AANFDWJFCINQCYGFCI7ULI3PXQZGLA5CNFSM4HPX3CHKYY3PNVWWK3TUL52HS4DFVREXG43V496VBW2HS4DFVREXG43VMVBW2S4DFVREXG43VMVBW2KY3PNVWWK3TUL52HS4DFVREXG43VMVBW2S4DFVREXG43VMVBVW3ZJF
atau nonaktifkan utasnya
https://github.com/notifications/unsubscribe-auth/AANFDWK6QTB65Z4TJU76XKTPXQZGLANCNFSM4HPX3CHA
.

-
Philip B. Stark | Associate Dean, Matematika dan Ilmu Fisika |
Profesor, Departemen Statistik |
Universitas California
Berkeley, CA 94720-3860 | 510-394-5077 | Statistics.berkeley.edu/~stark |
@tokopedia

Saya tidak cukup tahu tentang PRNG untuk benar-benar mempertimbangkannya, saya hanya ingin fokusnya berada pada properti statistik terlebih dahulu (jika jawabannya adalah semuanya sangat sangat baik, baiklah). Satu hal yang saya ingin tahu sekarang adalah distribusi persamaan k-dimensional. Apakah saat ini kami menggunakan varian PCG yang bekerja dengan baik di sini dibandingkan dengan MT? (Berasal dari dinamika nonlinier, itu membuat saya sedikit gugup, tetapi saya tidak memiliki gambaran yang cukup tentang PRNG dan saya tidak akan mendapatkannya dalam 2 hari ke depan ...

Tampaknya tidak mungkin ada banyak pengguna Windows 32-bit di luar sana yang peduli dengan kinerja canggih. Tidak perlu banyak usaha untuk beralih ke 64-bit.

Saya ingin melihatnya juga.

Kami tahu - berdasarkan matematika - bahwa pasti ada banyak masalah besar,
tapi kami belum bisa menunjukkan contoh.

Prinsip kehati-hatian akan mengatakan bahwa karena kita tahu ada yang besar
masalah dan kami tahu bagaimana mencegahnya (CS-PRNGs), kami mungkin juga melakukannya
itu secara default, dan biarkan pengguna kurang berhati-hati jika mereka memilihnya.

Pada hari Senin, 27 Mei 2019 pukul 12.39 Robert Kern [email protected]
menulis:

@pbstark https://github.com/pbstark Yang ingin saya lihat adalah beton
implementasi masalah (bisa dibuat-buat, tapi tidak terlalu dibuat-buat)
MT atau PRNG 128-bit yang gagal dan cryptorandom akan berfungsi. Bisakah kamu
tunjukkan kumpulan data di luar sana yang metode resamplingnya salah
kesimpulan dengan PRNG 128-bit dan kesimpulan yang benar dengan cryptorandom?

-
Anda menerima ini karena Anda disebutkan.
Balas email ini secara langsung, lihat di GitHub
https://github.com/numpy/numpy/issues/13635?email_source=notifications&email_token=AANFDWODTUIPNMVOJB6QP3DPXQ2FPA5CNFSM4HPX3CHKYY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGODWKNFCI#issuecomment-496292489 ,
atau nonaktifkan utasnya
https://github.com/notifications/unsubscribe-auth/AANFDWITAGQFZDQSIFNEHETPXQ2FPANCNFSM4HPX3CHA
.

-
Philip B. Stark | Associate Dean, Matematika dan Ilmu Fisika |
Profesor, Departemen Statistik |
Universitas California
Berkeley, CA 94720-3860 | 510-394-5077 | Statistics.berkeley.edu/~stark |
@tokopedia

k-equidistribution adalah properti ensembel dari keluaran PRNG secara keseluruhan
periode PRNG. Itu hal yang bagus, tapi tidak ada yang mengatakan tentang yang lain
jenis kegagalan keacakan, seperti korelasi serial keluaran.
Ini bar yang relatif rendah.

Pada hari Senin, 27 Mei 2019 pukul 12.48 Sebastian Berg [email protected]
menulis:

Saya tidak cukup tahu tentang PRNG untuk benar-benar mempertimbangkannya, saya hanya ingin
fokuslah pada properti statistik terlebih dahulu (jika jawabannya adalah itu
mereka semua sangat baik, bagus). Satu hal yang saya ingin tahu sekarang adalah
persamaan k-dimensional. Apakah saat ini kami menggunakan varian katakanlah PCG
yang melakukannya dengan baik di sini dibandingkan dengan MT? (Berasal dari dinamika nonlinier, itu
membuat saya sedikit gugup, tetapi saya tidak memiliki cukup gambaran tentang PRNG dan saya
tidak akan mendapatkannya dalam 2 hari ke depan ...

-
Anda menerima ini karena Anda disebutkan.
Balas email ini secara langsung, lihat di GitHub
https://github.com/numpy/numpy/issues/13635?email_source=notifications&email_token=AANFDWPOBTPYHC3XBINQYA3PXQ3HZA5CNFSM4HPX3CHKYY3PNVWWK3TUL52uNHS4DFVREXG42
atau nonaktifkan utasnya
https://github.com/notifications/unsubscribe-auth/AANFDWOEB7KR2YJZWHRRAHLPXQ3HZANCNFSM4HPX3CHA
.

-
Philip B. Stark | Associate Dean, Matematika dan Ilmu Fisika |
Profesor, Departemen Statistik |
Universitas California
Berkeley, CA 94720-3860 | 510-394-5077 | Statistics.berkeley.edu/~stark |
@tokopedia

@pbstark MT gagal dalam sejumlah uji statistik yang dilalui PCG (dan generator lain).

@tokopedia

Jika seseorang ingin MSVC menghasilkan instruksi ror, saya pikir seseorang perlu menggunakan intrinsic "_rotr64".

Juga orang mungkin lebih suka tanda '/ O2' untuk pengoptimalan.

Melihat itu, mungkin memang yang terbaik adalah menuliskannya dalam rakitan, jika seseorang ingin menggunakan PCG64.

Untuk @pbstark , berikut ini beberapa keluaran dari PCG-64 yang diinisialisasi dengan benih yang tidak Anda kenal (sebenarnya, saya bahkan akan memberi tahu Anda alirannya, 0x559107ab8002ccda3b8daf9dbe4ed480 ):

  64bit: 0x21fdab3336e3627d 0x593e5ada8c20b97e 0x4c6dce7b21370ffc
     0xe78feafb1a3e4536 0x35a7d7bed633b42f 0x70147a46c2a396a0
  Coins: TTTHHTTTHHTHTTTTHTHHTTTTTHTTHHTTHHTHHTHHHHHHHHTTHHTTHHTHHHHHTHTHH
  Rolls: 5 3 5 2 5 3 1 6 6 5 4 4 5 5 5 6 2 3 5 3 2 3 2 5 6 2 4 6 2 3 4 6 3
  Cards: 5h 3h 3c 8d 9h 7s Kh Ah 5d Kc Tc 6h 7h 8s Ac 5c Ad Td 8c Qd 2h As
     8h 2d 3s 5s 4d 6d 2s Jd 3d 4h Ks 6s Qc Js Th 9d 9c Ts Jh 4c 2c 9s
     6c 4s 7c 7d Jc Qs Kd Qh

Sekarang, misalkan Anda menginisialisasi generator pcg lain dengan seed yang dipilih secara acak. Mari kita pilih, demi argumen 0xb124fedbf31ce435ff0151f8a07496d3 . Berapa banyak keluaran yang harus kita hasilkan sebelum kita menemukan keluaran yang diketahui ini? Karena saya tahu seed yang saya gunakan di atas, saya dapat menjawab bahwa (melalui fungsi jarak PCG), sekitar 2,5 × 10 ^ 38 (atau sekitar 2 ^ 127,5) keluaran. Sebagai referensi, 10 ^ 38 nanodetik adalah 230 miliar kali usia alam semesta.

Jadi ada urutan di PCG-64 yang benar-benar ada di sana, tetapi, secara praktis Anda tidak akan pernah menemukannya kecuali saya memberi tahu Anda di mana mencarinya. (Dan akan ada lebih banyak kemungkinan jika kita memvariasikan aliran.)

PCG biasa sebenarnya tidak memiliki peluang untuk mengeluarkan Shakespeare Play; Skema generasi diperpanjang PCG sebenarnya dapat menghasilkan Shakespeare Play, tetapi peluangnya untuk melakukannya dalam skenario yang tidak dibuat-buat sangat kecil sehingga pada dasarnya nol juga. Di mata saya, hanya ada sedikit nilai properti yang tidak memiliki konsekuensi praktis sama sekali.

(Selain itu, PRNG yang aman secara kriptografik tidak dijamin akan didistribusikan secara k-dimensional, juga bukan peluru ajaib bagi orang-orang yang menginginkan PRNG yang dapat menghasilkan setiap kemungkinan urutan. Saat Anda menginginkan lebih banyak bit dari PRNG daripada yang dibutuhkan sebagai benih dan penyimpanan sebagai statusnya, tentu ada beberapa urutan bit yang tidak dapat dihasilkan (bukti: dengan prinsip lubang merpati). Dan jika Anda membatasi diri Anda pada jumlah keluaran yang sama seperti yang Anda masukkan sebagai benih, apa yang Anda ' yang benar-benar dicari adalah fungsi hash, atau mungkin hanya fungsi identitas jika input seed Anda benar-benar acak, bukan PRNG.)

Karena penasaran, saya membungkus generator bit penghitung AES menggunakan aesctr.h , waktu dalam ns per nilai acak:

+---------------------+--------------+----------+--------------+
|                     |   Xoshiro256 |    PCG64 |   AESCounter |
|---------------------+--------------+----------+--------------+
| 32-bit Unsigned Int |      3.40804 |  3.59984 |      5.2432  |
| Uniform             |      3.71296 |  4.372   |      4.93744 |
| 64-bit Unsigned Int |      3.97516 |  4.55628 |      5.76628 |
| Exponential         |      4.60288 |  5.63736 |      6.72288 |
| Normal              |      8.10372 | 10.1101  |     12.1082  |
+---------------------+--------------+----------+--------------+

Kerja bagus, @bashtage.

Beberapa hal yang perlu diingat, salah satunya adalah bahwa instruksi AES tertentu dapat bervariasi di seluruh arsitektur dan tidak ada di semua CPU yang digunakan secara aktif, sehingga perlu ada jalur fallback (lambat).

Juga, ini sedikit perbandingan apel dengan jeruk. Selain menggunakan instruksi khusus, kode AES mendapatkan sebagian kecepatannya dari loop unrolling - sebenarnya menghasilkan angka dalam blok dan kemudian membacanya. Membuka gulungan berpotensi mempercepat PRNG apa pun. FWIW, @lemire sebenarnya memiliki versi PCG vektor yang menggunakan instruksi AVX untuk menghasilkan beberapa keluaran sekaligus.

Biarkan saya melihat apakah saya dapat meringkas setidaknya satu poin konsensus: Kita semua setuju bahwa numpy harus berpendapat tentang algoritma BitGenerator yang akan digunakan, dan untuk mempromosikan satu BitGenerator atas yang lain.

Izinkan saya sekali lagi membuat sketsa opsi "Tidak ada default" yang sesuai dengan konsensus tersebut dan menghindari beberapa masalah yang mungkin dimiliki oleh beberapa opsi lain. Jika tidak ada daya tarik, saya akan tutup mulut.

Yang saya maksud dengan opsi "Tidak ada default" adalah "Tidak ada default anonim". Masih ada cara kita bisa mendesain API sedemikian rupa sehingga cara paling nyaman untuk mendapatkan Generator diunggulkan adalah dengan menamai PRNG yang kita nominasikan. Misalnya, kami _tidak_ menyertakan algoritme BitGenerator . Kami mencoba untuk menjaga numpy cukup minimal dan membiarkan penyelesaian ke scipy dan pustaka pihak ketiga lainnya, secara umum, dan mungkin ide yang bagus untuk melakukannya di sini. Keindahan arsitektur saat ini adalah memungkinkan kita untuk memindahkan BitGenerator s itu ke perpustakaan lain. Jadi katakanlah kita hanya menyediakan MT19937 untuk mendukung warisan RandomState dan satu BitGenerator yang kita ingin orang gunakan. Demi argumen, katakanlah itu Xoshiro256 . Mari kita membuat Generator.__init__() konstruktor membutuhkan BitGenerator . Tapi juga, mari kita definisikan fungsi np.random.xoshiro256_gen(seed) yang mengembalikan Generator(Xoshiro256(seed)) bawah sampul. Kami mendokumentasikan bahwa fungsi kenyamanan sebagai cara untuk mendapatkan unggulan Generator .

Sekarang percepat beberapa rilis. Katakanlah kita mendorong PCG64 , ThreeFry , dll. Menjadi random-tng atau scipy atau beberapa paket lain, dan salah satunya menjadi populer karena fitur tambahan atau kelemahan statistik baru ditemukan di Xoshiro256 . Kami memutuskan bahwa kami ingin memperbarui pendapat numpy tentang BitGenerator harus digunakan orang menjadi PCG64 . Kemudian yang kita lakukan adalah menambahkan kelas PCG64 BitGenerator dan menambahkan fungsi np.random.pcg64_gen(seed) . Kami menambahkan peringatan penghentian ke np.random.xoshiro256_gen(seed) untuk mengatakan bahwa itu bukan lagi algoritme yang disukai: kami menyarankan kode baru harus menggunakan np.random.pcg64_gen(seed) , tetapi untuk terus menggunakan algoritme Xoshiro256 tanpa peringatan, mereka harus secara eksplisit menggunakan Generator(Xoshiro256(seed)) .

Saya pikir ini menghindari beberapa masalah yang saya miliki dengan API "anonim" (yaitu Generator(seed) , Generator(DefaultBitGenerator(seed)) , np.random.default_gen(seed) ). Kami dapat mendukung algoritme yang tidak lagi disukai selamanya. Kita tidak perlu membuat konstruktor "pilihan" kita yang beropini melakukan sesuatu yang berbeda ketika kita mengubah opini kita. Karena kami menggunakan nama asli untuk membedakan hal-hal daripada nomor versi, Anda selalu tahu cara memperbarui kode untuk mereproduksi hasil lama (jika Anda tidak tahan dengan peringatan tidak berbahaya karena alasan tertentu). Anda bahkan dapat mengambil kode tanpa asal atau mencatat nomor rilis numpy dan melakukan pembaruan itu. Pada saat yang sama, dengan membatasi jumlah algoritme seminimal mungkin dan menjadikan praktik terbaik sebagai cara _easiest_ untuk bekerja dengan perpustakaan, kami dapat mengungkapkan pendapat numpy secara efektif.

Bagaimana kedengarannya? Kami masih harus berusaha keras untuk membuat pilihan yang solid untuk BitGenerator untuk rilis pertama. Itu masih penting.

Tampaknya tidak mungkin ada banyak pengguna Windows 32-bit di luar sana yang peduli dengan kinerja canggih. Tidak perlu banyak usaha untuk beralih ke 64-bit.

Saya setuju. Karena masalah dengan PCG64 di Win32 hanyalah kinerja (dan salah satu yang mungkin dapat kami perbaiki dengan sedikit usaha), apakah Anda setuju bahwa ini bukan pemblokir?

Jika seseorang ingin MSVC menghasilkan instruksi ror, saya pikir seseorang perlu menggunakan intrinsic "_rotr64".

Juga orang mungkin lebih suka tanda '/ O2' untuk pengoptimalan.

Terima kasih! @imneme menunjukkan semua kesalahan ini untuk saya. :-)

@seberg Apakah Anda memiliki kutipan dari bidang Anda yang membuat Anda waspada? Misalnya, makalah yang menunjukkan bahwa properti equidistribution k = 623 MT19937 memperbaiki masalah dalam simulasi dinamika nonlinear yang disebabkan oleh PRNG yang lebih kecil? Saya mungkin bisa memberikan jaminan yang lebih spesifik dengan itu sebagai referensi. Dalam _general_, pandangan saya tentang pemerataan adalah bahwa Anda biasanya ingin pemerataan PRNG mendekati maksimum yang diizinkan oleh ukuran negara PRNG. Dalam _practice_, jika PRNG Anda cukup besar untuk tujuan Anda dalam hal lain (melewati PractRand, memiliki periode lebih besar dari kuadrat jumlah sampel yang ingin Anda gambar, dll.), Saya tidak pernah melihat banyak alasan untuk khawatir tentang tepat k . Orang lain mungkin memiliki pendapat berbeda, dan mungkin ada masalah khusus di bidang Anda yang tidak saya ketahui. Jika demikian, maka ada solusi khusus yang tersedia!

Karena penasaran, saya menyelesaikan generator bit penghitung AES menggunakan aesctr.h

Saya bisa saja salah, tetapi saya tidak percaya bahwa ini akan membantu masalah @pbstark . AES-CTR adalah CS-RNG, tetapi tidak semua CS-RNG memiliki periode besar yang dibutuhkan seseorang untuk (secara teoritis) dapat mencapai semua permutasi k! untuk k . Penghitung masih berupa angka 128-bit dan setelah digulung, Anda telah mencapai akhir periode. @pbstark mengadvokasi PRNG dalam jangka waktu sangat besar, yang sebagian besar kebetulan adalah CS-RNG.

Secara umum, pandangan saya tentang pemerataan adalah bahwa Anda umumnya ingin pemerataan PRNG mendekati maksimum yang diizinkan oleh ukuran negara bagian PRNG.

Meskipun beberapa orang menganggap pemerataan maksimal sebagai properti yang diinginkan, itu juga dapat dianggap cacat (dan ada makalah di luar sana yang mengatakannya). Jika kita memiliki PRNG _k_-bit dan setiap urutan _k_-bit terjadi tepat satu kali, maka itu akan melanggar masalah ulang tahun yang mengatakan bahwa kita mengharapkan untuk melihat keluaran berulang setelah sekitar 2 ^ (k / 2) keluaran. ( Saya menulis tes statistik masalah ulang tahun berdasarkan ide-ide ini . Ini dengan benar mendeteksi tidak adanya pengulangan yang tidak masuk akal secara statistik di SplitMix, 64-bit-output 64-bit-state PRNG, dan Xoroshiro64 +, 32-bit-output 64-bit -state 2-dimensionally-equidistributed PRNG, antara lain.)

Menariknya, meskipun sangat praktis untuk menulis tes statistik yang akan gagal dalam PRNG karena kurangnya pengulangan 64-bit (atau terlalu banyak pengulangan - kami mengharapkan distribusi Poisson), sebaliknya _not_ praktis untuk menulis tes yang akan mendeteksi penghilangan 36,8% dari semua nilai 64-bit jika kita tidak tahu apa-apa tentang nilai mana yang dihilangkan.

Jelas pengujian untuk kekurangan pengulangan yang tidak diharapkan mulai menjadi tidak praktis untuk dijalankan saat _k_ semakin besar, tetapi saat kita mencapai ukuran status (dan periode) yang lebih besar dan lebih besar, ukuran yang ditambahkan berarti bahwa keduanya tidak praktis untuk menunjukkan bahwa PRNG dengan distribusi merata maksimal cacat karena gagal untuk mengulang dan sama tidak praktisnya untuk menunjukkan bahwa PRNG dengan distribusi yang tidak terdistribusi secara maksimal cacat untuk mengulangi beberapa urutan _k_-bit (dengan cara yang masuk akal secara statistik) dan menghilangkan yang lain sepenuhnya. Dalam kedua kasus tersebut, PRNG terlalu besar bagi kami untuk dapat membedakan keduanya.

Saya ingin melihatnya juga. Kami tahu - berdasarkan matematika - bahwa pasti ada banyak masalah besar, tetapi kami belum dapat menunjukkan contoh. Prinsip kehati-hatian akan mengatakan bahwa karena kita tahu ada masalah besar dan kita tahu bagaimana mencegahnya (CS-PRNG), kita mungkin juga melakukannya secara default, dan membiarkan pengguna kurang berhati-hati jika mereka memilih untuk melakukannya.

Saya harus mengatakan bahwa saya tidak terbujuk oleh argumen dan bukti ini. Karena itu, saya tidak akan merasa nyaman berdiri di depan pengguna numpy dan memberi tahu mereka bahwa mereka harus beralih karena alasan ini. Saya tidak siap untuk mempertahankan pernyataan ini, itulah sebabnya saya meminta contoh-contoh ini. Itu akan menjadi persuasif dan akan mempersiapkan saya untuk mempertahankan posisi yang Anda rekomendasikan untuk kami ambil ini.

Ada banyak sifat di mana PRNG terbatas tidak memenuhi RNG yang sebenarnya. Dan ada banyak perhitungan yang ingin kami lakukan, secara teoritis, bergantung pada properti RNG yang sebenarnya (atau setidaknya, kami belum membuktikan secara ketat seberapa banyak kami dapat mengendurkannya). Tetapi banyak dari kekurangan tersebut hanya memiliki efek yang sangat kecil dan praktis tidak terlihat pada hasil komputasi aktual yang kami lakukan. Pelanggaran ini tidak bersifat dispositif, all-or-nothing, go / no-go. Mereka memiliki ukuran efek, dan kita dapat mentolerir lebih banyak atau lebih sedikit efeknya.

Anda tentu saja menunjukkan dengan meyakinkan bahwa PRNG berukuran tertentu tidak dapat menghasilkan semua permutasi k! secara merata untuk beberapa k . Langkah yang saya lewatkan adalah bagaimana kegagalan untuk dapat menghasilkan semua permutasi tersebut memengaruhi komputasi konkret yang saya ingin lakukan. Saya melewatkan pengujian yang Anda sarankan untuk kami tambahkan ke PractRand atau TestU01 yang akan mendemonstrasikan masalah tersebut kepada orang-orang.

Salah satu baris analisis yang menurut saya sangat informatif dari makalah PCG @imneme adalah mendapatkan beberapa versi status yang lebih kecil dari setiap PRNG dan melihat dengan tepat di mana mereka mulai gagal TestU01. Itu memberi kita cara untuk membandingkan arsitektur PRNG secara teratur daripada hanya mengatakan, semua-atau-tidak sama sekali, "X PRNG lolos" atau gagal. Ini juga memungkinkan kami memperkirakan berapa banyak ruang kepala yang kami miliki pada ukuran negara bagian yang digunakan (yang lulus TestU01 pada sejumlah besar GiB sampel). Adakah perhitungan konkret yang dapat Anda lakukan yang menunjukkan masalah dengan PRNG 8-bit? PRNG 16-bit? Kemudian kita dapat melihat apakah tes baru ini akan memberi tahu kita informasi tentang PRNG lebih awal dari TestU01 / PractRand saat ini. Dan itu akan sangat membantu.

Di sisi lain, jika dibutuhkan _more_ data yang diambil dari PRNG untuk menunjukkan kegagalan berdasarkan permutasi ini daripada titik kegagalan PRNG kecil untuk rangkaian pengujian saat ini di PractRand, maka saya akan menyimpulkan bahwa masalah ini tidak praktis perhatian, dan kami dapat menggunakan "melewati PractRand" sebagai proxy yang baik untuk apakah masalah permutasi akan memiliki efek praktis pada perhitungan saya atau tidak.

Tetapi sampai saya memiliki program di tangan saya yang dapat saya jalankan dan menunjukkan kepada orang-orang masalahnya, saya tidak nyaman mendorong CS-PRNG atas dasar ini. Saya tidak akan bisa menjelaskan pilihan itu dengan meyakinkan.

Bagi mereka yang menuntut saat mengocok 32 item, semuanya 32! pengocokan (yaitu, semua 263130836933693530167218012160000000 di antaranya) harus dapat dihasilkan, daripada PRNG yang hanya menyediakan sampel acak dari 32 sampel tersebut! mengocok, saya sebenarnya akan mengatakan bahwa jika Anda akan menuntut jumlah besar, Anda hanya tidak berpikir cukup besar .

Dengan demikian saya akan (dengan bercanda) mengklaim bahwa urutan keluarnya shuffle itu juga tidak harus ditentukan sebelumnya! Jelas Anda harus menuntut bahwa itu menghasilkan semua 32! mengocok di semua kemungkinan pesanan - (32!)! adalah yang Anda butuhkan! Tentu saja, ini akan membutuhkan 3,8 × 10 ^ 18 exabyte untuk status dan jumlah entropi yang sama untuk diinisialisasi, tetapi pasti sepadan untuk mengetahui bahwa semuanya ada di sana.

... Kami menambahkan peringatan penghentian ke np.random.xoshiro256_gen(seed) untuk mengatakan bahwa ini bukan lagi algoritme pilihan: kami menyarankan kode baru harus menggunakan np.random.pcg64_gen(seed) , tetapi untuk terus menggunakan algoritme Xoshiro256 tanpa peringatan, mereka harus secara eksplisit menggunakan Generator(Xoshiro256(seed))

Itu masih mengganggu pengguna dengan penghentian, dan dengan nama yang terdengar aneh yang sebenarnya tidak ingin mereka ketahui.

NEP mengatakan: Kedua, melanggar kompatibilitas streaming untuk memperkenalkan fitur-fitur baru atau meningkatkan kinerja akan diizinkan dengan hati-hati.

Jika ada alasan yang cukup baik untuk memperbarui default kami, maka hanya melakukan itu dan memutus reproduktifitas bit-demi-bit untuk pengguna yang tidak secara eksplisit menentukan algoritme adalah opsi yang lebih baik imho (dan yang Anda perdebatkan sebelumnya).

Yang saya maksud dengan opsi "Tidak ada default" adalah "Tidak ada default anonim".

Jadi, apakah maksud Anda bahwa Anda _ ingin_ pengguna mengetahui nama PRNG yang mereka gunakan?

Lihat ini dari sudut pandang pengguna. Cukup sulit untuk membuat mereka beralih dari np.random.rand & co menjadi np.random.RandomState() dan kemudian menggunakan metode. Sekarang kami akan memperkenalkan sistem yang lebih baik, dan apa yang mereka lihat adalah np.random.xoshiro256_gen() ? Itu akan menjadi kegunaan regresi utama.

Jadi, apakah maksud Anda bahwa Anda _ ingin_ pengguna mengetahui nama PRNG yang mereka gunakan?

Tidak, ini untuk mengurangi masalah memiliki API "target bergerak yang ditunjuk" seperti default_generator(seed) yang sedang dikerjakan orang-orang (misalnya argumen @shoyer version ).

Mempertahankan kompatibilitas streaming (yang tidak diklaim oleh NEP 19) adalah hal sekunder dari kerusakan API. BitGenerator s yang berbeda memiliki API efektif yang berbeda, tergantung pada set fiturnya (aliran yang dapat diatur, jumpahead, terutama, meskipun bisa ada yang lain, tergantung pada seberapa parameterizable PRNG itu). Jadi beberapa perubahan dalam pemilihan PRNG default kita sebenarnya akan merusak kode (yaitu tidak lagi berjalan atau tidak lagi berjalan dengan benar), tidak hanya mengubah nilai yang keluar.

Misalnya, pertama-tama kita memilih PCG64 . Ini memiliki status 128-bit, aliran 2 ^ 127 yang dapat diatur, dan mengimplementasikan jumpahead; bagus dan berfitur lengkap. Jadi orang mulai menulis default_generator(seed, stream=whatever) . Sekarang katakanlah pekerjaan mendatang menemukan beberapa kekurangan statistik utama di dalamnya yang membuat kita ingin beralih ke pekerjaan lain. PRNG berikutnya yang kami promosikan sebagai default harus memiliki status> = 128-bit (mudah; Saya tidak akan merekomendasikan sesuatu yang lebih kecil sebagai default tujuan umum), jumpahead (hard!),> = 2 ^ 127 aliran yang dapat diatur (whoo, boy!), agar tidak merusak penggunaan default_generator() yang sudah ada di code. Sekarang mungkin kita bisa hidup dengan ratchet itu.

@shoyer menyarankan bahwa mungkin kita bisa membuat default BitGenerator selalu dengan sengaja tertatih-tatih hanya dengan fitur penyebut yang paling tidak umum. Itu akan berhasil! Tapi itu juga akan kehilangan kesempatan untuk mempromosikan aliran yang dapat diatur untuk menyelesaikan masalah aliran paralel seperti yang ingin dilakukan

Sekarang kita akan memperkenalkan sistem yang lebih baik, dan yang mereka lihat adalah np.random.xoshiro256_gen() ? Itu akan menjadi kegunaan regresi utama.

Jika nama yang terdengar aneh adalah masalahnya, maka saya akan senang menggunakan nama yang lebih ramah dan umum, selama kebijakannya sama (kami menambahkan fungsi baru dan memulai peringatan tentang yang lama). Saya akan menganggap itu setara. Kita seharusnya tidak melakukan ini terlalu sering.

Saya juga baik-baik saja jika kita memutuskan untuk hidup dengan ratchet dan menghindari mekanisme version .

Saya mengambil "default" adalah kita bisa membiarkannya sebagai detail implementasi, sehingga Generator() akan selalu berfungsi. Saya akan membahas ini dengan catatan kehati-hatian yang kuat bahwa satu-satunya cara untuk mendapatkan hasil yang selalu dapat direproduksi (hingga perubahan di Generator) adalah dengan menggunakan sintaks Generator(BitGenerator(kwarg1=1,kwargs2=b,...))

Tidak praktis menyembunyikan detail implementasi karena akses ke status diperlukan pengawetan.

Alternatifnya hanya memperlakukannya seperti fungsi lain - dan pembuatan acak secara umum - dan melalui siklus penghentian standar jika ada kebutuhan mendesak untuk berubah. Ini tidak akan pernah memengaruhi pengguna yang melakukan sesuatu dengan benar, dan dengan peringatan yang cukup di dokumen, dimungkinkan untuk mendapatkan hit rate yang layak untuk ini, setidaknya di antara proyek-proyek besar. Apa yang saya sarankan di sini adalah bahwa orang bisa melupakan jaminan kompatibilitas streaming yang pernah dibuat saat memikirkan API baru.

@bashtage di # 13650 Saya melarang akses ke Generator().bit_generator dengan cara yang masih memungkinkan pengawetan tanpa akses langsung ke state . Ini melewati test_pickle sedikit ditulis ulang dengan cara yang memungkinkan penggunaan di python Thread s

Pertanyaan saya adalah - apa yang aman? Hanya ada berbagai tingkat keacakan semu dengan berbagai properti. Sejauh ini saya belum melihat ada yang memberikan contoh konkret, baik di sini tidak di masalah lain, PR atau utas.

"Lulus PractRand di _N_ GiB" untuk beberapa _N_ (512, 1024) adalah definisi yang bisa dilalui jika Anda menginginkan kriteria lulus / gagal garis terang yang jelas. Jika Anda menginginkan contoh konkret, MT dan variannya akan dikecualikan berdasarkan kriteria ini. Kami juga menghapus beberapa anggota keluarga Xoroshiro yang lebih tua dari PR karena ini.

Jika Anda menginginkan tampilan kualitas statistik yang lebih canggih yang memungkinkan untuk pemeringkatan ordinal algoritme, saya merekomendasikan kepada Anda Bagian 3 dari makalah PCG @imneme , yang menggunakan profil varian algoritme dengan status yang dikurangi untuk mendapatkan gambaran tentang bagaimana banyak "ruang kepala" yang dimiliki setiap algoritme lengkap. Ini sangat mirip dengan bagaimana kriptografer menganalisis algoritma kripto yang berbeda. Opsi apa pun yang layak yang sedang diperiksa harus lulus kriteria dasar "tidak rusak", tetapi ini tidak membantu Anda menentukan peringkat pesaing. Sebaliknya, mereka membangun versi pengurangan-putaran dari algoritma pesaing dan melihat seberapa berkurang Anda harus mendapatkan sebelum mereka dapat memecahkannya. Jika algoritme penuh putaran-N rusak pada N-1, maka ruang kepala yang sangat sedikit, dan kriptografer mungkin akan menghindarinya. Demikian pula, jika 128-bit BitGenerator melewati PractRand tetapi versi 120-bitnya gagal, itu mungkin cukup berisiko.

@ Mattip Sepertinya masuk akal. Meskipun seseorang di suatu tempat akan melakukannya

import gc
state = [o for o in gc.get_objects() if 'Xoshiro256' in str(o)][0].state

jika mereka ingin mendalami itu, tidak masalah. Saya hanya ingin membantu pengguna non-ahli

Ini melewati test_pickle sedikit ditulis ulang dengan cara yang memungkinkan penggunaan di python Thread s

Perlu dicatat bahwa ini adalah masalah luar biasa (# 9650) - idealnya Generator() akan dipasang kembali di utas anak. IIRC ini hanya praktis dengan Python> = 3.7

Saya mengambil "default" adalah kita bisa membiarkannya sebagai detail implementasi, sehingga Generator() akan selalu berfungsi. Saya akan membahas ini dengan catatan kehati-hatian yang kuat bahwa satu-satunya cara untuk mendapatkan hasil yang selalu dapat direproduksi (hingga perubahan di Generator) adalah dengan menggunakan sintaks Generator(BitGenerator(kwarg1=1,kwargs2=b,...))

Ada dua jenis reproduktifitas yang perlu kita bedakan. Salah satunya adalah saya menjalankan program saya dua kali dengan benih yang sama dan mendapatkan hasil yang sama. Itulah yang perlu kami dukung. Yang lainnya adalah reproduktifitas di seluruh versi numpy, yang telah kami sangkal, setidaknya dalam arti yang paling ketat.

Argument-less Generator() , yaitu "beri saya PRNG yang diunggulkan secara sewenang-wenang yang direkomendasikan oleh numpy" bukanlah kasus penggunaan utama. Itu tidak membutuhkan banyak dukungan. "Beri saya PRNG yang direkomendasikan numpy dengan _this_ seed", dan itulah opsi yang kami diskusikan. Kami membutuhkan cara bagi numpy untuk mengungkapkan pendapat tentang cara mendapatkan PRNG unggulan, dan cara itu harus mudah dan nyaman bagi pengguna (atau mereka tidak akan menggunakannya). Saya _suka_ menamai algoritme (meskipun melalui fungsi yang lebih nyaman), tetapi @rgommers berpikir itu langkah yang terlalu jauh, dan saya bersimpati untuk itu.

Argument-less Generator (), yaitu "beri saya PRNG yang diunggulkan secara sewenang-wenang yang direkomendasikan oleh numpy" bukanlah kasus penggunaan utama. Itu tidak membutuhkan banyak dukungan. "Beri saya PRNG yang direkomendasikan numpy dengan benih ini", dan itulah opsi yang kami diskusikan. Kami membutuhkan cara bagi numpy untuk mengungkapkan pendapat tentang cara mendapatkan PRNG unggulan, dan cara itu harus mudah dan nyaman bagi pengguna (atau mereka tidak akan menggunakannya). Saya suka menamai algoritme (meskipun melalui fungsi yang lebih nyaman), tetapi @rgommers berpikir itu langkah yang terlalu jauh, dan saya bersimpati untuk itu.

Saya berpendapat bahwa pengguna sebenarnya tidak siap untuk menyediakan benih yang baik. Misalnya, berapa banyak pengguna yang tahu cara yang benar untuk menyemai Mersenne Twister? Ini tidak semudah yang Anda pikirkan - jika Anda tidak memberinya 624 bilangan bulat 32-bit acak (untuk menyediakan 19937 bit status), Anda salah melakukannya.

Jadi sebenarnya saya akan mengatakan bahwa cara yang tepat bagi pengguna untuk mendapatkan hasil yang dapat direproduksi adalah dengan membuat PRNG (tanpa menyediakan benih, membiarkannya disemai dengan baik secara otomatis) dan kemudian mengasinkannya.

Jika pembahasannya hanya tentang cara yang benar maka I'm for
Generator(BitGenerator(**kwargs)) karena ini hanya akan digunakan oleh
pengguna semiaware yang peduli tentang reproduksi.

Saya pikir default yang digunakan untuk Generator() masalah karena ini akan terjadi
ditafsirkan sebanyak pilihan yang dianggap dan karenanya dianggap sebagai a
rekomendasi saat menggunakan formulir unggulan.

Hanya untuk membuang satu lagi, metode kelas Generator.seeded(seed[, bit_generator]) where bit generator is a string. This would allow the pattern of switching from one value to None to warn if the default was going to change, like lstsq. I would also only support a limited pallatte of but generators initially (i.e. 1). Doesn't make it easy to expose advanced features I suppose. In a perfect world it would use kwarg only to allow any keyword argument to be used which avoids most depreciation problems. Of course, this doesn't really need to be a class function, just seeded`.

Pada Sel, 28 Mei 2019, 16:38 Robert Kern [email protected] menulis:

Saya mengambil "default" adalah kita bisa membiarkannya sebagai implementasi
detail, sehingga Generator () akan selalu berfungsi. Saya akan menawar ini dengan
catatan kehati-hatian yang kuat bahwa satu-satunya cara untuk mendapatkan hasil yang selalu dapat direproduksi
(sampai perubahan Generator) adalah menggunakan sintaks
Generator (BitGenerator (kwarg1 = 1, kwargs2 = b, ...))

Ada dua jenis reproduktifitas yang perlu kita bedakan. Satu adalah
bahwa saya menjalankan program saya dua kali dengan benih yang sama dan mendapatkan hasil yang sama.
Itulah yang perlu kami dukung. Yang lainnya adalah reproduktifitas
versi numpy, yang kami sangkal, setidaknya dalam arti yang paling ketat.

Argument-less Generator (), yaitu "beri saya PRNG yang diunggulkan secara sewenang-wenang
numpy recommends "bukan kasus penggunaan utama. Ini tidak membutuhkan banyak
dukung. "Beri saya PRNG yang direkomendasikan numpy dengan benih ini " adalah,
dan untuk apa kami mendiskusikan opsi. Kami membutuhkan cara untuk numpy
mengutarakan pendapat tentang cara mendapatkan PRNG yang diunggulkan, dan itu perlu dilakukan
mudah dan nyaman bagi pengguna (atau mereka tidak akan menggunakannya). Saya suka
menamai algoritme (meskipun melalui fungsi yang lebih nyaman), tetapi
@rgommers https://github.com/rgommers menganggap itu langkah yang terlalu jauh, dan
Saya bersimpati untuk itu.

-
Anda menerima ini karena Anda disebutkan.
Balas email ini secara langsung, lihat di GitHub
https://github.com/numpy/numpy/issues/13635?email_source=notifications&email_token=ABKTSRKA4SSNW6XZEVFUMCDPXVGW5A5CNFSM4HPX3CHKYY3PNVWWK3TUL52HS4DNTDVREXG43VWMVWR2HS4DFDNORXG43
atau nonaktifkan utasnya
https://github.com/notifications/unsubscribe-auth/ABKTSROCMLHG6E6BLWI6TWDPXVGW5ANCNFSM4HPX3CHA
.

Pada Sel, 28 Mei 2019, 16:38 Robert Kern [email protected] menulis:

Saya mengambil "default" adalah kita bisa membiarkannya sebagai implementasi
detail, sehingga Generator () akan selalu berfungsi. Saya akan menawar ini dengan
catatan kehati-hatian yang kuat bahwa satu-satunya cara untuk mendapatkan hasil yang selalu dapat direproduksi
(sampai perubahan Generator) adalah menggunakan sintaks
Generator (BitGenerator (kwarg1 = 1, kwargs2 = b, ...))

Ada dua jenis reproduktifitas yang perlu kita bedakan. Satu adalah
bahwa saya menjalankan program saya dua kali dengan benih yang sama dan mendapatkan hasil yang sama.
Itulah yang perlu kami dukung. Yang lainnya adalah reproduktifitas
versi numpy, yang kami sangkal, setidaknya dalam arti yang paling ketat.

Argument-less Generator (), yaitu "beri saya PRNG yang diunggulkan secara sewenang-wenang
numpy recommends "bukan kasus penggunaan utama. Ini tidak membutuhkan banyak
dukung. "Beri saya PRNG yang direkomendasikan numpy dengan benih ini " adalah,
dan untuk apa kami mendiskusikan opsi. Kami membutuhkan cara untuk numpy
mengutarakan pendapat tentang cara mendapatkan PRNG yang diunggulkan, dan itu perlu dilakukan
mudah dan nyaman bagi pengguna (atau mereka tidak akan menggunakannya). Saya suka
menamai algoritme (meskipun melalui fungsi yang lebih nyaman), tetapi
@rgommers https://github.com/rgommers menganggap itu langkah yang terlalu jauh, dan
Saya bersimpati untuk itu.

-
Anda menerima ini karena Anda disebutkan.
Balas email ini secara langsung, lihat di GitHub
https://github.com/numpy/numpy/issues/13635?email_source=notifications&email_token=ABKTSRKA4SSNW6XZEVFUMCDPXVGW5A5CNFSM4HPX3CHKYY3PNVWWK3TUL52HS4DNTDVREXG43VWMVWR2HS4DFDNORXG43
atau nonaktifkan utasnya
https://github.com/notifications/unsubscribe-auth/ABKTSROCMLHG6E6BLWI6TWDPXVGW5ANCNFSM4HPX3CHA
.

Dari perspektif kegunaan, saya pikir kita benar-benar perlu mendukung Generator(seed) . Jika tidak, dihadapkan dengan membuat pilihan yang tidak siap mereka buat, pengguna hanya akan bertahan dengan RandomState .

Untuk membuat versi pembuat bit default di Generator , kita dapat menggunakan bit_version=1 alih-alih version=1 , meskipun saya juga setuju dengan membatalkan ide version . Saya rasa pengguna tidak perlu sering menyetel generator bit secara eksplisit.

Preferensi saya untuk menyelesaikan kasus penggunaan tertentu yang memerlukan fitur generator tertentu akan merancang API BitGenerator generik baru yang menyembunyikan detail implementasi. Ini bisa ditambahkan ke DefaultBitGenerator atau dimasukkan ke dalam kelas baru jika penggunaannya melibatkan pengorbanan, misalnya, ParallelBitGenerator .

Saya pasti ingin menghindari peringatan tentang perubahan masa depan dalam aliran RNG karena mengubah generator bit default. Peringatan ini hanya akan menjadi gangguan bagi sebagian besar pengguna yang tidak bergantung pada detail seperti itu, tetapi yang menetapkan Generator seed hanya untuk menghentikan nomor acak mereka berubah secara spontan.

pengguna hanya akan tetap menggunakan RandomState.

Tidak apa-apa, mereka bukan pengadopsi awal. Saya berusaha keras (mungkin terlalu keras?) Untuk API yang layak seminimal mungkin, karena kami selalu dapat memperluas API tetapi jauh lebih sulit untuk menciutkannya. Nuansa antara Generator(Philox()) , Generator(seed(3)) dan Generator(bit_version=1) agak sulit dilihat sampai ini diketahui oleh pengguna akhir.

Mari kita dapatkan versi pertama tanpa Generator(seed) dan dapatkan umpan balik.

Mari kita dapatkan versi pertama tanpa Generator(seed) dan dapatkan umpan balik.

Oke, saya tidak keberatan serius di sini. Dalam hal ini, kami mungkin juga perlu menentukan BitGenerator lengkap untuk saat ini juga.

Jadi sebenarnya saya akan mengatakan bahwa cara yang tepat bagi pengguna untuk mendapatkan hasil yang dapat direproduksi adalah dengan membuat PRNG (tanpa menyediakan benih, membiarkannya disemai dengan baik secara otomatis) dan kemudian mengasinkannya.

Saya mengatakan hal yang sama, tetapi saya hanya mendapatkan sedikit daya tarik dengannya. Seperti yang Anda katakan, "Yah, hanya karena sesuatu adalah ide yang buruk tidak berarti orang tidak mau melakukannya!"

Sebagian dari masalah ini diperburuk oleh status MT yang sangat besar, yang benar-benar memerlukan serialisasi ke file. Sulit untuk membuat dansa berbasis file itu menjadi API termudah yang tersedia sehingga pengguna ingin menggunakannya. Segalanya akan lebih baik dengan PRNG default dengan status yang jauh lebih kecil. 128-bit adalah ukuran UUID, yang cukup kecil untuk dicetak dalam hex dan copy-paste. Jadi pola yang baik mungkin untuk menulis program Anda sedemikian rupa sehingga defaultnya adalah benih entropi yang baik dan kemudian mencetak statusnya dengan cara yang dapat Anda salin-tempel saat Anda menjalankan program di lain waktu.

❯ python secret_prng.py
Seed: 0x977918d0c7da45e5168f72005586500c
...
Result = 0.7223650399276123

❯ python secret_prng.py
Seed: 0xe8962534e5fb585483b86119fcb852ce
...
Result = 0.10640984721018876

❯ python secret_prng.py --seed 0xe8962534e5fb585483b86119fcb852ce
Seed: 0xe8962534e5fb585483b86119fcb852ce
...
Result = 0.10640984721018876

Tidak yakin apakah pola seperti ini akan memberikan kesederhanaan dan bukti masa depan.

NumPy 1. berikutnya

class Generator:
    def __init__(bitgen_or_seed=None, *, bit_generator='pcg64', inc=0):

Jumlah 1.20.x

`` python
Generator kelas:
def __init __ (bitgen_or_seed = Tidak ada, *, bit_generator = Tidak ada, inc = Tidak ada):
jika bit_generator bukan None atau inc bukan None:
warn ('Defaultnya berubah dari PCG64 ke AESCtr. Kata kunci inc'
'Argumen sudah tidak digunakan lagi dan akan muncul di masa depan', FutureWarning)
`` ''

Jumlah 1.22

`` python
Generator kelas:
def __init __ (bitgen_or_seed = Tidak ada, *, bit_generator = 'aesctr', inc = Tidak ada, counter = 0):
jika bit_generator == 'pcg64' atau inc bukan Tidak ada:
meningkatkan Pengecualian ('PCG tidak lagi didukung dan inc telah dihapus')
`` ''

Tidak yakin apakah pola seperti ini akan memberikan kesederhanaan dan bukti masa depan.

Seperti yang saya sebutkan di atas di https://github.com/numpy/numpy/issues/13635#issuecomment -496589421, menurut saya ini akan mengejutkan dan membuat frustasi bagi sebagian besar pengguna. Saya lebih suka menyediakan objek BitGenerator eksplisit daripada berencana untuk mulai mengeluarkan peringatan jika pengguna belum menyetel semua argumen opsional. Itu seharusnya menjadi pilihan terakhir, untuk kasus di mana kami menemukan bahwa API rusak dengan cara yang tidak kami antisipasi.

Masalahnya adalah masa transisi. Setiap orang yang menggunakan default tiba-tiba akan mendapatkan peringatan tanpa cara yang bagus untuk beralih selama masa transisi. Atau setidaknya, Anda memindahkannya dari "keadaan energi rendah" dari Generator(seed) ke "keadaan energi tinggi" yang kurang nyaman yaitu Generator(seed, bit_generator='aesctr') . Karena tujuan dari API ini adalah untuk menyediakan "keadaan energi rendah" yang nyaman, maka kami telah gagal dalam tujuan kami selama transisi ini. Kami melakukan ini sekali dengan salah satu fungsi histogramming kami, IIRC, dan itu adalah mimpi buruk.

Ini umum terjadi pada semua depresiasi yang mencoba mengubah arti argumen pada tempatnya. Penghentian yang _memindahkan_ Anda dari satu fungsi ke fungsi lainnya jauh lebih mudah untuk dikelola, dan itulah yang saya anjurkan.

Mari kita dapatkan versi pertama tanpa Generator(seed) dan dapatkan umpan balik.

Yang Anda maksud dengan "versi pertama" adalah rilis numpy lengkap? Atau hanya menggabungkan PR (yang sejak itu terjadi)?

Jika rilis numpy penuh, maka kita masih memiliki beberapa hal yang harus ditentukan, seperti berapa BitGenerator s yang kita sertakan. Jika kami menyertakan pelengkap saat ini lengkap, maka kami telah mengungkapkan beberapa opsi.

Penghentian yang _memindahkan_ Anda dari satu fungsi ke fungsi lainnya jauh lebih mudah untuk dikelola, dan itulah yang saya anjurkan.

+1 setuju

Tidak, ini untuk mengurangi masalah memiliki API "target bergerak yang ditunjuk" seperti default_generator (seed) yang sedang dikerjakan orang (misalnya argumen versi @shoyer ).

Mempertahankan kompatibilitas streaming (yang tidak diklaim oleh NEP 19) adalah hal sekunder dari kerusakan API. BitGenerator yang berbeda memiliki API efektif yang berbeda pula

Ah oke, sekarang lebih masuk akal bagiku.

Jika nama yang terdengar aneh adalah masalahnya, maka saya akan senang menggunakan nama yang lebih ramah dan umum, selama kebijakannya sama (kami menambahkan fungsi baru dan memulai peringatan tentang yang lama). Saya akan menganggap itu setara. Kita seharusnya tidak melakukan ini terlalu sering.

Ini terdengar seperti solusi terbaik sejauh ini. Dimungkinkan untuk memilih nama yang waras di sini. Dan ada banyak sekali nama-nama waras lainnya - yang sepertinya tidak akan pernah kita butuhkan.

Sesuatu seperti np.random.generator atau np.random.default_generator .

berapa banyak BitGenerator yang kami sertakan

Bisakah Anda membuka masalah terpisah dengan proposal untuk menghapus yang menurut Anda harus kami hapus dari yang saat ini disertakan (MT19937, DSFMT, PCG32, PCG64, Philox, ThreeFry, Xoshiro256, Xoshiro512)?

Kami masih belum menyelesaikan masalah yang ada di sini: BitGenerator mana yang seharusnya menjadi default (saat ini Xoshiro256 )

Nah, masalah ini lebih banyak tentang "mana yang harus dipromosikan secara numpy sebagai BitGenerator terhormat," yang memberi makan pada pilihan default tetapi juga mana yang harus disertakan atau dihapus. Mekanika yang kami sediakan default (jika kami menyediakan default) menambahkan beberapa batasan, jadi ini semua adalah hal yang kurang lebih perlu diputuskan bersama. Ini adalah kekacauan besar, dan setelah semua pekerjaan yang telah Anda lakukan untuk menggembalakan PR ini, saya yakin Anda lelah melihat mega-thread lain tanpa ada yang berkontribusi kode, jadi Anda bersimpati. :-)

Sejauh algoritma itu sendiri, saya sudah memberikan rekomendasi saya: kita harus menyimpan MT19937 untuk RandomState dan tujuan perbandingan, dan saya suka PCG64 untuk tujuan rekomendasi.

Saya mengotak-atik sedikit di Compiler Explorer, dan saya pikir saya telah menerapkan PCG64 untuk MSVC 64-bit menggunakan intrinsik dengan cara yang memaksa kompiler untuk menghasilkan perakitan dekat dengan clang uint128_t math: https: // godbolt .org / z / ZnPd7Z

Saya belum menyiapkan lingkungan pengembang Windows saat ini, jadi saya tidak tahu apakah itu benar-benar _correct _... @bashtage, maukah Anda

Tanpa tambalan:

Uniforms per second
************************************************************
PCG64            62.77 million

Dengan tambalan:

Uniforms per second
************************************************************
PCG64           154.50 million

Patch lolos pengujian, termasuk menghasilkan set yang sama dengan 1000 nilai uint64 untuk 2 seed yang berbeda.

Untuk perbandingan dengan GCC asli dan dalam mode perbandingan:

Time to produce 1,000,000 Uniforms
************************************************************
Linux-64, GCC 7.4                      PCG64            4.18 ms
Linux-64, GCC 7.4, Forced Emulation    PCG64            5.19 ms
Win64                                  PCG64            6.63 ms
Win32                                  PCG64           45.55 ms

wow, itu sepertinya sangat buruk. Mungkin kita harus memperluas informasi di halaman perbandingan untuk mendemonstrasikan kinerja pniduiua-on-win {64, 32} vs. gcc7.4-on-linux {64, 32} di komputer yang sama (Saya anggap saja Anda menggunakan pnidui.dua, Anda mungkin harus menyertakan info itu di suatu tempat).

Win32 tidak ada harapan di sini. Saya menduga bahwa Linux 32 bit juga akan sangat buruk, tetapi tidak memiliki sistem Linux 32 bit untuk diuji dengan mudah.

Saya pasti dapat melihat kasus untuk membuat rekomendasi bagi orang-orang yang menggunakan mesin 32 bit (kemungkinan besar Windows karena kebijakan TI perusahaan). Recco ini jelas: DSFMT untuk 32 bit (atau MT19937 juga bagus). Tolok ukur akan bagus.

Untuk apa nilainya, saya agak skeptis dengan klaim PCG yang sering diulangi dari beberapa aliran acak independen . Adakah yang pernah melakukan analisis statistik serius untuk mendukung klaim kemerdekaan? (Sebenarnya, menurut saya makalah O'Neill hanya mengacu pada aliran yang "berbeda", tanpa klaim kemerdekaan apa pun.)

Saya pikir ada alasan bagus untuk bersikap skeptis: untuk pengganda LCG tertentu, semua aliran berbeda ini hanya terkait melalui penskalaan [*]. Jadi mengingat dua aliran LCG dengan pengali yang sama, salah satunya akan menjadi kelipatan konstan (modulo 2**64 atau 2**32 sesuai) dari yang lain, meskipun dengan titik awal yang berbeda. Bagian permutasi dari PCG akan membantu menyembunyikan ini sedikit, tetapi tidak mengherankan jika ada korelasi yang dapat dideteksi secara statistik.

Aliran yang begitu berbeda , tentu, tetapi saya tidak akan mengambil klaim aliran independen begitu saja tanpa pengujian yang serius.

[*] Contoh: misalkan x[0], x[1], x[2], ... adalah aliran LCG 64-bit standar, dengan x[i+1] := (m*x[i] + a) % 2**64 . Setel y[i] := 3*x[i] % 2**64 untuk semua i . Maka y[i] adalah aliran LCG dengan y[i+1] := (m*y[i] + 3*a) % 2**64 , jadi hanya dengan menskalakan aliran asli Anda telah menghasilkan salah satu aliran LCG yang berbeda ini dengan pengali yang sama tetapi konstanta aditif yang berbeda. Dengan menggunakan pengganda ganjil lainnya sebagai pengganti 3 , dan dengan asumsi bahwa kami hanya tertarik pada LCG periode penuh (dan a adalah ganjil), Anda akan mendapatkan semua kemungkinan penuh- periode LCG dengan pengali itu.


EDIT: Memperbaiki pernyataan yang salah tentang jumlah kelas konjugasi.

Saya pikir analisis publik paling menyeluruh dari aliran PCG ada di sini: http://www.pcg-random.org/posts/critiquing-pcg-streams.html

@imneme Bisakah Anda memperluas saran terakhir Anda? "korespondensi dengan David Blackman menunjukkan bahwa mungkin lebih mudah daripada yang saya pikirkan untuk membuat aliran" terdekat "dengan inisialisasi berkorelasi seperti benih konstan dan aliran 1,2,3,4. Jika Anda akan menggunakan beberapa aliran di pada saat yang sama, untuk saat ini saya akan merekomendasikan bahwa id aliran dan benih harus berbeda dan tidak memiliki korelasi yang jelas satu sama lain, yang berarti jangan membuat keduanya menjadi 1,2,3,4. "

Apakah ini berarti Anda berpikir bahwa tidak apa-apa untuk memiliki satu seed yang bagus (misalnya berasal dari sumber entropi) dan kemudian ID streaming 1,2,3,4? Atau haruskah ID benih dan aliran dipilih secara acak dari sumber entropi yang baik?

Beberapa nomor Linux-32 (Ubuntu 18.04 / GCC 7.4)

Time to produce 1,000,000 Uniforms
***************************************************************
Linux-64, GCC 7.4                      PCG64            4.18 ms
Linux-64, GCC 7.4, Forced Emulation    PCG64            5.19 ms
Win64                                  PCG64            6.63 ms
Win32                                  PCG64           45.55 ms
Linux-32, GCC 7.4                      PCG64           25.45 ms

Jadi ini dua kali lebih cepat dari Win-32 tetapi lambat. Semua 4 pengaturan waktu dibuat pada mesin yang sama

Other Linux-32/GCC 7.4 Timing Results
-----------------------------------------------------------------
DSFMT            6.99 ms
MT19937         13.09 ms
Xoshiro256      17.28 ms
numpy           15.89 ms

NumPy adalah NumPy 1.16.4. DSFMT adalah satu-satunya geneator dengan kinerja baik pada 32-bit (x86). Ini harus didokumentasikan dengan jelas untuk setiap pengguna 32 bit. MT19937 juga merupakan pilihan yang relatif baik untuk pengguna 32 bit.

Jadi kita perlu memiliki MT19937 untuk tujuan warisan. Jika kami ingin meminimalkan tentang PRNG mana yang kami sertakan (yaitu MT19937 plus rekomendasi tujuan umum tunggal kami), maka saya tidak akan merasa terdorong untuk menggunakan kinerja 32-bit untuk membatasi satu rekomendasi tujuan umum atau merasa terdorong untuk menambahkan PRNG "direkomendasikan-untuk-32-bit" ketiga. MT19937 akan selalu tersedia, dan itu tidak lebih buruk dari yang mereka miliki saat ini. Dan paket pihak ketiga akan tersedia untuk penggunaan yang lebih khusus.

Tentu saja, jika kami ingin menyertakan satu set PRNG yang lebih lengkap karena alasan lain, maka kami dapat membuat semua jenis rekomendasi khusus dalam dokumentasi.

Saya ingin tahu seberapa besar bagian "P" dari PCG mengurangi potensi masalah dari aliran yang berkorelasi.

Jadi inilah (mungkin) kasus terburuk untuk LCG: di mana konstanta aditif dari satu aliran LCG adalah negasi yang tepat dari konstanta aditif untuk yang lain. Kemudian dengan pilihan benih yang sangat buruk, kita berakhir dengan salah satu aliran LCG menjadi negasi yang tepat dari yang lain.

Tetapi sekarang jika kita menggunakan kedua aliran untuk menghasilkan serangkaian float, baik bagian permutasi PCG dan konversi ke float64 akan sedikit membantu kita.

Berikut adalah plot yang menunjukkan seberapa besar bantuan permutasi:

streams

Itu adalah plot pencar dari 10.000 pelampung dari satu aliran tersebut, melawan 10.000 dari kembarannya yang dinegasikan. Tidak buruk, tapi juga tidak bagus: ada artefak yang jelas.

Tidak yakin apa yang harus disimpulkan dari ini: ini benar-benar contoh yang dibuat-buat, bahwa Anda tidak mungkin (saya harap) mengalami kecelakaan. Di sisi lain, ini menunjukkan bahwa beberapa pemikiran dan perhatian diperlukan jika Anda benar-benar membutuhkan beberapa aliran yang tidak berkorelasi.

Sebagai catatan, berikut sumbernya:

import matplotlib.pyplot as plt
import numpy as np

from pcgrandom import PCG64

gen1, gen2 = PCG64(), PCG64()
multiplier, increment, state = gen1._get_core_state()
new_increment, new_state = -increment % 2**128, -state % 2**128
gen2._set_core_state((multiplier, new_increment, new_state))

xs = np.array([gen1.random() for _ in range(10**4)])
ys = np.array([gen2.random() for _ in range(10**4)])
plt.scatter(xs, ys, s=0.1)
plt.show()

PCG64 adalah generator yang oleh O'Neill disebut PCG-XSL-RR (bagian 6.3.3 dari makalah PCG). Paket pcgrandom berasal dari sini

Saya pikir cara standar untuk mendapatkan aliran independen menggunakan jumpahead ().
Menyemai ulang untuk mendapatkan streaming "independen" pada umumnya berbahaya.

Generator penghitung / hash memiliki jumpahead () yang sepele. Apakah PCG?

Juga permohonan dari pengguna: berikan setidaknya satu bitstream
kualitas kriptografi, dengan ruang negara tak terbatas.

Bersulang,
Philip

(EDIT oleh seberg: Kutipan email dihapus)

@pbstark : Ini bukan hanya reseeding: dua generator LCG yang mendasari sebenarnya berbeda: x ↦ mx + a (mod 2 ^ 128) dan x ↦ mx + b (mod 2 ^ 128) untuk perbedaan yang berbeda a dan b. Makalah PCG O'Neill menjual gagasan untuk dapat membuat aliran yang berbeda dengan mengubah kenaikan LCG tersebut (lihat bagian 4.3.2 makalah).

Tetapi kesederhanaan LCG berarti bahwa mengubah konstanta aditif itu _does_ hanya berarti sebuah jumpahead dengan beberapa jumlah yang tidak diketahui di generator asli, dikombinasikan dengan transformasi linier sederhana (perkalian dengan konstanta, atau hanya penambahan konstanta dalam beberapa kasus).

Bukan alasan untuk tidak menggunakan PCG, dan saya tidak sebentar berdebat bahwa itu tidak cocok untuk PRNG utama baru NumPy; Saya hanya tidak ingin orang-orang terbuai oleh janji aliran acak "independen". Paling baik, ide aliran yang dapat diatur untuk PCG menawarkan cara yang nyaman untuk melakukan sesuatu yang setara dengan jumpahead cepat plus bonus transformasi perkalian atau tambahan tambahan.

Kami membahas sedikit tentang kriptografi dalam panggilan komunitas. Saya pikir kami agak berhati-hati tentang itu. Sepertinya ide yang bagus, tetapi jika kami menyertakan RNG yang terdengar secara kriptografik, kami juga harus mengatasi masalah keamanan yang muncul, karena kami tidak tahu apakah pengguna menggunakannya untuk tujuan kriptografi yang sebenarnya.

Pada catatan tentang berapa banyak yang akan disertakan: Konsensus cenderung baik-baik saja dengan memiliki beberapa generator bit lagi (beberapa dokumentasi kecil tentu saja akan baik). Beban perawatan sepertinya tidak terlalu besar. Pada akhirnya, tebakan saya adalah bahwa kita akan mengikuti apa pun yang disarankan Kevin dan Robert.

Pada catatan nama: Saya pribadi tidak keberatan menggunakan nama RNG dan memaksa pengguna untuk menggunakannya, satu-satunya downside adalah kita mungkin harus mencari nama tersebut saat melakukan pengkodean. Kita harus mencoba untuk memiliki peringatan penghentian sesedikit mungkin. Saya suka API terpapar minimal untuk RNG default tanpa penyemaian.

@mdickinson , saya mencoba mereproduksi grafik Anda sendiri dan gagal. Saya menggunakan versi C ++ kanonik dari kode dengan program ini yang seharusnya setara dengan moral Anda.

#include "pcg_random.hpp"
#include <iostream>
#include <random>

int main() {
    std::random_device rdev;
    pcg_detail::pcg128_t seed = 0;
    pcg_detail::pcg128_t stream = 0;
    for (int i = 0; i < 4; ++i) {
        seed   <<= 32;           
        seed   |= rdev();
        stream <<= 32;           
        stream |= rdev();
    }
    pcg64 rng1(seed,stream);
    pcg64 rng2(-seed,-stream);
    std::cerr << "RNG1: " << rng1 << "\n";
    std::cerr << "RNG2: " << rng2 << "\n";
    std::cout.precision(17);
    for (int i = 0; i < 10000; ++i) {
        std::cout << rng1()/18446744073709551616.0 << "\t";
        std::cout << rng2()/18446744073709551616.0 << "\n";
    }
}

Ketika saya menjalankan ini, ia mengeluarkan (untuk memungkinkan reproduktifitas):

RNG1: 47026247687942121848144207491837523525 203756742601991611962280963671468648533 41579532896305845786243518008404876432
RNG2: 47026247687942121848144207491837523525 136525624318946851501093643760299562925 52472962479578397910044896975270170620

dan titik data yang dapat memplot grafik berikut:

corr1

Jika Anda dapat mengetahui apa yang saya lakukan secara berbeda, itu akan membantu.

(Saya tidak mengatakan ini untuk menyangkal gagasan bahwa korelasi itu mungkin, karena memang demikian, dan saya akan menulis komentar terpisah tentang topik tersebut, tetapi dalam menulis komentar itulah saya menyadari bahwa saya tidak dapat mereproduksi hasil Anda menggunakan alat saya yang biasa.)

@mdickinson menekan dalam keadaan dihitung dan peningkatan langsung ke internal, melewati rutinitas inisialisasi biasa , yang memiliki dua langkah kemajuan.

Saya menulis skrip driver kecil cepat yang menyisipkan beberapa aliran PCG32, dibangun dengan berbagai cara, untuk dimasukkan ke dalam PractRand. Ini menggunakan master numpy pada Python 3. Ketika saya meninju status / increments internal adversarial secara langsung, PractRand gagal dengan cepat. Tidak jelas bagi saya apakah kita dapat menemukan cara yang masuk akal untuk menemukan adversarial _seeds_ (yang sebenarnya melewati rutinitas penginisialisasi) untuk mencapai keadaan permusuhan.

Seperti dicatat dalam posting blog saya yang disebutkan sebelumnya, aliran PCG memiliki banyak kesamaan dengan SplitMix.

Mengenai grafik @mdickinson 's, untuk _every_ PRNG yang memungkinkan Anda untuk benih seluruh negara, termasuk berbasis-counter yang kriptografi, kita dapat merancang bibit di mana kita harus PRNGs yang output yang berkorelasi dalam beberapa cara (cara termudah untuk melakukannya adalah membuat status PRNG yang jaraknya cukup dekat, tetapi seringkali kita dapat melakukan hal-hal lain berdasarkan pemahaman tentang cara kerjanya). Dan meskipun PRNG yang tidak mengizinkan penyemaian status penuh dapat menghindari masalah ini, melakukan hal itu hanya memperkenalkan yang baru, hanya memberikan akses praktis ke sebagian kecil dari kemungkinan status mereka.

Cara yang tepat untuk memikirkan aliran hanyalah keadaan yang lebih acak yang perlu diunggulkan. Menggunakan nilai kecil seperti 1,2,3 umumnya merupakan ide yang buruk untuk tujuan penyemaian untuk _any_ PRNG (karena jika semua orang menyukai benih ini, urutan awal yang sesuai akan terwakili secara berlebihan).

Kita dapat memilih untuk tidak menyebutnya sungai sama sekali dan hanya menyebutnya negara. Itulah yang dilakukan Marsaglia di XorWow . Jika Anda melihat kodenya, urutan Weyl counter sekali tidak berinteraksi dengan status lainnya, dan, seperti LCG, dan variasi nilai awal benar-benar hanya berupa konstanta tambahan.

Aliran SplitMix, PCG, dan XorWow adalah apa yang kita sebut aliran "bodoh". Mereka merupakan reparameterization sepele generator. Namun, ada nilai dalam hal ini. Misalkan tanpa aliran, PRNG kami akan memiliki pengulangan yang menarik dari 42, di mana 42 muncul beberapa kali secara berurutan dan hanya melakukan ini untuk 42 dan tidak ada nomor lain. Dengan aliran bodoh "hanya selisih" atau "hanya satu xor", kita sebenarnya akan menghindari memasang ulang aneh ke 42; semua angka memiliki aliran yang diulangi dengan aneh. (Untuk alasan ini, perbaikan yang akan saya terapkan untuk memperbaiki masalah close-repeat di Xoshiro 256 adalah mencampur dalam urutan Weyl.)

Saya bukan ahli, tapi dari sisi kriptografi, apa yang di usulkan tidak tersedia di:
https://cryptography.io/en/latest/ dari Python Cryptographic Authority ?

Halaman mereka tentang pembuatan nomor acak juga menyebutkan:

Dimulai dengan Python 3.6 pustaka standar menyertakan modul rahasia , yang dapat digunakan untuk menghasilkan nomor acak yang aman secara kriptografis, dengan bantuan khusus untuk format berbasis teks.

Saya kira mungkin menambahkan array ke generasi. Saya harus bertanya-tanya apakah potensi beban pemeliharaan terkait dengan kekokohan crypotgraphic benar-benar sepadan dan sesuai di NumPy vs. katakanlah berkomunikasi dengan pyca dan mungkin memikirkan generator / plugin pihak ketiga untuk itu. Saya pikir Nathaniel menyebutkan masalah serupa sebelumnya.

Memang, menurut saya hal-hal seperti refactor / penyempurnaan dtype potensial juga dirancang untuk menyediakan infrastruktur API tanpa harus mengambil beban untuk memelihara berbagai macam aplikasi baru khusus.

BTW, ada juga lebih banyak tentang membuat status PRNG berkorelasi dalam tanggapan saya terhadap kritik PCG Vigna [secara khusus, bagian ini ]. Yang saya amati ada bahwa dengan PCG, karena memiliki fungsi jarak, sebenarnya Anda bisa mengecek dengan fungsi jarak untuk mendeteksi benih bikin. Dalam PRNG tanpa fungsi jarak, orang masih dapat membuat pasangan penyemaian yang merupakan pilihan yang buruk (terutama jika mereka melewati API publik untuk penyemaian) tetapi tidak ada mekanisme yang tersedia yang dapat mendeteksi bahkan penemuan yang paling mencolok sekalipun.

Di satu sisi, menyenangkan untuk memikirkan apakah mungkin untuk mengambil PRNG favorit Anda (atau paling tidak favorit) dan membuat benih untuk itu yang membuatnya melakukan hal-hal yang lucu atau mengerikan (misalnya, patologi ini )…

Namun melihat gambaran yang lebih besar, menurut saya masuk akal untuk melihat masalah yang dihadapi pengguna dalam praktiknya. Saran apa yang kami berikan kepada mereka, dll. Sebagian besar pengguna tidak menyadari bahwa _untuk semua PRNG (masa lalu dan masa depan) _, seed 32-bit adalah ide yang sangat buruk dan menghasilkan bias yang dapat dideteksi secara sepele, apa pun PRNG yang sedang dimainkan. Tentu, kita dapat mengabaikannya dan sebagai gantinya menghabiskan waktu kita mengkhawatirkan apakah seseorang mungkin berhasil menginisialisasi Mersenne Twister ke keadaan kebanyakan-nol (atau keadaan semua-nol di mana LFSR gagal berfungsi sama sekali!), Atau apakah seseorang mungkin menginisialisasi Xoshiro ke dekat titik di mana ia mengulangi keluaran yang sama tujuh kali dalam ruang sebelas keluaran, atau membuat dua aliran PCG yang serupa, atau apa pun, tetapi semua alat ini pada dasarnya memiliki peluang yang sangat kecil (dalam praktiknya nol) terjadi jika generator diunggulkan dengan data acak. Betapapun menarik secara intelektual dan akademis seperti pengalihan ini, memikirkannya sambil mengabaikan fakta bahwa pengguna biasanya memiliki sedikit gagasan tentang apa yang mereka lakukan ketika datang ke penyemaian adalah mengutak-atik saat Roma terbakar.

Jika inc=1,2,3,4 adalah ide yang buruk, bukankah itu menunjukkan bahwa itu harus didokumentasikan dengan sangat jelas, atau mungkin kita harus memiliki API yang sedikit berbeda? Bahkan mungkin new_generator = (Bit)Generator().independent() , kita dapat memberi peringatan jika pembuat bit (yang mendasari) tidak menyediakan cara yang bagus untuk mencapai itu.

Juga, tergantung pada seberapa buruk penyemaian 32bit. Bisakah kita memikirkan API yang bagus untuk membuat dan menyimpan benih untuk membekukannya? Saya tidak tahu. Mungkin bahkan "buat file cache benih beku jika tidak ada".

Untuk PCG cukup seed -> uint64_t [2] -> splitmix64 (seed_by_array) -> uint128 yang akan memastikan bahwa seed yang rendah dan berurutan tersebar.

Untuk PCG cukup seed -> uint64_t [2] -> splitmix64 (seed_by_array) -> uint128 yang akan memastikan bahwa seed yang rendah dan berurutan tersebar.

Atau gunakan saja hash integer yang bagus. (Ini harus menjadi bijection.). Ada banyak yang murah dan pendek. Beberapa putaran Multiply – XorShift sudah cukup.

Untuk poin @mdickinson , saya pikir dia masih ingin sedikit meyakinkan bahwa ketergantungan streaming terbatas pada set kecil pengaturan yang dibuat-buat / permusuhan. Dan jika itu masalahnya, maka kita dapat menyelesaikannya dengan praktik yang tepat untuk mencegah kejadian seperti itu. Dengan kode saat ini yang kami miliki, ada beberapa status buruk yang dapat dengan mudah terjatuh oleh pengguna dengan API saat ini. Saya dapat mengkonfirmasi temuan David Blackman bahwa pengaturan seed=1 dan inc=0,1,2,... menciptakan korelasi. Driver PractRand terbaru saya untuk aliran PCG32 berselang-seling dapat digunakan untuk mendemonstrasikan hal ini.

❯ ./pcg_streams.py --seed 1 --inc 0 |time ./RNG_test stdin32
[
    {
        "bit_generator": "PCG32",
        "state": {
            "state": 12728272447693586011,
            "inc": 1
        }
    },
    {
        "bit_generator": "PCG32",
        "state": {
            "state": 7009800821677620407,
            "inc": 3
        }
    }
]
RNG_test using PractRand version 0.93
RNG = RNG_stdin32, seed = 0x470537d5
test set = normal, folding = standard (32 bit)

rng=RNG_stdin32, seed=0x470537d5
length= 128 megabytes (2^27 bytes), time= 4.0 seconds
  Test Name                         Raw       Processed     Evaluation
  BCFN(2+0,13-3,T)                  R=  +9.6  p =  2.3e-4   mildly suspicious
  ...and 116 test result(s) without anomalies

rng=RNG_stdin32, seed=0x470537d5
length= 256 megabytes (2^28 bytes), time= 8.7 seconds
  Test Name                         Raw       Processed     Evaluation
  BCFN(2+0,13-2,T)                  R= +26.1  p =  6.3e-13    FAIL           
  ...and 123 test result(s) without anomalies

./RNG_test stdin32  8.86s user 0.11s system 93% cpu 9.621 total

Saya belum mengalami kegagalan dengan benih acak tetapi peningkatan yang sama. Aku akan memeriksa denganmu besok.

Saya perhatikan bahwa kami tidak menggunakan kenaikan default yang disarankan ketika tidak ada yang ditentukan dalam konstruktor. Kami mungkin harus memperbaikinya. Mungkin itu akan menjadi bilangan dasar yang baik dari mana kami memperoleh kenaikan sebenarnya dari ID streaming yang diberikan, bukan 2*inc + 1 .

Kami dapat mencoba membangun beberapa perkakas untuk membantu orang dalam menggunakan benih entropi default dan menyimpannya. Satu pertanyaan yang saya miliki adalah apakah kenaikan untuk beberapa aliran dapat dibuat secara sederhana atau jika kita juga perlu mengambil sampel dengan entropi dan menyimpannya juga. Sangat mudah untuk dapat menyandikan "keadaan awal" simulasi sebagai nomor tunggal yang dapat disalin-tempel dari email kolega daripada file buram. Dengan PRNG yang lebih kecil ini dengan hanya 128 atau 256 bit status, saya dapat dengan mudah mencetaknya dalam hex ke file log saya dan kemudian hanya menyalin-tempelnya ke baris perintah saya ketika saya ingin mereproduksinya. Ini lebih besar dari integer 32-bit, tetapi dapat dikelola. Jika saya harus mengambil sampel entropi semua ID streaming saya juga, maka saya harus melupakannya dan memastikan bahwa saya merekam semuanya dalam file status di suatu tempat. Itu mungkin menutup beberapa kasus penggunaan yang telah kita diskusikan di mana kita ingin secara dinamis menelurkan aliran baru. Jika saya bisa menaikkan penghitung untuk mendapatkan ID streaming yang bagus (mungkin memperolehnya melalui hash penghitung, atau apa pun), maka saya hanya perlu merekam seed awal dan bukan ID streaming.

IIRC, modul rahasia memanggil sumber entropi OS, yang bisa jadi cukup
buruk di beberapa sistem, dan tidak dapat direplikasi / direproduksi.

Pada Rabu, 29 Mei 2019 pukul 15.19 Tyler Reddy [email protected]
menulis:

Saya bukan ahli, tapi di sisi kriptografi, apa yang diusulkan itu
tidak tersedia di:
https://cryptography.io/en/latest/ dari Python Cryptographic Authority
https://github.com/pyca ?

Halaman mereka tentang pembuatan nomor acak
https://cryptography.io/en/latest/random-numbers/ juga menyebutkan:

Dimulai dengan Python 3.6 pustaka standar menyertakan rahasia
https://docs.python.org/3/library/secrets.html modul, yang bisa
digunakan untuk menghasilkan nomor acak yang aman secara kriptografis, dengan spesifik
pembantu untuk format berbasis teks.

Saya kira mungkin menambahkan array ke generasi. Saya harus bertanya-tanya apakah file
beban pemeliharaan potensial yang terkait dengan crypotgraphic
ketahanan sangat berharga dan sesuai di NumPy vs. katakanlah
berkomunikasi dengan pyca dan mungkin memikirkan pihak ketiga
generator / plugin untuk itu. Saya pikir Nathaniel menyebutkan kekhawatiran serupa
sebelumnya.

Memang, menurut saya hal-hal seperti potensi dtype refactor /
peningkatan juga dirancang untuk menyediakan infrastruktur API tanpa
perlu mengambil beban memelihara berbagai macam
aplikasi baru khusus.

-
Anda menerima ini karena Anda disebutkan.
Balas email ini secara langsung, lihat di GitHub
https://github.com/numpy/numpy/issues/13635?email_source=notifications&email_token=AANFDWKXSSTX6QI7HJ65GYTPX36O3A5CNFSM4HPX3CHKYY3PNVWWK3TUL5252HS4DFVREXG43VMVBVW2HS4DFVREXG43VMVBVW4DFVREXG43VMVBZW4DFVREXG43VMVBVW4DFVRXG43
atau nonaktifkan utasnya
https://github.com/notifications/unsubscribe-auth/AANFDWKGZMUB67VPCMFZYGTPX36O3ANCNFSM4HPX3CHA
.

-
Philip B. Stark | Associate Dean, Matematika dan Ilmu Fisika |
Profesor, Departemen Statistik |
Universitas California
Berkeley, CA 94720-3860 | 510-394-5077 | Statistics.berkeley.edu/~stark |
@tokopedia

@tylerjereddy Itu untuk mendapatkan sejumlah kecil bit acak dari sumber entropi fisik yang tidak dapat diprediksi oleh penyerang (dan Anda!). Mereka digunakan dalam kriptografi untuk hal-hal seperti vektor inisialisasi, nonce, kunci, yang semuanya pendek. Intinya adalah tidak ada cara untuk mereproduksinya, yang bertentangan dengan tujuan simulasi numerik np.random . Halaman itu tidak berbicara tentang _reproducible_ PRNG yang aman secara kriptografis, yang juga merupakan hal-hal yang ada dan _dapat_ dibangun dari primitif yang tersedia dalam paket cryptography . Namun, dalam _practice_, kami memiliki implementasi yang lebih baik dari algoritme tersebut yang sudah tersedia bagi kami dalam kode C yang efisien, setidaknya yang telah dirumuskan dan diuji untuk tujuan simulasi. @bashtage menerapkan beberapa untuk kerangka ini.

Saya juga ingin menjelaskan kepada tim numpy bahwa apa yang diusulkan @pbstark bukan sembarang PRNG berbasis crypto. Sebaliknya, dia menginginkan satu dengan _unbounded state_, yang akan memberikan properti matematika yang dia cari.

Sebagian besar PRNG berbasis kripto yang biasanya dipertimbangkan untuk simulasi tidak _not_ memiliki status tak terbatas yang diinginkan @pbstark . Mereka biasanya berbasis di sekitar mengenkripsi penghitung terbatas. Setelah penghitung itu berputar, Anda telah mencapai periode yang terbatas. Secara teknis, cryptorandom miliknya juga terikat ke 2**(256+64) kondisi awal yang unik karena status intisari 256-bit ukuran tetap dan penghitung panjang 64-bit ukuran tetap. Itu mungkin menunjukkan cara untuk menerapkan PRNG yang benar-benar tidak terbatas dengan membuat penghitung panjang berukuran sewenang-wenang, tetapi saya belum pernah melihat algoritme seperti itu diterbitkan atau diuji.

Di sisi lain, jika Anda hanya menginginkan algoritme PRNG yang memiliki status berukuran sewenang-wenang, hanya algoritme yang ditetapkan di awal untuk sesuatu di atas apa pun yang Anda butuhkan, maka generator tambahan PCG akan bekerja dengan baik untuk tugas itu. Ini jelas bukan CS-PRNG, tetapi mereka benar-benar memenuhi keinginan @pbstark untuk memiliki ruang negara yang luas sesuai permintaan. Meskipun demikian, saya tidak menyarankan kami memasukkannya ke dalam numpy.

Ada properti lain yang dimiliki CS-PRNG standar, terbatas, yang mungkin kami inginkan, tetapi itu bukan default no-brainer, IMO.

Ruang status Cryptorandom bukanlah hash 256 bit: itu tidak terbatas. Itu
status benih adalah string dengan panjang sembarang, dan setiap pembaruan menambahkan nol
ke kondisi saat ini. Menambahkan penghitung integer tak terbatas akan
mencapai hal yang sama. Kami awalnya menerapkan itu, tetapi berubah menjadi
menambahkan bukan kenaikan, karena memungkinkan pembaruan yang lebih efisien ke
intisari daripada hashing setiap status dari awal (speedup terlihat).

Pada Rabu, 29 Mei 2019 pukul 19.26 Robert Kern [email protected]
menulis:

@tylerjereddy https://github.com/tylerjereddy Itu untuk mendapatkan
sejumlah kecil bit acak dari sumber entropi fisik
tidak dapat diprediksi oleh penyerang (dan Anda!). Mereka digunakan dalam kriptografi untuk
hal-hal seperti vektor inisialisasi, nonce, kunci, yang semuanya pendek. Itu
Intinya adalah bahwa tidak ada cara untuk mereproduksinya, yaitu pada
aneh dengan tujuan simulasi numerik np.random. Halaman itu
tidak berbicara tentang PRNG yang aman secara kriptografis yang dapat direproduksi
juga hal-hal yang ada dan bisa dibangun dari primitif
tersedia dalam paket kriptografi. Namun, dalam praktiknya , kami punya
implementasi yang lebih baik dari algoritme tersebut sudah tersedia untuk kami di
kode C yang efisien, setidaknya yang telah dirumuskan dan diuji
untuk tujuan simulasi. @bashtage https://github.com/bashtage diimplementasikan
beberapa https://github.com/numpy/numpy/issues/13635#issuecomment-496287650
untuk kerangka ini.

Saya juga ingin menjelaskan kepada tim numpy bahwa @pbstark
https://github.com/pbstark mengusulkan bukan sembarang crypto berbasis
PRNG. Sebaliknya, dia menginginkan seseorang dengan keadaan tak terbatas , yang akan menyediakan
properti matematika yang dia cari.

Sebagian besar PRNG berbasis kripto yang biasa dipertimbangkan untuk simulasi
tidak memiliki status tak terbatas yang @pbstark
https://github.com/pbstark ingin. Mereka biasanya berbasis di sekitar
mengenkripsi penghitung yang terbatas. Setelah penghitung itu berputar, Anda telah menekan tombol
periode terbatas. Secara teknis, cryptorandom-nya
https://statlab.github.io/cryptorandom/ juga dibatasi ke 2 ** (256 + 64)
kondisi awal yang unik karena status intisari 256-bit ukuran tetap dan
penghitung panjang 64-bit ukuran tetap. Itu mungkin menunjukkan jalannya
menerapkan PRNG yang benar-benar tidak terbatas dengan membuat penghitung panjang
berukuran sewenang-wenang, tetapi saya belum pernah melihat algoritme seperti itu diterbitkan atau
diuji.

Di sisi lain, jika Anda hanya menginginkan algoritme PRNG yang memiliki ekstensi
negara berukuran sewenang-wenang, hanya satu yang diperbaiki di awal
sesuatu di atas apa pun yang Anda butuhkan, lalu generator tambahan PCG
http://www.pcg-random.org/party-tricks.html akan bekerja dengan baik untuk itu
tugas. Ini jelas bukan CS-PRNG, tetapi sebenarnya akan memuaskan
@pbstark https://github.com/pbstark keinginan untuk memiliki ruang negara yang luas
sesuai permintaan. Meskipun demikian, saya tidak menyarankan kami memasukkannya ke dalam numpy.

Ada properti lain yang dimiliki oleh standar, terikat, CS-PRNG
kita mungkin ingin, tapi itu bukan default no-brainer, IMO.

-
Anda menerima ini karena Anda disebutkan.
Balas email ini secara langsung, lihat di GitHub
https://github.com/numpy/numpy/issues/13635?email_source=notifications&email_token=AANFDWLGAF6YVIWXYZ2LTT3PX43ONA5CNFSM4HPX3CHKYY3PNVWWK3TUL5252HS4DFVREXG43VMVBW2HS4DFVREXG43VMVBW2S4DFVREXG43VMVBW2S4DFVREXG43VMVBW2S4DFVREXG43VMVBW2S4DFVREXG43VMVBW4DF
atau nonaktifkan utasnya
https://github.com/notifications/unsubscribe-auth/AANFDWLIJD3UCVY3NXCLPKDPX43ONANCNFSM4HPX3CHA
.

-
Philip B. Stark | Associate Dean, Matematika dan Ilmu Fisika |
Profesor, Departemen Statistik |
Universitas California
Berkeley, CA 94720-3860 | 510-394-5077 | Statistics.berkeley.edu/~stark |
@tokopedia

Saya khawatir itu bukan cara kerja pembaruan online SHA-256. Status yang dipertahankan hanyalah intisari 256-bit dan penghitung panjang 64-bit ukuran tetap yang ditambahkannya saat menghitung pembaruan. Itu tidak menampung seluruh teks. Kompres bulu mata. Begitulah cara ia dapat melakukan pembaruan yang efisien pada setiap byte. Pada dasarnya, ada banyak inisialisasi / riwayat masa lalu yang dipetakan ke status SHA-256 internal yang sama, yang terbatas. Meskipun siklusnya pasti panjang, mungkin lebih lama dari 2**(256+64) , siklusnya pasti ada. Dan bagaimanapun, Anda hanya memiliki kurang dari 2**(256+64) kemungkinan kondisi awal (untuk setiap panjang teks 0 hingga 2**64-1 , Anda dapat memiliki paling banyak 2**256 status hash internal; setelah panjang teks lebih dari 32 byte, harus ada tabrakan a la pigeonhole). Tidak ada lagi bit dalam struktur data.

Terima kasih banyak; mengerti. Saya akan mengungkapkannya secara berbeda: negara
ruang tidak dibatasi, tetapi (dengan lubang kecil) banyak keadaan awal yang berbeda harus
menghasilkan urutan keluaran yang tidak bisa dibedakan.

Pada Rabu, 29 Mei 2019 pukul 20.21 Robert Kern [email protected]
menulis:

Saya khawatir itu bukan cara kerja pembaruan online SHA-256. Negara
yang dipertahankan hanyalah intisari 256-bit dan 64-bit ukuran tetap
penghitung panjang yang ditambahkan saat menghitung pembaruan. Itu tidak tahan
seluruh teks. Kompres bulu mata. Begitulah cara ia dapat melakukan yang efisien
perbarui setiap byte. Pada dasarnya ada banyak inisialisasi / masa lalu
sejarah yang memetakan ke status SHA-256 internal yang sama, yang terbatas.
Meskipun siklusnya pasti panjang, mungkin lebih lama dari 2 (256 + 64), merekapasti ada.
kemungkinan kondisi awal (untuk setiap panjang teks 0 hingga 2 64-1, Anda bisamemiliki paling banyak 2.256 status hash internal; setelah panjang teks melebihi 32
byte, harus ada tabrakan a la pigeonhole). Tidak ada
lebih banyak bit dalam struktur data.

-
Anda menerima ini karena Anda disebutkan.
Balas email ini secara langsung, lihat di GitHub
https://github.com/numpy/numpy/issues/13635?email_source=notifications&email_token=AANFDWO6HRJZHTVBF2TLK3LPX5B3TA5CNFSM4HPX3CHKYY3PNVWWK3TUL_token
atau nonaktifkan utasnya
https://github.com/notifications/unsubscribe-auth/AANFDWM56HCQRZXDO3BAQHDPX5B3TANCNFSM4HPX3CHA
.

-
Philip B. Stark | Associate Dean, Matematika dan Ilmu Fisika |
Profesor, Departemen Statistik |
Universitas California
Berkeley, CA 94720-3860 | 510-394-5077 | Statistics.berkeley.edu/~stark |
@tokopedia

Ini juga merupakan kasus bahwa hanya ada 2**(256+64) status yang mungkin bisa dilalui. Karena pembaruan mengambil bentuk yang sama setiap saat, Anda akhirnya mencapai keadaan yang telah Anda lihat sebelumnya dan memasuki lingkaran yang tidak diketahui (bagi saya) tetapi periode terbatas. Baik itu jumlah keadaan awal yang terbatas atau periode terbatas, cryptorandom memiliki keduanya, dan saya pikir mereka lebih kecil bahkan dari MT19937 .

Bukannya saya pikir itu masalah dengan cryptorandom , per se. Saya belum yakin bahwa memiliki sekumpulan keadaan awal yang tidak terbatas atau periode tidak terbatas adalah sesuatu yang sebenarnya dibutuhkan dalam arti praktis.

Saya belum mengalami kegagalan dengan benih acak tetapi peningkatan yang sama. Aku akan memeriksa denganmu besok.

Masih kuat di 512GiB:

❯ ./pcg_streams.py -i 0 |time ./RNG_test stdin32
[
    {
        "bit_generator": "PCG32",
        "state": {
            "state": 10843219355420032665,
            "inc": 1
        }
    },
    {
        "bit_generator": "PCG32",
        "state": {
            "state": 5124747729404067061,
            "inc": 3
        }
    }
]
RNG_test using PractRand version 0.93
RNG = RNG_stdin32, seed = 0xb83f7253
test set = normal, folding = standard (32 bit)

rng=RNG_stdin32, seed=0xb83f7253
length= 128 megabytes (2^27 bytes), time= 4.0 seconds
  no anomalies in 117 test result(s)

rng=RNG_stdin32, seed=0xb83f7253
length= 256 megabytes (2^28 bytes), time= 8.6 seconds
  no anomalies in 124 test result(s)

rng=RNG_stdin32, seed=0xb83f7253
length= 512 megabytes (2^29 bytes), time= 16.9 seconds
  Test Name                         Raw       Processed     Evaluation
  BCFN(2+2,13-2,T)                  R=  -8.0  p =1-2.1e-4   mildly suspicious
  ...and 131 test result(s) without anomalies

rng=RNG_stdin32, seed=0xb83f7253
length= 1 gigabyte (2^30 bytes), time= 33.8 seconds
  no anomalies in 141 test result(s)

rng=RNG_stdin32, seed=0xb83f7253
length= 2 gigabytes (2^31 bytes), time= 65.7 seconds
  Test Name                         Raw       Processed     Evaluation
  BCFN(2+2,13-1,T)                  R=  -7.8  p =1-3.8e-4   unusual          
  ...and 147 test result(s) without anomalies

rng=RNG_stdin32, seed=0xb83f7253
length= 4 gigabytes (2^32 bytes), time= 136 seconds
  no anomalies in 156 test result(s)

rng=RNG_stdin32, seed=0xb83f7253
length= 8 gigabytes (2^33 bytes), time= 270 seconds
  no anomalies in 165 test result(s)

rng=RNG_stdin32, seed=0xb83f7253
length= 16 gigabytes (2^34 bytes), time= 516 seconds
  no anomalies in 172 test result(s)

rng=RNG_stdin32, seed=0xb83f7253
length= 32 gigabytes (2^35 bytes), time= 1000 seconds
  no anomalies in 180 test result(s)

rng=RNG_stdin32, seed=0xb83f7253
length= 64 gigabytes (2^36 bytes), time= 2036 seconds
  no anomalies in 189 test result(s)

rng=RNG_stdin32, seed=0xb83f7253
length= 128 gigabytes (2^37 bytes), time= 4064 seconds
  no anomalies in 196 test result(s)

rng=RNG_stdin32, seed=0xb83f7253
length= 256 gigabytes (2^38 bytes), time= 8561 seconds
  no anomalies in 204 test result(s)

rng=RNG_stdin32, seed=0xb83f7253
length= 512 gigabytes (2^39 bytes), time= 19249 seconds
  no anomalies in 213 test result(s)

Ah, jika kami melakukan lebih dari 2 aliran dengan kenaikan berurutan, kami melihat kegagalan dengan cepat. Kita perlu melihat penurunan aktual dari input pengguna dengan beberapa jenis bijection untuk menyebarkannya ke seluruh ruang.

❯ ./pcg_streams.py -n 3  | time ./build/RNG_test stdin32
[
    {
        "bit_generator": "PCG32",
        "state": {
            "state": 18394490676042343370,
            "inc": 2891336453
        }
    },
    {
        "bit_generator": "PCG32",
        "state": {
            "state": 12676019050026377766,
            "inc": 2891336455
        }
    },
    {
        "bit_generator": "PCG32",
        "state": {
            "state": 6957547424010412162,
            "inc": 2891336457
        }
    }
]
RNG_test using PractRand version 0.93
RNG = RNG_stdin32, seed = 0x4a9d21d1
test set = normal, folding = standard (32 bit)

rng=RNG_stdin32, seed=0x4a9d21d1
length= 128 megabytes (2^27 bytes), time= 3.2 seconds
  Test Name                         Raw       Processed     Evaluation
  DC6-9x1Bytes-1                    R= +19.4  p =  1.6e-11    FAIL           
  [Low8/32]DC6-9x1Bytes-1           R= +13.2  p =  4.6e-8    VERY SUSPICIOUS 
  ...and 115 test result(s) without anomalies

@tokopedia

Jika Anda dapat mengetahui apa yang saya lakukan secara berbeda, itu akan membantu.

Saya pikir Anda perlu mengganti baris pcg64 rng2(-seed,-stream); dalam kode Anda dengan pcg64 rng2(-seed,-1-stream); , untuk memungkinkan transformasi increment = 2 * stream + 1 . Negasi kenaikan sesuai dengan negasi bitwise dari indeks aliran. Jika saya membuat perubahan itu dan menjalankan kode Anda, saya melihat sesuatu yang sangat mirip dengan plot saya sebelumnya. (Dan saya mengonfirmasi bahwa jika saya tidak membuat perubahan itu, maka semuanya terlihat bagus secara visual.)

@tokopedia

Cara yang tepat untuk memikirkan aliran hanyalah keadaan yang lebih acak yang perlu diunggulkan.

Sepakat. Saya pikir itu memberikan gambaran yang sangat bersih untuk LCG: untuk LCG 64-bit dengan pengganda yang dipilih dengan baik a , kami kemudian memiliki ruang negara berukuran 2^127 , terdiri dari semua pasangan (x, c) integer mod 2 ^ 64, di mana c adalah kenaikan ganjil. Fungsi pembaruan status adalah next : (x, c) ↦ (ax+c, c) , membagi ruang status menjadi 2^63 siklus terputus masing-masing dengan panjang 2^64 . Pembibitan hanya melibatkan pengambilan titik awal di ruang negara bagian ini.

Kemudian ada tindakan grup yang jelas yang membuat analisis menjadi mudah, dan membuat hubungan antara aliran yang berbeda menjadi jelas: grup transformasi affine 1-hari yang dapat dibalik pada Z / 2^64Z memiliki pesanan tepat 2^127 , dan bertindak secara transitif (dan begitu juga dengan setia) di ruang negara: transformasi affine y ↦ ey + f memetakan pasangan (x, c) menjadi (ex + f, ec + (1-a)f) . Tindakan grup itu bolak-balik dengan fungsi next , jadi elemen grup unik yang mengubah satu titik (x, c) di ruang negara menjadi yang lain, (x2, c2) , juga memetakan urutan yang dihasilkan oleh (x, c) ke urutan yang dihasilkan oleh (x2, c2) .

tl; dr: untuk multiplier tetap, setiap dua urutan LCG dengan multiplier yang sama (apakah menggunakan kenaikan yang sama, seperti dalam kasus lookahead, atau kenaikan yang berbeda) terkait dengan transformasi affine. Dalam kasus yang tidak menguntungkan yang ingin kita hindari, transformasi affine itu adalah sesuatu yang sangat sederhana, seperti menambahkan 2 atau mengalikan dengan -1 . Dalam kasus umum, kami berharap transformasi affine cukup rumit sehingga uji statistik standar tidak dapat mendeteksi hubungan antara dua aliran.

@mdickinson menutupi situasi dengan baik. Permutasi PCG akan sedikit mengubah kasus LCG, tetapi tidak banyak. Inti dari permutasi PCG adalah kita dapat memilih seberapa banyak pengacakan yang harus dilakukan. Karena LCG 128-bit yang terpotong sudah melewati BigCrush, ketika saya memilih permutasi untuk pcg64 saya memilih jumlah pengacakan yang sederhana untuk ukuran LCG (XSL RR). Sebaliknya, LCG 64-bit dengan cepat gagal dalam beberapa tes statistik sehingga pcg32 menggunakan sedikit lebih banyak pengacakan, tetapi ini masih bukan permutasi terkuat dari kertas PCG. Seperti yang saya sebutkan di thread pull-request thread, saya mulai condong ke permutasi PCG yang lebih kuat (RXS M) untuk kasus penggunaan pcg32 . Ini belum menjadi default, Anda harus meminta versi itu secara eksplisit, tetapi ada kemungkinan besar saya akan mengganti default ketika saya melakukan tonjolan versi utama untuk PCG. (RXS M adalah bagian atas dari RXS M XS, yang telah diuji secara ekstensif oleh Vigna pada ukuran ini dan juga permutasi yang disukai David Blackman).

Kami dapat memvisualisasikan perbedaan versi yang diperbarui dari program pengujian near-streams menggunakan kedua skema untuk pcg32 (XSH RR dan RCS M [dan juga LCG yang mendasari mentah]):

#include "pcg_random.hpp"
#include <iostream>
#include <random>

// Create a "PCG" variant with a trivial output function, just truncation

template <typename xtype, typename itype>
struct truncate_only_mixin {
    static xtype output(itype internal)
    {
        constexpr size_t bits = sizeof(itype) * 8;
        return internal >> (bits/32);
    }
};

using lcg32 = pcg_detail::setseq_base<uint32_t, uint64_t, truncate_only_mixin>;

int main() {
    std::random_device rdev;
    uint64_t seed = 0;
    uint64_t stream = 0;
    for (int i = 0; i < 2; ++i) {
        seed   <<= 32;           
        seed   |= rdev();
        stream <<= 32;           
        stream |= rdev();
    }
    lcg32 rng1(seed,stream);
    lcg32 rng2(-seed,-1-stream);
    // pcg32 rng1(seed,stream);
    // pcg32 rng2(-seed,-1-stream);
    // pcg_engines::setseq_rxs_m_64_32 rng1(seed,stream);
    // pcg_engines::setseq_rxs_m_64_32 rng2(-seed,-1-stream);
    std::cerr << "RNG1: " << rng1 << "\n";
    std::cerr << "RNG2: " << rng2 << "\n";
    std::cout.precision(17);
    for (int i = 0; i < 10000; ++i) {
        std::cout << rng1()/4294967296.0 << "\t";
        std::cout << rng2()/4294967296.0 << "\n";
    }
}

Sebelum kita mulai, mari kita lihat grafik yang digambar @mdickinson tetapi hanya untuk LCG tanpa permutasi, hanya pemotongan:

corr-truncated-lcg

Perhatikan bahwa ini untuk LCG patologis dengan keadaan yang berkorelasi. Jika sebaliknya kami hanya memilih dua LCG dengan konstanta aditif yang dipilih secara acak (tetapi nilai awal yang sama), akan terlihat seperti ini:

corr-truncated-lcg-good

Pindah ke fungsi output PCG, jika kita menggunakan XSH RR pada kasus patologis terlihat seperti ini - ini adalah peningkatan besar pada grafik di atas tetapi jelas itu tidak sepenuhnya mengaburkan kengeriannya:

corr-pcg32-current

dan ini adalah RXS M dengan pasangan LCG dasar yang sama (berkorelasi buruk):

corr-pcg32-future

Tapi ini hanya sesuatu yang saya pertimbangkan untuk pcg32 . Hukuman kinerja kecil, dan pcg32 cukup kecil sehingga saya dapat membayangkan beberapa pengguna berat khawatir tentang membuat satu ton generator pcg32 diunggulkan secara acak dan meminta banyak nomor dari mereka dan memiliki peluang korelasi yang tidak terlalu kecil. Saya, sejujurnya, dalam dua pemikiran tentang hal itu, karena akankah pengguna kekuatan mitos ini menggunakan pcg32 pada awalnya.

Salah satu alasan saya tidak terlalu peduli untuk membuat aliran pcg64 lebih mandiri adalah karena saya tidak yakin saya melihat kasus penggunaan yang akan masuk akal untuk menjaga semua status lain tetap sama dan mengalihkan aliran ke nilai yang berbeda (misalnya, ke nilai acak, apalagi ke nilai yang berdekatan). Untuk hampir semua PRNG, cara yang benar untuk membuat PRNG kedua adalah menginisialisasi dengan entropi baru.

Kesimpulannya, untuk NumPy, saya pikir mungkin paling masuk akal untuk hanya mempertimbangkan bahwa PCG64 menginginkan dua status 256 bit (secara teknis 255 karena bit tinggi aliran diabaikan) dan menyebutnya selesai. Itu akan menghindari masalah yang terkait dengan API juga karena itu akan menjadi satu fitur yang lebih sedikit yang dimiliki orang di satu BitGenerator dan tidak di yang lain.

(Tetapi Anda mungkin ingin mengganti varian PCG 32-bit ke RXS M satu. Untuk sumber C, Anda memerlukan versi terbaru karena saya dulu tidak repot-repot menyediakan RXS M secara eksplisit dalam kode C, hanya membuatnya tersedia di C ++ inkarnasi.)

[Maaf jika ini lebih dari yang ingin Anda ketahui! Yah, bukan _that_ maaf. ;-)]

Salah satu alasan saya tidak terlalu peduli untuk membuat aliran pcg64 lebih independen adalah karena saya tidak yakin saya melihat kasus penggunaan yang akan masuk akal untuk menjaga semua status lain tetap sama dan mengalihkan aliran ke nilai yang berbeda (misalnya, ke nilai acak, apalagi ke nilai yang berdekatan). Untuk hampir semua PRNG, cara yang benar untuk membuat PRNG kedua adalah menginisialisasi dengan entropi baru.

Saya telah menjelaskan kasus penggunaan sebelumnya. Ada alasan kuat UX untuk menulis program stokastik yang menerima satu masukan "benih" pendek (yaitu sesuatu tentang ukuran yang dapat mereka salin-tempel dari email ke baris perintah) yang kemudian membuat keluaran dari program itu deterministik. @stevenjkern mencatat kepada saya dalam percakapan offline bahwa interaksi semacam itu penting untuk bekerja dengan badan pengatur yang harus memvalidasi perangkat lunaknya. Jika Anda harus menggunakan file _output_ dari sebuah program untuk mereplikasi hasilnya, itu terlihat sedikit mencurigakan dalam keadaan seperti itu. Regulator harus menyelami kode secara mendalam (yang mungkin sebenarnya tidak tersedia bagi mereka) untuk memastikan bahwa informasi dalam file benar-benar halal.

Kami sekarang memiliki alat yang bagus dengan Python untuk menjalankan proses paralel N secara dinamis untuk melakukan beberapa bagian dari pekerjaan kemudian mengumpulkan hasil dan melanjutkan dalam proses utama (kemudian putar proses M nanti, dll.). Tidak seperti skema yang lebih lama dan kurang fleksibel seperti MPI, kami tidak hanya memutar proses N tetap di awal. Dalam kasus tersebut, saya dapat melihat entropi-seeding setiap N PRNG dan menyimpannya ke file karena hanya ada satu tempat dalam program yang melakukan itu. Setidaknya dari perspektif pemrograman, itu tidak terlalu sulit. Kami memiliki alat yang jauh lebih fleksibel untuk paralelisme sekarang. Pembibitan PRNG sekarang menjadi penghambat yang mencegah kami menggunakan fleksibilitas tersebut dalam program stokastik. Tidak ada lagi satu titik tanggung jawab di mana kita dapat menempatkan pembukuan berbasis file.

Kebutuhan untuk mendapatkan aliran N yang dapat direproduksi cukup kuat sehingga orang akan melakukan hal-hal aneh untuk mendapatkannya dengan algoritme MT kami saat ini. Saya harus menghentikan banyak skema berisiko, dan saya berharap aliran PCG akan membantu kami sampai di sana.

Apa pendapat Anda tentang menggunakan hash bijektiva yang baik di atas 2**63 / 2**127 untuk mendapatkan kenaikan dari urutan penghitung 0,1,2,3, ... sambil menjaga keadaan tetap sama? Apakah Anda memperkirakan ada masalah dengan itu? Apa pendapat Anda tentang menggabungkan peningkatan hash yang diikuti oleh lonjakan besar untuk memindahkan status ke bagian jauh dari siklus baru? Mungkin kita bisa memindahkan sub-diskusi ini ke email atau masalah lain dan melaporkan kembali.

@rkern , mungkin ada sesuatu yang menyenangkan tentang dapat memberikan benih yang sangat singkat kepada PRNG, tetapi (terlepas dari PRNG), itu ide yang buruk. Jika Anda memberikan _k_ bit masukan seed, dan kemudian meminta _k_ bits (langsung, atau lewati _j_ bits terlebih dahulu [untuk beberapa _j_ arbitrary] dan kemudian membaca _k_ bits), meskipun semua 2 ^ _k_ integer adalah masukan yang valid, tidak semua 2 ^ _k_ keluaran dapat diamati (karena fungsi dari bit ke bit keluar tidak dijamin [dan benar-benar tidak bisa] bijection). Distribusi yang diharapkan adalah Binomial (2 ^ k, 2 ^ -k), yang dapat kita perkirakan sebagai distribusi Poisson dan dengan demikian nilai 2 ^ k / e tidak akan diamati. Ini benar tidak peduli apa PRNG itu. Yang bisa kita lakukan adalah membuat _k_ cukup besar sehingga sama sekali tidak praktis untuk mencari tahu apa yang hilang.

Masalahnya bertambah ketika setiap orang, katakanlah, menggunakan PRNG yang sama (misalnya Mersenne Twister) dan memetik benih dari set kecil yang sama (misalnya, jumlahnya kurang dari 10000), karena daripada bias per program tertentu yang sewenang-wenang, itu sebuah _for-everyone do this_ bias. Sebagai contoh, misalkan Anda memilih seed empat digit dan kemudian mengambil sejumlah angka yang wajar dari Mersenne Twister, (katakanlah, kurang dari satu juta). Dalam situasi itu, saya dapat meyakinkan Anda bahwa angka sial 13 _tidak akan pernah muncul_ sebagai salah satu dari 10 miliar output (sebenarnya sekitar 10% dari bilangan bulat 32-bit tidak akan ada), dan angka 123580738 terlalu diwakili oleh faktor faktor 16. Ini persis seperti yang kami harapkan untuk sampel acak dari sepuluh miliar bilangan bulat 32-bit, tetapi ini adalah masalah nyata _ jika semua orang menggunakan sampel yang sama_. Kami akan memiliki masalah yang sama persis jika setiap orang mengambil benih sembilan digit dan hanya menarik 10.000 nomor.

Fakta bahwa banyak orang ingin melakukan sesuatu tidak menjadikannya ide yang bagus. (Itu tidak berarti tidak apa-apa untuk memberi tahu hanya orang bahwa mereka melakukan kesalahan atau menginginkan hal yang salah. Anda harus mencari tahu apa yang sebenarnya mereka butuhkan (misalnya, hasil yang dapat direproduksi dari argumen baris perintah yang singkat - mungkin hal yang benar adalah mengizinkan penyemaian dari UUID dan bilangan bulat kecil; beberapa ide tentang cara mengacak hal-hal ini dengan baik untuk membuat data benih dapat ditemukan di entri blog ini dan diubah menjadi

(Ini kode untuk dimainkan, karena cukup pendek ...)

// mtbias.cpp -- warning, uses 4GB of RAM, runs for a few minutes
// note: this is *not* showing a problem with the Mersenne Twister per se, it is
// showing a problem with simplistic seeding

#include <vector>
#include <iostream>
#include <random>
#include <cstdint>

int main() {
    std::vector<uint8_t> counts(size_t(std::mt19937::max()) + 1);
    for (size_t seed=0; seed < 10000; ++seed) {
        std::mt19937 rng(seed);
        for (uint i = 0; i < 1000000; ++i) {
            ++counts[rng()];
        }
    }
    size_t shown = 0;
    std::cout << "Never occurring: ";
    for (size_t i = 0; i <= std::mt19937::max(); ++i) {
        if (counts[i] == 0) {
            std::cout << i << ", ";
            if (++shown >= 20) {
                std::cout << "...";
                break;
            }
        }
    }
    std::cout << "\nMost overrepresented: ";
    size_t highrep_count = 0;
    size_t highrep_n = 0;
    for (size_t i = 0; i <= std::mt19937::max(); ++i) {
        if (counts[i] > highrep_count) {
            highrep_n = i;
            highrep_count = counts[i];
        }
    }
    std::cout << highrep_n << " -- repeated " << highrep_count << " times\n";
}

Seperti yang telah saya katakan sebelumnya, menurut saya seed 128-bit cukup pendek untuk tujuan itu, dan saya dapat membuat perkakas untuk membantu orang menulis program yang melakukan hal yang benar. Yaitu, sampel entropi secara default, mencetaknya atau mencatatnya, lalu membiarkannya diteruskan nanti. Rekomendasi Anda untuk menghasilkan UUID untuk setiap program dan mencampurkan seed yang disediakan pengguna yang mungkin lebih kecil per proses juga bagus.

Mari kita asumsikan bahwa saya dapat membuat orang menggunakan seed 128-bit yang bagus untuk bagian negara bagian dari PCG64 , dengan satu atau lain cara. Apakah Anda memiliki komentar tentang memperoleh aliran dari status yang sama? Saya tidak ingin menggambar lebih banyak angka, secara keseluruhan, daripada yang kami lakukan dari satu aliran PCG64 . Saya hanya ingin menggambar angka-angka ini dalam proses yang berbeda tanpa koordinasi pada setiap undian. Menggunakan hash ad hoc 63-bit

@tokopedia

Mungkin berguna untuk menjelaskan apa yang kami maksud dengan singkat.

Saya pikir @rkern menulis "sesuatu tentang ukuran yang dapat mereka salin-tempel dari email ke baris perintah". Saya bisa mewakili angka yang cukup besar dalam beberapa karakter seperti 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff.

Saya hanya ingin menggambar angka-angka ini dalam proses yang berbeda tanpa koordinasi pada setiap undian. Menggunakan hash ad hoc 63-bit

Sudahkah Anda mencoba menyisipkan aliran n menggunakan benih kualitas tunggal dengan memajukan status dengan angka yang cukup besar (misalnya 2 ** 64, yang digunakan oleh PCG64.jumped )? Ini sepertinya cara termudah untuk mengoordinasikan aliran n besar secara longgar di seluruh kluster menggunakan sesuatu seperti PCG64(seed).jumped(node_id)

dimana node_id adalah 0,1,2, ...

Apakah ada PRNG yang benar-benar bagus dalam menghasilkan aliran independen sederhana menggunakan sesuatu seperti indeks? Saya percaya bahwa MLFG bisa, tapi saya tidak suka ini karena itu generator 63-bit.

@bashtage , itu bukanlah cara yang tepat untuk melakukannya. Cara yang benar adalah dengan mengambil seed, jika Anda ingin menambahkan integer kecil, gunakan fungsi hash untuk melakukan hash. Seperti yang disebutkan sebelumnya, saya sebelumnya (terlepas dari PCG) menulis fungsi mixing yang serius [edit: fix link ke pos yang benar] untuk mencampur berbagai macam entropi besar dan kecil. Anda tidak harus menggunakan milik saya, tetapi saya merekomendasikan Anda melakukan sesuatu seperti itu.

Idealnya, Anda menginginkan mekanisme yang tidak spesifik untuk PCG. PCG mungkin bukan pilihan default Anda, dan meskipun demikian, Anda ingin orang melakukan hal serupa dengan semua generator. Saya tidak berpikir Anda harus menginginkan skema untuk membuat beberapa PRNG independen yang bergantung pada aliran atau lompatan ke depan.

(Ups, saya menautkan ke entri blog yang salah; saya telah mengedit pesan sebelumnya, tetapi jika Anda membaca melalui email, saya bermaksud menautkan ke entri blog ini )

@imneme Saat ini, semua generator yang kami miliki mendukung jump (beberapa di antaranya benar-benar panggilan tipe advance). Saya yakin bahwa penyemaian dengan hati-hati adalah ide yang bagus, saya curiga banyak pengguna yang akan tergoda untuk menggunakan panggilan PRNG.jumped() . Apakah ini sesuatu yang harus dibujuk?

Untuk pembibitan, semua generator MT menggunakan rutinitas init penulis, PCG menggunakan milik Anda, dan sisanya seperti

seed = np.array(required_size, dtype=np.uint64)
last = 0
for i in range(len(user_seed))
    if i < len(user_seed)
        last = seed[i] = splitmix64(last ^ user_seed[i])
    else:
        last = seed[i] = splitmix64(last)

Saya membayangkan ini bisa diperbaiki.

Apakah ini sesuatu yang harus dibujuk?

Saya belum melihat jumped . Ini cukup mengerikan untuk LCG yang mendasarinya.

Misalkan kita memiliki pengali, M, dari 0x96704a6bb5d2c4fb3aa645df0540268d . Jika kita menghitung M ^ (2 ^ 64), kita mendapatkan 0x6147671fb92252440000000000000001 yang merupakan pengganda LCG yang buruk. Jadi jika Anda mengambil setiap 2 ^ 64 item dari LCG 128-bit, itu akan menjadi buruk (bit order rendah hanyalah sebuah counter). Fungsi permutasi standar PCG dirancang untuk mengacak keluaran normal LCG, bukan untuk mengacak penghitung.

PCG64 saat ini diuji hingga setengah petabyte dengan Practrand dan analisis lebih lanjut menunjukkan bahwa Anda dapat membaca banyak petabyte tanpa masalah terkait kekuatan dua. Sayangnya, jika Anda melompat ke depan untuk melewati kekuatan dua yang sangat besar, permutasi PCG yang biasa (agak sederhana) tidak dapat cukup mengimbangi urutan patologis dari melewatkan jarak besar LCG yang mendasarinya seperti ini. Anda dapat meningkatkan ante kekuatan permutasi untuk memperbaikinya, dan pada kenyataannya baik I dan Vigna secara independen membandingkan permutasi standar PCG terhadap fungsi hash integer off-the shelf yang kemungkinan besar akan melakukannya (bagaimanapun juga, mereka adalah dasar dari SplitMix yang _is_ hanya sebuah counter). Ketika saya melihatnya pada tahun 2014 dengan Fast Hash, kecepatannya tidak terlalu bagus, tetapi ketika Vigna melakukannya baru-baru ini dengan murmurhash, dia mengklaim kinerjanya mengalahkan PCG standar (!).

Jika Anda benar-benar ingin memiliki 2 ^ 64 lompatan ke depan, saya pikir Anda perlu beralih ke permutasi fungsi keluaran yang lebih kuat (yang seperti yang telah kita lihat dapat dilakukan dengan biaya rendah). Tetapi jika Anda merasa itu membuatnya tidak benar-benar PCG "standar" lagi dan ingin mempertahankan permutasi keluaran biasa, maka jumped() mungkin perlu dihilangkan.

(BTW, lompatan patologis juga berlaku untuk PRNG lain. SplitMix diketahui memiliki beberapa peningkatan yang buruk dan masuk akal untuk mengasumsikan bahwa meskipun kenaikan biasa (a.ka. “gamma”) dari 0xbd24b73a95fb84d9 baik-baik saja, maju sebesar 2 ^ 32 akan memberi Anda peningkatan sebesar 0x95fb84d900000000, yang tidak begitu baik. Untuk LFSR, lompatan ke depan yang buruk mungkin bukan kekuatan dua, tapi saya cukup yakin akan ada lompatan di mana matriks yang mendasari berakhir secara patologis jarang.)

Saya dapat mengonfirmasi, setidaknya dengan PCG32 , 4 aliran berselang-seling menggunakan .jumped() gagal dengan sangat cepat.

❯ ./pcg_streams.py --jumped -n 4 | time ./RNG_test stdin32
[
    {
        "bit_generator": "PCG32",
        "state": {
            "state": 10149010587776656704,
            "inc": 2891336453
        }
    },
    {
        "bit_generator": "PCG32",
        "state": {
            "state": 1158608670957446464,
            "inc": 2891336453
        }
    },
    {
        "bit_generator": "PCG32",
        "state": {
            "state": 10614950827847787840,
            "inc": 2891336453
        }
    },
    {
        "bit_generator": "PCG32",
        "state": {
            "state": 1624548911028577600,
            "inc": 2891336453
        }
    }
]
RNG_test using PractRand version 0.93
RNG = RNG_stdin32, seed = 0xeedd49a8
test set = normal, folding = standard (32 bit)

rng=RNG_stdin32, seed=0xeedd49a8
length= 128 megabytes (2^27 bytes), time= 2.1 seconds
  Test Name                         Raw       Processed     Evaluation
  BCFN(2+0,13-3,T)                  R= +58.7  p =  1.3e-27    FAIL !!!       
  BCFN(2+1,13-3,T)                  R= +48.0  p =  1.5e-22    FAIL !!        
  BCFN(2+2,13-3,T)                  R= +16.0  p =  2.3e-7   very suspicious  
  DC6-9x1Bytes-1                    R= +53.5  p =  1.8e-32    FAIL !!!       
  [Low8/32]DC6-9x1Bytes-1           R= +27.4  p =  1.1e-17    FAIL !         
  ...and 112 test result(s) without anomalies

Idealnya, Anda menginginkan mekanisme yang tidak spesifik untuk PCG. PCG mungkin bukan pilihan default Anda, dan meskipun demikian, Anda ingin orang melakukan hal serupa dengan semua generator.

Nah, itulah yang kami coba putuskan di sini. :-) Kami cukup puas dengan hanya mengekspos fitur apa pun yang disediakan setiap PRNG, dengan asumsi bahwa properti yang diekspos oleh setiap algoritme dipelajari dengan baik. Kami juga cukup puas dengan mengatakan "inilah PRNG default yang kami rekomendasikan; ia memiliki banyak fitur yang berguna; yang lain mungkin tidak memilikinya".

Gagasan menggunakan hash untuk mendapatkan status baru dari status tertentu dan ID streaming, untuk algoritme apa pun, adalah menarik. Tahukah Anda seberapa baik dipelajari itu? Kedengarannya seperti masalah penelitian untuk memverifikasi bahwa itu berfungsi dengan baik untuk semua algoritme. Saya ragu untuk mengklaim "inilah prosedur umum untuk mendapatkan aliran independen untuk semua PRNG kami". Saya lebih puas dengan "inilah API umum untuk memperoleh aliran independen; setiap PRNG mengimplementasikannya dengan cara apa pun yang sesuai untuk algoritme dan mungkin tidak menerapkannya jika algoritme tidak mendukungnya dengan baik".

Di sisi lain, jika itu hanya masalah mengalokasikan siklus CPU yang cukup untuk menguji aliran interleaved untuk setiap BitGenerator keluar ke N GiB di PractRand, itu tidak terlalu memberatkan.

Gagasan menggunakan hash untuk mendapatkan status baru dari status tertentu dan ID streaming, untuk algoritme apa pun, adalah menarik. Tahukah Anda seberapa baik dipelajari itu? Kedengarannya seperti masalah penelitian untuk memverifikasi bahwa itu berfungsi dengan baik untuk semua algoritme. Saya ragu untuk mengklaim "inilah prosedur umum untuk mendapatkan aliran independen untuk semua PRNG kami". Saya lebih puas dengan "inilah API umum untuk memperoleh aliran independen; setiap PRNG mengimplementasikannya dengan cara apa pun yang sesuai untuk algoritme dan mungkin tidak menerapkannya jika algoritme tidak mendukungnya dengan baik".

Saya tidak tahu bahwa Anda dapat menyebutnya "masalah penelitian" (dan dengan demikian "dipelajari dengan baik") dengan tepat, tetapi C ++ 11 (yang sebagian besar tentang penggunaan teknik yang telah terbukti dan benar) menyediakan konsep _SeedSequence_ (dan implementasi std::seed_seq ) yang tugasnya adalah menyediakan data seeding ke PRNG yang sepenuhnya arbitrer.

Secara umum, hampir semua PRNG berharap untuk diinisialisasi / di-seed dengan bit acak. Tidak ada yang sangat ajaib tentang bit acak yang keluar dari (katakanlah) random.org dan bit acak yang keluar dari sesuatu yang lebih algoritmik (CS PRNG, fungsi hash, dll.).

Cukup mudah untuk memikirkan kumpulan PRNG dari skema yang sama yang semuanya diunggulkan dengan bit acaknya sendiri. Anda dapat menganggap apa yang kami lakukan sebagai titik pengambilan (atau sebenarnya interval hingga panjang maksimum tertentu sesuai dengan jumlah nomor acak yang pernah kami harapkan untuk diminta secara masuk akal, misalnya, 2 ^ 56) pada satu baris (misalnya, a baris dengan 2 ^ 255 poin). Kita dapat menghitung probabilitas jika kita meminta interval _n_ yang satu akan tumpang tindih dengan yang lain. Ini adalah probabilitas yang cukup mendasar - Saya tidak yakin Anda bisa menerbitkan makalah tentangnya karena (seperti yang saya pahami) tidak ada yang tertarik dengan makalah yang berisi matematika dasar. ( @lemire mungkin tidak setuju!)

[Saya berpendapat bahwa yang biasanya Anda _not_ lakukan adalah memasukkan PRNG dengan bit acak keluar dari dirinya sendiri. Itu terasa terlalu incest bagi saya.]

Benar, jelas bagi saya bahwa menggunakan sesuatu seperti _SeedSequence_ yang dirancang dengan baik akan menjadi cara untuk mengambil benih awal yang sewenang-wenang dan menggambar beberapa titik awal dalam siklus algoritme kami yang seharusnya tidak tumpang tindih. Dan jika itu satu-satunya cara nyata untuk mendapatkan streaming independen, biarlah. Ini akan menjadi masalah desain API untuk membuatnya nyaman.

Yang kurang saya jelaskan adalah seberapa aman mengambil status saat ini dari PRNG yang diinisialisasi, campuran hash di ID streaming untuk melompat ke status baru dalam siklus, yang menurut saya Anda sarankan (dan itu terpikir oleh saya kemudian bahwa saya mungkin salah tentang itu). Terpisah dengan baik dalam siklus bukanlah satu-satunya faktor, seperti yang ditunjukkan oleh kegagalan jumped() . jumped() juga memastikan bahwa Anda sedang dikirim ke bagian yang jauh dari urutan yang tidak akan tumpang tindih; itu hanya bagian yang dapat berkorelasi sangat kuat dengan bagian awal jika lompatan tidak dipilih dengan baik. Diperlukan beberapa pengetahuan tentang internal setiap algoritme untuk mengetahui lompatan yang baik dan tidak. Kami jelas tidak melakukannya untuk kasus PCG.

Pada dasarnya, jika kita menganggap PRNG sebagai fungsi transisi dan fungsi keluaran, new_state = seed_seq(old_state||streamID) ini hanyalah fungsi transisi lain yang kita letakkan untuk satu langkah. Kita harus yakin bahwa operasi yang terlibat dalam seed_seq itu cukup berbeda dari fungsi transisi di setiap algoritma PRNG (atau inversnya) dan mungkin harus memastikan hal-hal lain. Saya tidak ingin menggunakan sesuatu yang dibangun dari, katakanlah, wyhash untuk menginisialisasi wyrand . Seperti yang Anda katakan, Anda tidak ingin menggunakan PRNG itu sendiri untuk menyediakan bit itu sendiri. Itu sebabnya saya pikir perlu beberapa studi untuk memastikan bahwa untuk semua PRNG kami (studi yang saya harap tidak harus dilakukan sendiri).

Di sisi lain, new_state = seed_seq(old_state||streamID) mungkin tidak lebih buruk dalam hal ini daripada penggunaan _SeedSequence_ yang dimaksudkan untuk beberapa aliran: tarik dua status secara berurutan. Jika demikian, maka saya akan baik-baik saja mengandalkan pengalaman C ++, mungkin dengan implementasi Anda, dan hanya melakukan beberapa pengujian empiris dengan PractRand untuk semua algoritme kami untuk menunjukkan bahwa mereka tidak lebih buruk daripada rekan aliran tunggal mereka.

Akan sangat menyenangkan jika hash-jump berfungsi karena itu membuka beberapa kasus penggunaan untuk pemijahan PRNG dengan cara yang bebas koordinasi. Menggunakan ID streaming memerlukan beberapa komunikasi atau pra-alokasi. dask telah meminta sesuatu seperti ini di masa lalu.

Jika ada alternatif bagus yang hanya mengandalkan penyemaian yang baik sehingga kita dapat membuat nyaman untuk melakukan hal yang benar, maka kita mungkin harus menghapus aliran yang dapat diatur sebagai kriteria untuk pemilihan default. Kami hanya menginginkan algoritme default yang memiliki ruang status yang cukup besar.

Semua yang dikatakan, sepertinya menggunakan hash 63-bit untuk mendapatkan kenaikan PCG32 dari ID aliran berurutan ( range(N) ) tampaknya berfungsi. 8192 aliran berselang-seling melewati PractRand ke 2 TiB. Jika kami mengekspos ID aliran untuk generator PCG, kami mungkin ingin menggunakan teknik ini untuk mendapatkan kenaikan, bahkan jika kami menyarankan orang menggunakan cara lain untuk mendapatkan aliran independen yang dapat direproduksi.

Yang kurang saya jelaskan adalah seberapa aman mengambil status saat ini dari PRNG yang diinisialisasi, campuran hash di ID streaming untuk melompat ke status baru dalam siklus, yang menurut saya Anda sarankan (dan itu terpikir oleh saya kemudian bahwa saya mungkin salah tentang itu).

Saya mungkin mengekspresikan diri saya secara ambigu, tetapi tidak , saya tidak pernah bermaksud untuk menyarankan bahwa status PRNG saat ini harus digunakan dalam swa-reseeding.

Tapi, FWIW, SplitMix melakukan ini, itulah yang dilakukan operasi split() . Dan, saya tidak suka itu melakukannya.

Ini mungkin terlalu banyak informasi, tetapi saya akan berbagi sedikit tentang mengapa saya merasa ngeri (mungkin lebih ngeri dari yang seharusnya) oleh fungsi split() SplitMix. Sebagai catatan sejarah, SplitMix dan PCG dirancang secara independen sekitar waktu yang sama (SplitMix diterbitkan pada tanggal 20 Oktober 2014, sedangkan pcg-random.org ditayangkan pada bulan Agustus 2014 dan ditautkan ke makalah PCG pada tanggal 5 September 2014 ). Ada beberapa kesamaan antara PCG dan SplitMix (dan berbagai PRNG lainnya, termasuk xor shift * dan xorshift + Vigna - juga dirilis ke dunia pada tahun 2014). Semua memiliki fungsi transisi status yang cukup sederhana yang tidak cukup baik yang diperbaiki oleh fungsi keluaran yang acak. Ketika saya menulis makalah PCG, satu hal yang saya tahu beberapa orang akan suka adalah fungsi split() tetapi tidak tahu cara yang baik untuk melakukannya; alih-alih saya mengembangkan bukti cepat bahwa jika Anda memiliki PRNG _k_-bit di mana Anda dapat pergi ke kiri atau kanan pada setiap langkah, dalam langkah _k_ Anda harus dapat mencapai keadaan yang pernah Anda alami sebelumnya, sehingga membuktikan keseluruhan konsep dipahami dengan buruk. Pengamatan itu tidak membuatnya menjadi kertas. Tetapi sebagai hasil dari pemikiran saya sebelum bukti itu, dalam catatan kaki di draft makalah yang hampir final, saya menyarankan, agak aneh, karena output PCG adalah hash / scramble / permutasi dari statusnya, jika Anda merasa nakal Anda bisa memasang kembali generator dengan outputnya sendiri dan lolos begitu saja. Saya mengeluarkannya dari versi final karena saya pikir imajinasi seperti itu akan menjadi tanda bahaya yang terlalu besar bagi pengulas, mengingat bahwa pemberian ulang PRNG dengan statusnya sendiri secara luas dianggap sebagai jenis penyalahgunaan PRNG, dan semacamnya hal yang kami lihat dari orang-orang yang tidak berpengalaman dalam menggunakannya.

Membaca makalah SplitMix, saya menemukan banyak hal yang disukai, tetapi saya sangat terkejut ketika melihat split() . Itu melakukan sesuatu yang pada dasarnya saya anggap hanya sebagai lelucon dan menjadikannya fitur tentpole. Tidak sampai beberapa tahun kemudian saya sempat menulis lebih dalam secara teknis tentang apa yang terjadi ketika Anda memiliki operasi semacam ini.

Pengambilan keseluruhan adalah bahwa jika Anda memiliki ruang status yang cukup besar (dan SplitMix hampir tidak cukup), Anda mungkin dapat melakukan reseeding sendiri melalui fungsi hash. Saya masih merasa ini bukan ide yang bagus. Karena pemetaan acak (yang kita hadapi dalam situasi ini) memiliki properti seperti "dengan probabilitas asimtotik bukan nol, pohon tertinggi dalam grafik fungsional tidak berakar pada siklus terpanjang", saya rasa sulit untuk memiliki keyakinan penuh kecuali perancang telah pergi ke pekerjaan yang diperlukan untuk menunjukkan bahwa patologi semacam itu tidak ada dalam desain mereka.

Untuk bersenang-senang, berikut adalah dump dari state-space versi kecil dari SplitMix yang mengeksplorasi hanya tiga cara berbeda (dan tetap kaku) untuk menggabungkan next() dan split() :

Testing: SplitMix16: void advance() { rng = rng.split();}

Finding cycles...
- state 00000000 -> new cycle 1, size 4, at 000043b0 after 516 steps
- state 00000050 -> new cycle 2, size 41, at 00002103 after 2 steps
- state 000000cd -> new cycle 3, size 4, at 0000681a after 6 steps
- state 00000141 -> new cycle 4, size 23, at 00004001 after 11 steps
- state 00000dee -> new cycle 5, size 7, at 00007436 after 4 steps
- state 00008000 -> new cycle 6, size 90278, at 5e5ce38c after 46472 steps
- state 00030000 -> new cycle 7, size 6572, at 12c65374 after 10187 steps
- state 00030016 -> new cycle 8, size 3286, at 65d0fc0c after 402 steps
- state 00058000 -> new cycle 9, size 17097, at 2a2951fb after 31983 steps
- state 08040000 -> new cycle 10, size 36, at 08040000 after 0 steps
- state 08040001 -> new cycle 11, size 218, at 08040740 after 360 steps
- state 08040004 -> new cycle 12, size 10, at 38c01b3d after 107 steps
- state 08040006 -> new cycle 13, size 62, at 38c013a0 after 39 steps
- state 08040009 -> new cycle 14, size 124, at 08045259 after 24 steps
- state 08040019 -> new cycle 15, size 32, at 38c06c63 after 151 steps
- state 08040059 -> new cycle 16, size 34, at 38c00217 after 17 steps
- state 08040243 -> new cycle 17, size 16, at 38c06e36 after 13 steps
- state 123c8000 -> new cycle 18, size 684, at 77d9595f after 194 steps
- state 123c8002 -> new cycle 19, size 336, at 5de8164d after 141 steps
- state 123c9535 -> new cycle 20, size 12, at 123c9535 after 0 steps
- state 139f0000 -> new cycle 21, size 545, at 743e3a31 after 474 steps
- state 139f0b35 -> new cycle 22, size 5, at 139f0b35 after 0 steps
- state 139f1b35 -> new cycle 23, size 5, at 68d3c943 after 8 steps

Cycle Summary:
- Cycle 1, Period 4, Feeders 32095
- Cycle 2, Period 41, Feeders 188
- Cycle 3, Period 4, Feeders 214
- Cycle 4, Period 23, Feeders 180
- Cycle 5, Period 7, Feeders 12
- Cycle 6, Period 90278, Feeders 1479024474
- Cycle 7, Period 6572, Feeders 102385385
- Cycle 8, Period 3286, Feeders 5280405
- Cycle 9, Period 17097, Feeders 560217399
- Cycle 10, Period 36, Feeders 413
- Cycle 11, Period 218, Feeders 51390
- Cycle 12, Period 10, Feeders 1080
- Cycle 13, Period 62, Feeders 4113
- Cycle 14, Period 124, Feeders 4809
- Cycle 15, Period 32, Feeders 2567
- Cycle 16, Period 34, Feeders 545
- Cycle 17, Period 16, Feeders 87
- Cycle 18, Period 684, Feeders 95306
- Cycle 19, Period 336, Feeders 100263
- Cycle 20, Period 12, Feeders 7
- Cycle 21, Period 545, Feeders 163239
- Cycle 22, Period 5, Feeders 12
- Cycle 23, Period 5, Feeders 34

- Histogram of indegrees of all 2147483648 nodes:
      0  529334272
      1 1089077248
      2  528875520
      3     131072
      4      65536
Testing: SplitMix16: void advance() { rng.next(); rng = rng.split();}

Finding cycles...
- state 00000000 -> new cycle 1, size 36174, at 6b34fe8b after 21045 steps
- state 00000002 -> new cycle 2, size 4300, at 042a7c6b after 51287 steps
- state 0000000f -> new cycle 3, size 11050, at 0b471eb5 after 4832 steps
- state 0000001d -> new cycle 4, size 38804, at 2879c05c after 16280 steps
- state 00000020 -> new cycle 5, size 4606, at 46e0bdf6 after 7379 steps
- state 00046307 -> new cycle 6, size 137, at 0a180f87 after 89 steps
- state 00081c25 -> new cycle 7, size 16, at 177ed4d8 after 27 steps
- state 0044c604 -> new cycle 8, size 140, at 5e1f125b after 44 steps
- state 006e329f -> new cycle 9, size 18, at 006e329f after 0 steps
- state 13ebcefc -> new cycle 10, size 10, at 13ebcefc after 0 steps

Cycle Summary:
- Cycle 1, Period 36174, Feeders 975695553
- Cycle 2, Period 4300, Feeders 766130785
- Cycle 3, Period 11050, Feeders 110698235
- Cycle 4, Period 38804, Feeders 251133911
- Cycle 5, Period 4606, Feeders 43723200
- Cycle 6, Period 137, Feeders 4101
- Cycle 7, Period 16, Feeders 172
- Cycle 8, Period 140, Feeders 2310
- Cycle 9, Period 18, Feeders 124
- Cycle 10, Period 10, Feeders 2

- Histogram of indegrees of all 2147483648 nodes:
      0  529334272
      1 1089077248
      2  528875520
      3     131072
      4      65536
Testing: SplitMix16: void advance() { rng.next(); rng = rng.split(); rng = rng.split();}

Finding cycles...
- state 00000000 -> new cycle 1, size 40959, at 0069b555 after 49520 steps
- state 00000031 -> new cycle 2, size 1436, at 5f619520 after 2229 steps
- state 000003a4 -> new cycle 3, size 878, at 18d1cb99 after 1620 steps
- state 0000046c -> new cycle 4, size 2596, at 46ba79c0 after 1591 steps
- state 0000c6e2 -> new cycle 5, size 24, at 0212f11b after 179 steps
- state 000af7c9 -> new cycle 6, size 61, at 40684560 after 14 steps
- state 00154c16 -> new cycle 7, size 110, at 29e067ce after 12 steps
- state 0986e055 -> new cycle 8, size 4, at 2b701c82 after 7 steps
- state 09e73c93 -> new cycle 9, size 3, at 352aab83 after 1 steps
- state 19dda2c0 -> new cycle 10, size 1, at 78825f1b after 2 steps

Cycle Summary:
- Cycle 1, Period 40959, Feeders 2129209855
- Cycle 2, Period 1436, Feeders 5125630
- Cycle 3, Period 878, Feeders 7077139
- Cycle 4, Period 2596, Feeders 5997555
- Cycle 5, Period 24, Feeders 24221
- Cycle 6, Period 61, Feeders 1774
- Cycle 7, Period 110, Feeders 1372
- Cycle 8, Period 4, Feeders 23
- Cycle 9, Period 3, Feeders 4
- Cycle 10, Period 1, Feeders 3

- Histogram of indegrees of all 2147483648 nodes:
      0  829903716
      1  684575196
      2  468475086
      3  132259769
      4   32192209
      5      58402
      6      17026
      7       1982
      8        261
      9          1
Testing: SplitMix16: void advance() { rng.next(); rng.next(); rng = rng.split();}

Finding cycles...
- state 00000000 -> new cycle 1, size 55038, at 3e57af06 after 30005 steps
- state 00000005 -> new cycle 2, size 376, at 4979e8b5 after 6135 steps
- state 0000001e -> new cycle 3, size 10261, at 0cd55c94 after 1837 steps
- state 0000002d -> new cycle 4, size 3778, at 7f5f6afe after 3781 steps
- state 00000064 -> new cycle 5, size 2596, at 3bc5404b after 5124 steps
- state 0000012b -> new cycle 6, size 4210, at 525cc9f3 after 397 steps
- state 00000277 -> new cycle 7, size 1580, at 410010c8 after 1113 steps
- state 00001394 -> new cycle 8, size 916, at 7b20dfb0 after 193 steps
- state 00063c2d -> new cycle 9, size 51, at 6e92350b after 121 steps
- state 058426a6 -> new cycle 10, size 8, at 058426a6 after 0 steps
- state 0e5d412d -> new cycle 11, size 1, at 0e5d412d after 0 steps
- state 4c2556c2 -> new cycle 12, size 1, at 4c2556c2 after 0 steps

Cycle Summary:
- Cycle 1, Period 55038, Feeders 2027042770
- Cycle 2, Period 376, Feeders 28715945
- Cycle 3, Period 10261, Feeders 49621538
- Cycle 4, Period 3778, Feeders 13709744
- Cycle 5, Period 2596, Feeders 15367156
- Cycle 6, Period 4210, Feeders 10418779
- Cycle 7, Period 1580, Feeders 1782252
- Cycle 8, Period 916, Feeders 744273
- Cycle 9, Period 51, Feeders 2351
- Cycle 10, Period 8, Feeders 24
- Cycle 11, Period 1, Feeders 0
- Cycle 12, Period 1, Feeders 0

- Histogram of indegrees of all 2147483648 nodes:
      0  529334272
      1 1089077248
      2  528875520
      3     131072
      4      65536

dll.

Ah, bagus. Saya sendiri yang menolak beberapa proposal seperti itu beberapa tahun yang lalu, jadi saya takut kami melewatkan sesuatu yang baik. :-)

Adakah pemikiran akhir tentang pendekatan hash untuk mendapatkan kenaikan untuk aliran PCG? Mengesampingkan apakah itu mekanisme utama untuk mendapatkan aliran independen. Singkatnya menghapus akses ke fitur itu sama sekali, sepertinya itu adalah sesuatu yang ingin kami lakukan untuk mencegah ID streaming berurutan yang mudah disalahgunakan.

Karena penasaran, apakah ada cara (mudah) untuk mengetahui seberapa jauh jarak dua status di PCG64?

Ya, meskipun kami tidak mengungkapkannya: http://www.pcg-random.org/useful-features.html#distance

Karena penasaran, apakah ada cara (mudah) untuk mengetahui seberapa jauh jarak dua status di PCG64?

Ya, meskipun kami tidak mengungkapkannya: http://www.pcg-random.org/useful-features.html#distance

Dalam sumber C ++, fungsi jarak bahkan akan memberi tahu Anda jarak antar aliran, memberikan titik terdekatnya (di mana satu-satunya perbedaan antara aliran adalah konstanta tambahan).

Kebetulan, untuk LCG yang mendasari, kita dapat menggunakan jarak untuk mengetahui seberapa berkorelasi yang kita harapkan dengan posisi. Jarak dekat jelas buruk (dan buruk untuk PRNG apa pun), tetapi jarak dengan hanya satu set bit juga tidak bagus, itulah sebabnya melompat ke depan ke 2 ^ 64 ( 0x10000000000000000 ) dengan .jumped adalah ide yang buruk. Pada daftar tugas PCG saya menulis fungsi " independence_score " yang melihat jarak antara dua keadaan dan memberi tahu Anda seberapa acak jaraknya (melalui hamming weight, dll - idealnya kita ingin sekitar setengah bit menjadi nol dan setengah satu dan mereka tersebar bebas).

Salah satu cara untuk _mempertahankan_ jumped dengan PCG64 adalah dengan tidak melompat sebesar n * 0x10000000000000000 melainkan melompat n * 0x9e3779b97f4a7c150000000000000000 (terpotong menjadi 128 bit). Ini akan memberi Anda semua properti biasa yang Anda inginkan ( .jumped(3).jumped(5) == .jumped(8) ) tanpa menjadi patologis untuk LCG yang mendasarinya.

(Saya juga sadar bahwa mengatakan "jangan maju dengan 0x10000000000000000 " adalah sesuatu dari " baik, jangan anggap seperti itu tanggapan " dan saya tidak terlalu puas dengannya. Tentu, itu keren bahwa independence_score bisa ada, tetapi semua ini (dan masalah dengan aliran serupa), mungkin memperdebatkan fungsi keluaran default yang lebih kuat sehingga saya bahkan jika orang melakukan (jarang) hal-hal yang sama sekali patologis untuk yang mendasarinya LCG, tidak ada kerugian yang akan ditimbulkan. PCG akan segera berusia lima tahun pada saat ini, dan saya sedang mempertimbangkan versi bump and tweak musim panas ini, jadi masalah ini dapat masuk ke dalam daftar. Tentu saja, ini mungkin mengganggu kalian jika sama seperti Anda memasukkan PCG, saya membuat peningkatan versi utama dan memperbaikinya.)

Adakah pemikiran akhir tentang pendekatan hash untuk mendapatkan kenaikan untuk aliran PCG? Mengesampingkan apakah itu mekanisme utama untuk mendapatkan aliran independen. Singkatnya menghapus akses ke fitur itu sama sekali, sepertinya itu adalah sesuatu yang ingin kami lakukan untuk mencegah ID streaming berurutan yang mudah disalahgunakan.

Saya sarankan Anda memasukkannya melalui mixer Murmur3 . Tidak ada yang mungkin secara tidak sengaja membuat aliran serupa dengan itu tanpa usaha yang disengaja. (Edit: Saya kira Anda memerlukan versi 128-bit, tetapi Anda bisa mencampur bagian atas dan bawah. Saya juga akan menambahkan konstanta juga. Semua orang suka 0x9e3779b97f4a7c15f39cc0605cedc835 (bagian pecahan ϕ) tetapi 0xb7e151628aed2a6abf7158809cf4f3c7 (bagian pecahan dari e) juga bisa digunakan, atau _any_ angka yang tampak acak.)

Saya merekomendasikan wyhash (https://github.com/wangyi-fudan/wyhash) karena ini adalah yang tercepat dan paling sederhana yang melewati BigCrush dan PractRand. Kode c sesederhana

inline  uint64_t    wyrand(uint64_t *seed){    
    *seed+=0xa0761d6478bd642full;    
    __uint128_t t=(__uint128_t)(*seed^0xe7037ed1a0b428dbull)*(*seed);    
    return  (t>>64)^t;    
}

@ wangyi-fudan, saya tidak dapat meyakinkan diri sendiri bahwa ini adalah perhiasan.

Maaf atas pengetahuan saya yang terbatas: mengapa bijection diperlukan / disukai untuk PRNG?
akan dihargai untuk beberapa penjelasan :-) @imneme

@ wangyi-fudan, jika fungsi hash dari 64-bit ints ke 64-bit ints bukan bijection (yaitu, fungsi 1-ke-1) maka beberapa hasil dihasilkan lebih dari sekali dan beberapa tidak sama sekali. Itu semacam bias.

Aku mengerti apa yang kamu maksud. namun, untuk pembuat nomor acak 64-bit R, kita akan mengharapkan satu tabrakan setelah 1.2 * 2 ^ 32 nomor acak (http://mathworld.wolfram.com/BirthdayAttack.html). dengan 2 ^ 64 nomor acak, wajar jika banyak tabrakan. tabrakan bersifat alami sedangkan kebijaksanaan tidak acak secara alami. Jika saya mengetahui meja judi (misalnya PRNG 3 bit) ditentukan memiliki nilai 0 dalam 8 jalur, saya akan berani bertaruh besar pada nol setelah mengamati 5 bukan nol.

@ wangyi-fudan, Dalam konteks ini, kami berbicara tentang cara mengubah stream-id sehingga aliran seperti 1,2,3 menjadi sesuatu yang terlihat lebih acak (alias lebih normal). Tidak ada kebajikan dalam tabrakan dalam proses ini.

Untuk PRNG secara umum, Anda harus membaca tentang perbedaan antara PRNG berdasarkan pemetaan acak dan yang didasarkan pada pemetaan acak yang dapat dibalik (fungsi 1-ke-1). Saya telah menulis tentang itu, tetapi begitu juga yang lainnya. Jika ukurannya kecil, PRNG yang didasarkan pada pemetaan acak akan menunjukkan bias dan gagal lebih cepat daripada yang didasarkan pada teknik lain. Pada ukuran besar, segala jenis kekurangan mungkin lebih sulit dideteksi.

Kita dapat menghitung probabilitas jika kita meminta interval _n_ yang satu akan tumpang tindih dengan yang lain. Ini adalah probabilitas yang cukup mendasar - Saya tidak yakin Anda bisa menerbitkan makalah tentangnya karena (seperti yang saya pahami) tidak ada yang tertarik dengan makalah yang berisi matematika dasar.

Saya pikir Anda hanya perlu menjadi Pierre L'Ecuyer. ;-) halaman 15

Ya, ketika dia menjelaskan dasar-dasarnya, itu dianggap oke!

@rkern @imneme Kesederhanaan adalah sebuah fitur, baik dalam perangkat lunak maupun dalam matematika. Bahwa beberapa tidak terkesan oleh pekerjaan sederhana tidak boleh dianggap sebagai bukti yang kontradiktif.

@ lmire : Ada bagian humor yang saya suka yang menurut saya mengandung banyak kebenaran yang disebut _Cara Mengkritik Ilmuwan Komputer_ . Ide yang mendasari karya ini adalah bahwa para ahli teori menyukai kecanggihan dan eksperimentalis menyukai kesederhanaan. Jadi, jika audiens Anda adalah salah satu eksperimental, mereka akan senang dengan kesederhanaan, tetapi jika audiens Anda adalah salah satu ahli teori, tidak terlalu.

Default BitGenerator adalah PCG64 . Terima kasih atas kontribusi bijaksana Anda. Dan stamina!

Sangat terinspirasi oleh utas ini, saya memiliki beberapa berita untuk dilaporkan…

Latar Belakang

Dengan banyak ukuran pcg64 cukup bagus; misalnya, di bawah ukuran kualitas statistik yang biasa, ia mendapat tagihan kesehatan yang bersih. Ini telah diuji dengan berbagai cara; baru-baru ini saya telah menjalankannya hingga setengah petabyte dengan PractRand. Ini berfungsi dengan baik dalam kasus penggunaan normal.

TAPI, patologi yang muncul di utas ini tidak cocok dengan saya. Tentu, saya bisa mengatakan " baik, jangan anggap seperti itu ", tetapi inti dari tujuan umum PRNG adalah bahwa itu harus kuat. Saya ingin melakukan yang lebih baik ...

Jadi, sekitar 25 hari yang lalu saya mulai berpikir untuk merancang anggota baru keluarga PCG…

Tujuan

Tujuan saya adalah merancang anggota keluarga PCG baru yang bisa menjadi pengganti varian pcg64 . Dengan demikian:

  • Fungsi output harus mengacak bit lebih dari XSL RR (karena hal itu akan menghindari masalah yang muncul di utas ini).
  • Kinerja harus secepat (atau lebih cepat) dari pcg64 .
  • Desain harus PCG-ish (yaitu, jangan mudah diprediksi, dan dengan demikian tidak mengizinkan _ apa pun_ pekerjaan fungsi keluaran dengan mudah dibatalkan).

Seperti biasa, selalu ada kompromi saat kami berusaha mendapatkan kualitas terbaik secepat mungkin. Jika kita tidak peduli sama sekali tentang kecepatan, kita dapat memiliki lebih banyak langkah dalam fungsi keluaran untuk menghasilkan keluaran yang lebih teracak, tetapi inti dari PCG adalah bahwa LCG yang mendasarinya "hampir cukup baik" dan jadi kita tidak perlu untuk melakukan upaya sebanyak yang kami lakukan dengan sesuatu seperti penghitung yang bertambah 1.

Spoiler

Saya senang melaporkan kesuksesan! Sekitar 25 hari yang lalu ketika saya pertama kali memikirkan hal ini, saya sebenarnya sedang berlibur. Ketika saya kembali sekitar sepuluh hari yang lalu, saya mencoba ide-ide yang saya miliki dan senang menemukan bahwa ide-ide itu bekerja dengan baik. Waktu berikutnya sebagian besar dihabiskan untuk berbagai jenis pengujian. Kemarin sudah cukup puas bahwa saya mendorong kode ke versi C ++ dari PCG. Pengujian pada ukuran kecil menunjukkan bahwa itu jauh lebih baik daripada XSL RR, dan bersaing dengan RXS M, tetapi sebenarnya bersinar pada ukuran yang lebih besar. Itu memenuhi semua tujuan lainnya juga.

Detail

FWIW, fungsi keluaran baru adalah (untuk kasus keluaran 64-bit):

uint64_t output(__uint128_t internal)
{
    uint64_t hi = internal >> 64;
    uint64_t lo = internal;

    lo |= 1;
    hi ^= hi >> 32;
    hi *= 0xda942042e4dd58b5ULL;
    hi ^= hi >> 48;
    hi *= lo;
    return hi;
}

Fungsi keluaran ini terinspirasi oleh xorshift-multiply, yang banyak digunakan. Pilihan pengali adalah (a) untuk menekan jumlah konstanta ajaib, dan (b) untuk mencegah permutasi dibatalkan (jika Anda tidak memiliki akses ke bit orde rendah), dan juga menyediakan keseluruhan "acak- kualitas dengan sendirinya ”yang biasanya dimiliki oleh fungsi keluaran PCG.

Perubahan lainnya

Ini juga merupakan kasus bahwa 0xda942042e4dd58b5 adalah pengganda LCG untuk PRNG ini (dan semua generator PCG 128-bit-state cm_ diawali). Dibandingkan dengan 0x2360ed051fc65da44385df649fccf645 digunakan oleh pcg64 , konstanta ini sebenarnya masih cukup baik dalam hal properti uji spektral, tetapi lebih murah untuk dikalikan karena 128-bit × 64-bit lebih mudah daripada 128-bit × 128-bit. Saya telah menggunakan konstanta LCG ini selama beberapa tahun tanpa masalah. Saat menggunakan varian pengganda-murah, saya menjalankan fungsi keluaran pada keadaan pra-iterasi daripada status pasca-iterasi untuk paralelisme tingkat instruksi yang lebih besar.

Menguji

Saya telah mengujinya secara menyeluruh (PractRand dan TestU01) dan saya senang dengannya. Tes termasuk skenario yang diuraikan dalam utas ini (misalnya, mengambil generator geng baik pada uap berurutan atau maju dengan 2 ^ 64 dan menyisipkan output mereka - Saya menguji sekelompok empat dan sekelompok 8192 hingga 8 TB tanpa masalah, juga sebagai sungai dan lawan daratannya).

Kecepatan

Saya bisa panjang lebar tentang tes kecepatan dan benchmark. Ada berbagai macam faktor yang memengaruhi apakah satu PRNG berjalan lebih cepat daripada yang lain dalam tolok ukur tertentu, tetapi secara keseluruhan, varian ini tampaknya sering kali sedikit lebih cepat, terkadang jauh lebih cepat, dan terkadang sedikit lebih lambat. Faktor-faktor seperti compiler dan aplikasi memiliki pengaruh yang jauh lebih besar pada variabilitas benchmark.

Ketersediaan

Pengguna dengan header C ++ dapat mengakses anggota keluarga baru ini _now_ sebagai pcg_engines::cm_setseq_dxsm_128_64 ; di masa mendatang, saya akan mengalihkan pcg64 dari pcg_engines::setseq_xsl_rr_128_64 ke skema baru ini. Rencana saya saat ini adalah melakukannya musim panas ini sebagai bagian dari benjolan versi PCG 2.0.

Pengumuman Resmi

Secara keseluruhan, saya sangat senang dengan anggota keluarga baru ini dan pada suatu saat nanti di musim panas, akan ada postingan blog dengan detail lebih lanjut, kemungkinan merujuk pada utas ini.

Pilihan Anda ...

Tentu saja, Anda harus memikirkan apa yang harus dilakukan dengan ini. Terlepas dari apakah Anda akan menggunakannya atau tidak, saya sebenarnya akan sangat penasaran untuk melihat apakah itu lebih baik atau lebih buruk dalam tolok ukur kecepatan Anda.

@imneme Apakah itu menyiasati kebutuhan untuk memiliki pengganda 64-bit penuh yang cepat? (Yang super cepat pada x64 tetapi sedikit lebih lambat pada beberapa arsitektur yang lebih lemah.)

@lemire :

Ini masih berpotensi lebih baik dari 128-bit × 128-bit. Meskipun seberapa baik tergantung pada seberapa baik penjadwalan instruksi berjalan pada saat itu.

Anda benar bahwa pada ARM, hasil 64-bit × 64-bit → 128-bit sebenarnya adalah dua instruksi.

(Sangat mungkin, tentu saja, untuk menggabungkan dua LCG 64-bit dan mencampurnya. Ruang dari semua PRNG yang bisa ada dan akan bekerja dengan baik cukup besar.)

Penerapan cepat dan kotor dalam kerangka kerja kami menyarankan peningkatan kinerja ringan, setidaknya pada Linux 64-bit:

Time to produce 1,000,000 64-bit unsigned integers
************************************************************
MT19937      5.42 ms
PCG64        2.59 ms
PCG64DXSM    2.41 ms
Philox       4.37 ms
SFC64        2.07 ms
numpy        5.41 ms
dtype: object

64-bit unsigned integers per second
************************************************************
MT19937      184.39 million
PCG64        386.01 million
PCG64DXSM    415.02 million
Philox       228.88 million
SFC64        483.94 million
numpy        184.79 million
dtype: object

Saya pikir itu keluaran dari keadaan pra-iterasi yang memberikan tonjolan, setidaknya dalam konteks ini. Saya meninggalkannya pada awalnya dan pada dasarnya mendapatkan kinerja yang sama dengan PCG64 1.0. Kemenangan sebenarnya akan berada di bawah emulasi 128-bit, saya kira, tetapi saya tidak sempat menulisnya, dan saya tidak memiliki cara yang baik untuk mengujinya pada platform yang penting.

Saya kira pertanyaan sebenarnya untuk Anda, @imneme , adalah seberapa kesal Anda dengan nama numpy.random.PCG64 menerapkan algoritma 1.0? Rilis dalam waktu dekat dan sudah tertunda, jadi saya tidak _pikir_ kami akan mengubah algoritme saat ini. Jika kinerja pada platform 32-bit sangat bagus, maka saya pikir kami dapat menambahkan PCG64DXSM dalam rilis berikut, dan mungkin mempertimbangkan kembali default beberapa rilis berikutnya.

Itu adalah pilihanmu!

Saya tidak punya masalah dengan pengiriman Anda versi 1.0 dari PCG64. Banyak orang lain telah menggunakan varian itu.

Saya pikir varian DXSM memiliki keuntungan menghindari masalah penggunaan edge-case yang muncul di utas ini (lagipula, itulah alasan mengapa itu ada), tetapi di sisi lain, ia memiliki kelemahan yaitu terlambat untuk pesta. Bahkan mungkin tampak sangat sembrono untuk mengirimkan PRNG yang berusia kurang dari satu bulan kepada pengguna (meskipun itu didasarkan pada ide yang sama dengan varian PCG yang lebih teruji waktu).

(Meskipun demikian, jika itu adalah pilihan _my_, terlepas dari kemungkinan tuduhan kecerobohan, saya mungkin akan mengirimkan yang baru; Saya pikir penundaan untuk menjalankannya di Numpy cukup minimal. Dan risikonya sangat rendah - itu sudah benar-benar diuji dengan BigCrush, dan diuji dengan PractRand hingga 16 TB (termasuk cm_mcg_dxsm_64_32 yang merupakan seperempat ukuran [tanpa aliran, keluaran 32-bit]), dan kemungkinan akan mencapai 32 TB dalam waktu kurang dari seminggu .)

[Senang kinerjanya sedikit lebih baik. Lima tahun lalu, menggunakan status pra-iterasi adalah pesimisasi untuk ukuran 128-bit dengan pengganda 128-bit. Tapi saat itulah, pada mesin yang saya uji, dengan tolok ukur yang saya gunakan.]

Saya lebih bermaksud menggunakan nama PCG64 untuk varian 1.0 ketika Anda akan menggunakan nama itu untuk merujuk ke varian 2.0.

@rkern Jika ini hanya masalah penamaan, maka PCG64DXSM dan PCG64 membedakannya dengan baik, bukan?

Untuk numpy, tentunya. Saya hanya ingin tahu apakah @imneme lebih suka kita tidak menamai implementasi 1.0 kami PCG64 ketika dia akan mempromosikan varian 2.0 dengan nama itu di versi C ++. Saya peka terhadap fakta bahwa kehilangan nama berarti bahwa beberapa orang mungkin menguji PCG64 numpy dan membandingkannya dengan klaim yang akan dibuat di pcg-random.org tentang versi 2.0. Cf hanya tentang percakapan apa pun tentang PRNG Bob Jenkin.

Di Bagian 6.3 dari makalah PCG, dikatakan:

Perhatikan juga bahwa meskipun generator disajikan dengan nama mnemonik berdasarkan permutasi yang mereka lakukan, pengguna pustaka PCG sebaiknya jarang memilih anggota keluarga dengan mnemonik ini. Pustaka menyediakan generator bernama berdasarkan propertinya, bukan implementasi yang mendasarinya (misalnya, pcg32_unique untuk generator 32-bit tujuan umum dengan aliran unik). Dengan begitu, ketika anggota keluarga di masa depan yang kinerjanya lebih baik ditemukan dan ditambahkan (semoga karena penemuan orang lain), pengguna dapat beralih ke mereka secara mulus.

Dan pustaka C dan C ++ disusun seperti itu. Perpustakaan menyediakan

  • antarmuka tingkat rendah yang memungkinkan Anda memilih anggota keluarga tertentu melalui nama permutasinya, ukuran bit operasinya, dan karakteristik LCG yang mendasarinya
  • antarmuka tingkat tinggi yang menyediakan alias yang nyaman seperti pcg64 yang terhubung ke anggota keluarga tingkat rendah yang telah dipilih sebelumnya.

Dengan cara ini, alias dapat diperbarui untuk menunjuk ke anggota keluarga yang lebih baru, tetapi pengguna yang ingin mereproduksi hasil lama dengan tepat akan tetap dapat menggunakan antarmuka tingkat rendah untuk memilih anggota keluarga yang sebelumnya dapat dijangkau oleh high yang nyaman. -tingkat alias.

Jika Anda akan mengirimkan PRNG yang disebut PCG64 , saya akan mengatakan bahwa cukup untuk mengatakan dalam dokumentasi Anda varian PCG spesifik mana - dengan kata lain, katakanlah anggota keluarga mana yang sesuai di bawah -tingkat C atau antarmuka perpustakaan C ++.

Generator default diimplementasikan diimplementasikan sebagai np.random.default_gen() di https://github.com/numpy/numpy/pull/13840. ( @rkern untuk referensi di masa mendatang, mungkin bagus untuk memanggil PR secara eksplisit - mereka mudah terlewat di GitHub jika Anda hanya memberikan tautan balik, karena tidak ada pemberitahuan untuk itu.)

Satu hal kecil: bagaimana dengan menyebut np.random.default_generator() sebagai gantinya? gen terasa terlalu pendek / tidak jelas bagi saya. Saya ingin tahu apa yang dipikirkan orang lain.

bagaimana dengan memanggil np.random.default_generator () ini?

Saya memiliki pemikiran yang sama, tetapi kemudian, np.random.default_generator() adalah rambut yang panjang, jadi saya bermain dengan default_rng .

👍 Saya juga suka default_rng daripada default_gen . Saya akan senang dengan salah satu dari ini, meskipun saya masih condong ke default_generator .

: +1: untuk default_rng() .

Apakah halaman ini membantu?
0 / 5 - 0 peringkat

Masalah terkait

qualiaa picture qualiaa  ·  3Komentar

Levstyle picture Levstyle  ·  3Komentar

keithbriggs picture keithbriggs  ·  3Komentar

inducer picture inducer  ·  3Komentar

Kreol64 picture Kreol64  ·  3Komentar