Numpy: Implementasi PCG yang diberikan oleh Numpy memiliki korelasi diri yang signifikan dan berbahaya

Dibuat pada 20 Mei 2020  ·  104Komentar  ·  Sumber: numpy/numpy

Generator PCG yang digunakan oleh Numpy memiliki korelasi diri yang signifikan. Artinya, untuk setiap urutan yang dihasilkan dari sebuah benih ada sejumlah besar urutan yang berkorelasi dan tidak tumpang tindih mulai dari benih lain. Yang saya maksud dengan "berkorelasi" adalah bahwa menyisipkan dua urutan tersebut dan menguji hasil Anda mendapatkan kegagalan yang tidak muncul di setiap urutan secara individual.

Probabilitas bahwa dua generator dari kumpulan terminal yang besar mendapatkan dua dari urutan tersebut tidak dapat diabaikan. Mengapa ini terjadi dari sudut pandang matematika sudah diketahui tetapi dijelaskan di sini secara rinci: http://prng.di.unimi.it/pcg.pgp (lihat "Urutan dalam generator yang sama").

Untuk menunjukkan masalah ini secara langsung, saya menulis program C sederhana ini menggunakan kembali kode Numpy: http://prng.di.unimi.it/intpcgnumpy.c . Program ini mengambil dua status 128-bit dari dua generator (dengan konstanta LCG atau "aliran" yang sama) dalam bentuk bit tinggi dan rendah, menyisipkan keluarannya dan menuliskannya dalam bentuk biner. Setelah kami mengirimkannya melalui PractRand, kami seharusnya tidak melihat adanya kegagalan statistik, karena kedua aliran harus independen. Tetapi jika mencoba memulai dari dua status dengan 64 bit yang lebih rendah yang sama, Anda mendapatkan:

./intpcgnumpy 0x596d84dfefec2fc7 0x6b79f81ab9f3e37b 0x8d7deae980a64ab0 0x6b79f81ab9f3e37b | stdbuf -oL ~ / svn / c / xorshift / praktrand / RNG_test stdin -tf 2 -te 1 -tlmaxonly -multithreaded
RNG_test menggunakan PractRand versi 0.94
RNG = RNG_stdin, seed = tidak diketahui
set tes = diperluas, lipat = ekstra

rng=RNG_stdin, seed=unknown
length= 128 megabytes (2^27 bytes), time= 2.2 seconds
  Test Name                         Raw       Processed     Evaluation
  BCFN(0+0,13-2,T)                  R= +27.6  p =  1.0e-13    FAIL
  BCFN(0+1,13-2,T)                  R= +68.0  p =  2.3e-34    FAIL !!!
  BCFN(0+2,13-3,T)                  R= +90.8  p =  8.8e-43    FAIL !!!
  BCFN(0+3,13-3,T)                  R=+120.6  p =  6.9e-57    FAIL !!!!
  DC6-6x2Bytes-1                    R=  +8.9  p =  4.0e-5   mildly suspicious
  DC6-5x4Bytes-1                    R= +15.7  p =  4.3e-9   very suspicious
  [Low1/8]BCFN(0+0,13-4,T)          R= +11.6  p =  4.9e-5   unusual
  ...and 1074 test result(s) without anomalies

Anda bahkan dapat menurunkannya — Anda hanya perlu 58 bit lebih rendah yang sama:

./intpcgnumpy 0x596d84dfefec2fc7 0x0579f81ab9f3e37b 0x8d7deae980a64ab0 0x6b79f81ab9f3e37b | stdbuf -oL ~/svn/c/xorshift/practrand/RNG_test stdin -tf 2 -te 1 -tlmaxonly -multithreaded

[...]
rng=RNG_stdin, seed=unknown
length= 32 gigabytes (2^35 bytes), time= 453 seconds
  Test Name                         Raw       Processed     Evaluation
  [Low1/16]FPF-14+6/32:cross        R= +11.6  p =  4.0e-10   VERY SUSPICIOUS
  [Low1/32]FPF-14+6/32:cross        R= +16.5  p =  3.2e-14    FAIL
  [Low1/32]FPF-14+6/16:cross        R= +12.8  p =  3.8e-11   VERY SUSPICIOUS
  [Low1/64]FPF-14+6/64:cross        R=  +6.8  p =  4.8e-6   mildly suspicious
  [Low1/64]FPF-14+6/32:cross        R=  +6.0  p =  1.9e-5   unusual
  [Low1/64]FPF-14+6/16:cross        R=  +5.5  p =  5.8e-5   unusual
  [Low4/32]FPF-14+6/64:all          R=  +5.8  p =  5.9e-5   unusual
  [Low4/32]FPF-14+6/32:(0,14-0)     R=  +7.7  p =  1.0e-6   unusual
  [Low4/32]FPF-14+6/32:(1,14-0)     R=  +7.7  p =  9.1e-7   unusual
  [Low4/32]FPF-14+6/32:all          R=  +6.5  p =  1.3e-5   unusual
  [Low4/64]FPF-14+6/64:all          R=  +5.9  p =  5.1e-5   unusual
  [Low4/64]FPF-14+6/64:cross        R=  +8.2  p =  3.0e-7   suspicious
  [Low4/64]FPF-14+6/32:(0,14-0)     R=  +7.6  p =  1.0e-6   unusual
  [Low8/64]FPF-14+6/64:(0,14-0)     R= +17.0  p =  2.2e-15    FAIL
  [Low8/64]FPF-14+6/64:(1,14-0)     R=  +9.1  p =  5.1e-8   mildly suspicious
  [Low8/64]FPF-14+6/64:all          R= +12.7  p =  2.1e-11   VERY SUSPICIOUS
  [Low8/64]FPF-14+6/32:(0,14-0)     R= +12.8  p =  1.7e-11   VERY SUSPICIOUS
  [Low8/64]FPF-14+6/32:all          R= +11.0  p =  9.3e-10   VERY SUSPICIOUS
  ...and 1696 test result(s) without anomalies

Perhatikan bahwa untuk mendapatkan lebih banyak kemungkinan 50% bahwa dua generator memulai dari dua benih yang berkorelasi (dipilih secara acak) Anda memerlukan sekitar setengah juta generator yang dimulai secara acak (paradoks ulang tahun). Dan jika Anda mempertimbangkan kemungkinan bahwa mereka tidak benar-benar mulai dari keadaan yang sama, tetapi memiliki urutan berkorelasi yang tumpang tindih secara signifikan, Anda memerlukan lebih sedikit.

Generator yang masuk akal dari literatur tidak akan berperilaku seperti itu. Anda dapat memilih dua status awal MRG32k3a, SFC64, CMWC, xoshiro256 ++, dll., Dan selama Anda membuat urutan yang tidak tumpang tindih, Anda tidak akan melihat kegagalan di atas. Ini adalah kelemahan utama yang dapat muncul ketika sejumlah perangkat menggunakan generator dan seseorang berasumsi (sebagaimana mestinya) bahwa pasangan urutan tersebut seharusnya tidak menunjukkan korelasi. Korelasi dapat menyebabkan perilaku yang tidak diinginkan yang sulit dideteksi.

Harap setidaknya dokumentasikan di suatu tempat bahwa generator tidak boleh digunakan di banyak terminal atau di lingkungan yang sangat paralel.

Hal yang sama dapat terjadi dengan "aliran" yang berbeda, karena urutan yang dihasilkan oleh LCG dengan mengubah konstanta aditif semuanya merupakan modul yang sama, yaitu perubahan tanda dan konstanta aditif. Anda dapat melihat beberapa diskusi di sini: https://github.com/rust-random/rand/issues/907 dan diskusi matematis lengkap tentang masalahnya di sini: https://arxiv.org/abs/2001.05304 .

numpy.random

Semua 104 komentar

@imneme , @bashtage , @rkern akan menjadi otoritas di sini, tapi saya pikir kami telah membahas ini dan itulah mengapa kami lebih suka antarmuka SeedSequence.spawn daripada jumped satu. Misalnya ada diskusi ini saat kita membahas API. Silakan periksa saran di sini https://numpy.org/devdocs/reference/random/parallel.html dan sarankan perbaikan sesuai kebutuhan.

@ Mattip Ini tidak ada hubungannya dengan lompat.

Saya rasa dalam praktiknya sulit untuk membuat perubahan besar-besaran, meskipun dokumentasi yang lebih baik selalu merupakan ide yang bagus.

Saya mungkin akan merekomendasikan AESCounter untuk siapa pun dengan AES-NI atau SPECK128 untuk siapa pun yang tidak memiliki pengaturan yang sangat paralel.

Hal yang sama dapat terjadi dengan "aliran" yang berbeda, karena urutan yang dihasilkan oleh LCG dengan mengubah konstanta aditif semuanya merupakan modul yang sama, yaitu perubahan tanda dan konstanta aditif.

Bisakah Anda mengukur ini? Saya dapat mereplikasi kegagalan menggunakan kenaikan yang sama, tetapi kami menyemai kenaikan serta status, dan saya belum mengamati kegagalan dengan dua kenaikan acak yang berbeda. Jika kenaikan juga harus dibangun dengan hati-hati, maka itu akan mempengaruhi frekuensi tabrakan ulang tahun praktis.

https://gist.github.com/rkern/f46552e030e59b5f1ebbd3b3ec045759

❯ ./pcg64_correlations.py --same-increment | stdbuf -oL ./RNG_test stdin64 -tf 2 -te 1 -tlmaxonly -multithreaded
0x56b35656ede2b560587e4251568a8fed
0x93526034ed105e9e587e4251568a8fed
[
    {
        "bit_generator": "PCG64",
        "state": {
            "state": 115244779949650410574112983538102603757,
            "inc": 137507567477557873606783385380908979143
        },
        "has_uint32": 0,
        "uinteger": 0
    },
    {
        "bit_generator": "PCG64",
        "state": {
            "state": 195824235027336627448689568147458133997,
            "inc": 137507567477557873606783385380908979143
        },
        "has_uint32": 0,
        "uinteger": 0
    }
]
RNG_test using PractRand version 0.93
RNG = RNG_stdin64, seed = 0x4bf19f7b
test set = expanded, folding = extra

rng=RNG_stdin64, seed=0x4bf19f7b
length= 128 megabytes (2^27 bytes), time= 3.0 seconds
  Test Name                         Raw       Processed     Evaluation
  BCFN_FF(2+0,13-3,T)               R= +59.9  p =  3.8e-28    FAIL !!!       
  BCFN_FF(2+1):freq                 R= +89.0  p~=   6e-18     FAIL !         
  BCFN_FF(2+2):freq                 R= +39.6  p~=   6e-18     FAIL !         
  BCFN_FF(2+3):freq                 R= +14.6  p~=   6e-18     FAIL !         
  BCFN_FF(2+4):freq                 R= +10.3  p~=   5e-11   very suspicious  
  DC6-9x1Bytes-1                    R=  +7.1  p =  5.6e-4   unusual          
  DC6-6x2Bytes-1                    R= +18.9  p =  1.0e-10   VERY SUSPICIOUS 
  DC6-5x4Bytes-1                    R= +11.2  p =  1.4e-6   suspicious       
  [Low4/16]BCFN_FF(2+0):freq        R= +19.5  p~=   6e-18     FAIL !         
  [Low4/16]FPF-14+6/16:all          R=  +5.6  p =  1.0e-4   unusual          
  [Low4/16]FPF-14+6/4:all           R=  +5.9  p =  4.6e-5   unusual          
  [Low4/32]BCFN_FF(2+0):freq        R=  +6.5  p~=   2e-5    unusual          
  [Low8/32]BCFN_FF(2+0):freq        R= +15.1  p~=   6e-18     FAIL !         
  [Low8/32]FPF-14+6/32:all          R=  +8.4  p =  2.5e-7   very suspicious  
  [Low8/32]FPF-14+6/32:all2         R=  +9.0  p =  7.8e-5   unusual          
  [Low8/32]FPF-14+6/16:(0,14-0)     R= +12.4  p =  4.5e-11   VERY SUSPICIOUS 
  [Low8/32]FPF-14+6/16:all          R= +15.5  p =  5.2e-14    FAIL           
  [Low8/32]FPF-14+6/16:all2         R= +41.4  p =  2.6e-16    FAIL !         
  [Low8/32]FPF-14+6/4:(0,14-0)      R=  +6.9  p =  5.9e-6   unusual          
  [Low8/32]FPF-14+6/4:all           R=  +7.9  p =  6.6e-7   suspicious       
  ...and 871 test result(s) without anomalies

Oke, saya akan coba lagi.

Tidak ada beberapa aliran dalam LCG dengan modulus power-of-2. Banyak yang mempercayainya pada masa-masa awal, dan bahkan ada makalah lama yang mengklaim melakukan hal-hal menarik dengan "aliran" tersebut, tetapi telah diketahui selama beberapa dekade bahwa orbit yang Anda peroleh dengan mengubah konstanta adalah semua modulo yang sama dan aditif konstan dan mungkin tanda change_. Terjauh yang bisa saya lacak

Mark J. Durst, Menggunakan generator kongruensial linier untuk pembuatan bilangan acak paralel,
Prosiding Konferensi Simulasi Musim Dingin 1989, IEEE Press, 1989, hlm. 462–466.

Jadi, saya menulis program lain http://prng.di.unimi.it/corrpcgnumpy.c di mana Anda dapat mengatur:

  • Keadaan awal untuk PRNG.
  • Status awal untuk PRNG lain.
  • "Konstanta aliran" sewenang-wenang untuk PRNG pertama.
  • "Konstanta aliran" arbitrer untuk PRNG kedua (keduanya harus genap atau keduanya ganjil; pembatasan ini dapat dihilangkan dengan beberapa biola tambahan).
  • Sejumlah tetap bit bawah yang akan kami tetapkan secara berlawanan dalam PRNG kedua, pada dasarnya sedemikian rupa sehingga dimulai dengan bit yang sama dari PRNG pertama. Bit lainnya akan diambil dari status awal untuk PRNG kedua yang telah Anda berikan.

Jadi ini _exactly_ pengaturan dari program pertama, tetapi Anda juga dapat memilih konstanta.

./corrpcgnumpy 0x596d84dfefec2fc7 0x6b79f81ab9f3e37b 0xac9c8abfcb89f65f 0xe42e8dff1c46de8b 0x8d7deae9efec2fc7 0x6b79f81ab9f3e37b 0x06e13e5e8c92c843 0xf92e8346feee7a21 56 | stdbuf -oL ~/svn/c/xorshift/practrand/RNG_test stdin -tf 2 -te 1 -tlmaxonly -multithreaded

rng=RNG_stdin, seed=unknown
length= 4 gigabytes (2^32 bytes), time= 113 seconds
  Test Name                         Raw       Processed     Evaluation
  [Low1/8]BCFN(0+0,13-1,T)          R= +27.2  p =  4.0e-14    FAIL
  [Low1/8]DC6-6x2Bytes-1            R= +10.9  p =  4.4e-6   suspicious
  [Low1/64]DC6-5x4Bytes-1           R=  -6.4  p =1-1.4e-4   unusual
  [Low8/64]FPF-14+6/64:(0,14-0)     R=  +8.4  p =  2.2e-7   mildly suspicious
  [Low8/64]FPF-14+6/64:all          R=  +8.7  p =  1.2e-7   suspicious
  [Low8/64]FPF-14+6/32:(0,14-0)     R= +10.2  p =  5.1e-9   suspicious
  [Low8/64]FPF-14+6/32:all          R=  +9.4  p =  2.7e-8   very suspicious
  [Low8/64]FPF-14+6/16:all          R=  +5.8  p =  6.4e-5   unusual
  ...and 1439 test result(s) without anomalies

Jadi ada _ setidaknya_ 2 ^ 72 korespondensi yang berkorelasi, tidak peduli bagaimana Anda memilih "konstanta aliran", persis seperti dalam kasus konstanta yang sama.

Dan kami diberi sejumlah kelonggaran yang konyol untuk generator: bahkan jika alih-alih titik awal yang tepat saya menghitung Anda akan menggunakan keadaan sedikit sebelum atau sesudah, korelasi akan tetap muncul. Anda dapat dengan mudah memodifikasi program dengan parameter tambahan untuk melakukannya.

Saya ulangi, sekali lagi: tidak ada generator modern dari literatur ilmiah yang memiliki perilaku buruk ini (tentu saja, LCG power-of-2 memiliki perilaku ini, tetapi, demi Tuhan, itu _bukan_ generator modern).

Kritik Sabastiano terhadap PCG dibahas dalam posting blog ini dari tahun 2018.

Versi singkatnya adalah jika Anda diizinkan untuk membuat benih tertentu, Anda dapat menunjukkan perilaku "buruk" dari hampir semua PRNG. Terlepas dari klaimnya bahwa PCG entah bagaimana unik, sebenarnya PCG cukup konvensional - aliran PCG tidak lebih buruk daripada, katakanlah, SplitMix, yang merupakan PRNG lain yang banyak digunakan.

Itu sepenuhnya salah. Untuk membuktikan bahwa saya salah, tunjukkan dua urutan non-overlap yang berkorelasi dari MRG32k3a atau xoshiro256 ++.

Saya tidak pernah mengatakan tidak tumpang tindih. Tunjukkan saya tes yang saat ini tersedia untuk xoshiro256 ++. agar dua biji tidak saling tumpang tindih.

Sebaliknya, saya memiliki tes untuk PCG yang menunjukkan bahwa "korelasi" yang Anda tunjukkan pada dasarnya adalah bentuk tumpang tindih.

Saya tidak bisa melawan FUD seperti "pada dasarnya" dan "bentuk", tetapi saya memodifikasi http://prng.di.unimi.it/intpcgnumpy.c sehingga awalnya mengulang setiap PRNG 10 miliar kali, dan keluar dengan kesalahan pesan jika urutan yang dihasilkan melintasi status awal PRNG lainnya. Ini menjamin bahwa 160 GB data pertama ke dalam Practrand berasal dari urutan yang tidak tumpang tindih:

./intpcgnumpy 0x596d84dfefec2fc7 0x0579f81ab9f3e37b 0x8d7deae980a64ab0 0x6c79f81ab9f3e37b | stdbuf -oL ~/svn/c/xorshift/practrand/RNG_test stdin -tf 2 -te 1 -tlmaxonly -multithreaded
[...]
rng=RNG_stdin, seed=unknown
length= 64 gigabytes (2^36 bytes), time= 926 seconds
  Test Name                         Raw       Processed     Evaluation
  [Low1/8]FPF-14+6/64:(0,14-0)      R=  +8.8  p =  8.7e-8   mildly suspicious
  [Low1/8]FPF-14+6/64:all           R=  +6.3  p =  2.1e-5   unusual          
  [Low1/16]FPF-14+6/64:(0,14-0)     R=  +7.6  p =  1.1e-6   unusual          
  [Low1/16]FPF-14+6/64:(1,14-0)     R=  +8.3  p =  2.9e-7   mildly suspicious
  [Low1/16]FPF-14+6/64:all          R=  +8.0  p =  5.8e-7   suspicious       
  [Low1/16]FPF-14+6/32:all          R=  +7.1  p =  3.9e-6   mildly suspicious
  [Low1/64]FPF-14+6/32:cross        R=  +7.1  p =  2.6e-6   mildly suspicious
  [Low4/32]FPF-14+6/64:(0,14-0)     R= +13.5  p =  4.3e-12   VERY SUSPICIOUS 
  [Low4/32]FPF-14+6/64:all          R=  +9.0  p =  5.9e-8   very suspicious  
  [Low4/64]FPF-14+6/64:(0,14-0)     R= +11.4  p =  3.8e-10  very suspicious  
  [Low4/64]FPF-14+6/64:all          R=  +8.0  p =  5.3e-7   suspicious       
  [Low4/64]FPF-14+6/32:(0,14-0)     R= +10.3  p =  3.6e-9   suspicious       
  [Low4/64]FPF-14+6/32:all          R=  +6.1  p =  3.2e-5   unusual          
  [Low8/64]FPF-14+6/64:(0,14-0)     R= +18.6  p =  8.4e-17    FAIL           
  [Low8/64]FPF-14+6/64:(1,14-0)     R= +11.4  p =  3.9e-10  very suspicious  
  [Low8/64]FPF-14+6/64:(2,14-0)     R=  +8.3  p =  2.8e-7   mildly suspicious
  [Low8/64]FPF-14+6/64:all          R= +15.3  p =  6.9e-14    FAIL           
  [Low8/64]FPF-14+6/32:(0,14-0)     R=  +7.8  p =  7.1e-7   unusual          
  [Low8/64]FPF-14+6/32:(1,14-0)     R=  +7.2  p =  2.7e-6   unusual          
  [Low8/64]FPF-14+6/32:all          R=  +5.8  p =  6.9e-5   unusual          
  ...and 1786 test result(s) without anomalies

Data inisialisasi khusus ini hanya memiliki 56 bit tetap yang lebih rendah, sehingga seseorang dapat menghasilkan 2 ^ 72 urutan berkorelasi dengan membalik bit yang lebih tinggi. Kegagalan statistik terjadi setelah hanya 64 GB data, yang menunjukkan bahwa tumpang tindih tidak bertanggung jawab atas korelasi tersebut. Ada kemungkinan bahwa dengan pilihan target spesifik lainnya tumpang tindih terjadi sebelum 64GB, tentu saja — ini adalah contoh spesifik. Tetapi sekarang mudah untuk memeriksa bahwa tumpang tindih bukanlah masalahnya — generator hanya memiliki banyak korelasi internal yang tidak diinginkan.

Harap hormati kode etik . Usahakan agar komentar Anda senada dengan arahan untuk menjadi "empati, ramah, bersahabat, dan sabar" dan "hati-hati dengan kata-kata yang kita pilih. Kita berhati-hati dan hormat dalam komunikasi kita".

Saya tidak pernah mengatakan tidak tumpang tindih. Tunjukkan saya tes yang saat ini tersedia untuk xoshiro256 ++. agar dua biji tidak saling tumpang tindih.

Yah, ini sepele: putuskan panjang aliran, ulangi, dan periksa apakah kedua aliran tidak melewati keadaan awal. Ini adalah kode yang sama yang saya gunakan untuk menunjukkan aliran PCG yang berkorelasi dalam program http://prng.di.unimi.it/intpcgnumpy.c tidak tumpang tindih.

Terlepas dari klaimnya bahwa PCG entah bagaimana unik, sebenarnya PCG cukup konvensional - aliran PCG tidak lebih buruk daripada, katakanlah, SplitMix, yang merupakan PRNG lain yang banyak digunakan.

IMHO, korelasi diri dalam PCG jauh lebih buruk. Tidak ada hasil untuk generator aditif yang mendasari instans SplitMix yang serupa dengan hasil dramatis Durst tahun 1989 tentang LCG.

Tetapi masalah yang sangat ringan dari SplitMix telah diketahui, dan JEP 356 akan menyediakan kelas baru dari generator yang dapat dipisahkan, LXM, mencoba untuk mengatasi masalah tersebut. Ini akan menjadi waktu untuk pindah dan mengganti PCG, juga, dengan sesuatu yang tidak terlalu cacat.

Masalah mendasar diketahui untuk kedua generator, dan itu karena kurangnya campuran negara. Jika Anda mengubah bit _k_ dari status salah satu generator tersebut, perubahan tidak akan pernah menyebar di bawah bit _k_. Ini tidak terjadi pada LCG dengan modulus prima, pada generator F₂-linear, generator CMWC, dll. Semua generator lainnya mencoba mencampur statusnya secepat dan sebanyak mungkin.

Menyamakan masalah PCG dan SplitMix adalah hal yang salah. SplitMix memiliki generator dasar yang sangat sederhana, hanya aditif, tetapi di atas itu ada fungsi pengacakan yang sangat kuat: ini adalah finalizer 64-bit Appleby dari fungsi hash MurmurHash3, yang telah banyak digunakan dalam sejumlah konteks dan telah ditingkatkan oleh Stafford (http://zimbry.blogspot.com/2011/09/better-bit-mixing-improving-on.html). Konstanta fungsi telah dilatih untuk memiliki sifat longsoran terukur yang spesifik. Bahkan perubahan dalam sejumlah kecil bit cenderung menyebar ke semua keluaran. Dengan kata lain, SplitMix berdiri di atas bahu para raksasa.

Sebaliknya, generator PCG yang mendasari LCG memiliki masalah kurangnya pencampuran yang sama, tetapi fungsi pengacakan hanyalah urutan sederhana dari operasi aritmatika dan logis yang dirakit oleh penulis tanpa jaminan teoritis atau statistik. Jika mereka telah dirancang dengan memperhatikan fakta bahwa semua urutan LCG yang mendasarinya adalah modulo yang sama, sebuah konstanta aditif dan mungkin sebuah perubahan tanda, itu mungkin untuk mengatasi masalah tersebut.

Tetapi penulis tidak tahu bahwa urutan itu dapat dengan mudah diturunkan satu sama lain. Ini dapat dengan mudah dilihat dari pernyataan ini di Bagian 4.2.3 dari laporan teknis PCG (https://www.pcg-random.org/pdf/hmc-cs-2014-0905.pdf):

"Setiap pilihan _c_ menghasilkan urutan angka berbeda yang tidak memiliki pasangan keluaran berurutan yang sama dengan urutan lain."

Ini diambil sebagai bukti bahwa urutannya berbeda, yaitu LCG yang mendasarinya menyediakan banyak aliran. Hasil negatif Durst 1989 tentang topik ini tidak muncul di manapun di koran. Seperti yang saya katakan sebelumnya, dengan hasil tersebut semua urutan tersebut adalah sama, modulo konstanta aditif dan mungkin perubahan tanda (untuk LCG dengan modulus power-of-2 potensi maksimum, seperti yang terjadi di PCG).

Saya yakin tidak mengutip hasil Durst adalah kesalahan _bona fide_, tetapi masalahnya adalah begitu Anda yakin bahwa LCG yang mendasari yang Anda gunakan menyediakan "aliran" yang "berbeda" dalam arti tertentu, padahal tidak, Anda akhirnya dengan generator seperti PCG di mana untuk setiap urutan ada 2 ^ 72 urutan yang tidak tumpang tindih dan berkorelasi, bahkan jika Anda mengubah "aliran".

Terima kasih atas masukan Anda. Untuk saat ini, saya tidak tertarik dengan penilaian biner seperti "PCG itu baik / buruk". Silakan gunakan forum Anda sendiri untuk diskusi semacam itu. Apa yang menjadi topik di sini adalah apa yang akan dilakukan numpy, dan penilaian terakhir itu milik pengembang numpy. Kami sangat menghargai keahlian yang Anda semua bawa dalam diskusi ini, tetapi saya ingin memfokuskannya pada fakta yang mendasari daripada penilaian akhir. Saya sangat menghargai pernyataan kuantitatif yang memberi saya gambaran tentang jumlah ruang kepala yang kita miliki. Jika penilaian saya sebelumnya salah, itu karena saya melompat ke penilaian terlalu cepat, jadi saya sangat menghargai bantuan Anda untuk menghindarinya lagi. Terima kasih.

Perhatikan bahwa untuk mendapatkan lebih banyak kemungkinan 50% bahwa dua generator memulai dari dua benih yang berkorelasi (dipilih secara acak) Anda memerlukan sekitar setengah juta generator yang dimulai secara acak (paradoks ulang tahun).

@vigna Bisakah Anda memandu saya melalui perhitungan ini? Perhitungan tabrakan ulang tahun yang saya kenal memberikan peluang 50% dari tabrakan n -bit pada 2**(n/2) item (berikan atau ambil faktor 2). Setengah juta adalah 2**19 , jadi Anda sepertinya mengklaim bahwa korelasi berbahaya dimulai pada sekitar tabrakan 40-bit di bagian bawah, tetapi saya belum melihat bukti bahwa ini secara praktis dapat diamati. Saya telah menguji pasangan yang berbagi 40 bit lebih rendah dan mendapatkan 16 TiB di PractRand sebelum membatalkan pengujian. Jika Anda telah mengamati kegagalan dengan tabrakan 40-bit, berapa banyak TiB yang harus Anda uji untuk melihatnya?

Saya yakin bahwa mengubah kenaikan tidak mempengaruhi kemungkinan tabrakan. Diskusi lebih lanjut tentang manfaat "aliran PCG" di luar topik. Menggunakan diskusi itu sebagai alasan untuk berulang kali menekankan "penulis" sangat tidak diinginkan dan menginjak kode etik kita . Bertahan berarti kami harus melanjutkan tanpa masukan Anda. Terima kasih.

@imneme Tampaknya ini terkait dengan masalah dengan melompat dengan kelipatan dari kekuatan besar 2. Ketika saya membuat sepasang instance PCG64 dengan kenaikan yang sama dan berbagi n bit, jarak yang saya hitung antara keduanya adalah kelipatan 1 << n . Tampaknya fungsi output DXSM Anda yang PCG64DXSM yang berbagi kenaikan dan status 64-bit yang lebih rendah ke 2 TiB tanpa masalah.

Oke, ini memalukan: itu setengah _billion_, bukan setengah _million_. Satu huruf bisa membuat perbedaan besar. Saya minta maaf atas kesalahannya.

Tapi, seperti yang saya katakan di awal, ini adalah probabilitas untuk mencapai keadaan awal yang persis sama, bukan probabilitas tumpang tindih yang signifikan dari selanjutnya yang berkorelasi. Secara pribadi saya lebih suka menggunakan PRNG tanpa urutan yang berkorelasi, karena jumlahnya banyak, tetapi, seperti yang Anda katakan dengan benar, keputusan ada di tangan Anda.

Memperbaiki fungsi pengacakan sehingga memiliki sifat pencampuran yang lebih baik terdengar seperti solusi yang masuk akal.

Posting saya hanya dimaksudkan untuk menjadi klarifikasi tentang perbedaan struktural antara PCG dan SplitMix, karena posting sebelumnya mengklaim mereka memiliki masalah yang sama, dan saya rasa itu bukan pernyataan yang benar. Anda tidak dapat menulis program seperti http://prng.di.unimi.it/corrpcgnumpy.c untuk SplitMix.

@rkern , Anda bertanya:

@imneme Tampaknya ini terkait dengan masalah dengan melompat dengan kelipatan dari kekuatan besar 2. Ketika saya membuat sepasang instance PCG64 dengan kenaikan yang sama dan berbagi n bit, jarak yang saya hitung antara keduanya adalah kelipatan 1 << n . Tampaknya fungsi output DXSM Anda yang PCG64DXSM yang berbagi kenaikan dan status 64-bit yang lebih rendah ke 2 TiB tanpa masalah.

Terima kasih telah menemukan dan menautkan kembali ke utas diskusi tahun lalu. Ya, seperti yang dicatat Sebastiano dalam jawabannya,

Memperbaiki fungsi pengacakan sehingga memiliki sifat pencampuran yang lebih baik terdengar seperti solusi yang masuk akal.

XSL-RR berada di ujung yang lebih lemah. Sebaliknya, fungsi keluaran RXS-M asli dari kertas PCG, dan fungsi keluaran DXSM yang baru berfungsi lebih banyak dalam mengacak, jadi tidak menampilkan masalah seperti ini. DXSM (ditambahkan ke sumber PCG dalam komitmen ini tahun lalu) secara khusus dirancang agar lebih kuat dari XSL-RR tetapi memiliki kinerja waktu yang sama (cf, RXS-M, yang lebih lambat). Saya menguji DXSM cukup keras tahun lalu, tetapi 67 hari setelah dijalankan kami mengalami pemadaman listrik yang lama yang menurunkan server (baterai UPS terkuras) dan mengakhiri uji coba, tetapi pada saat itu telah terbukti cukup baik di kedua normal. pengujian (128 TB keluaran yang diuji) dan lompatan 2 ^ 48 (64 TB keluaran yang diuji, karena itu berjalan lebih lambat).

Jika, bahkan tanpa mendesain DXSM, RXS-M akan mengatasi masalah ini, satu pertanyaan adalah mengapa saya pernah menggunakan permutasi XSL-RR yang lebih lemah - mengapa tidak selalu menggunakan bit-scrambling yang sangat kuat dalam fungsi output? Jawabannya adalah pada dasarnya hal itu bermuara pada siklus. Kecepatan penting bagi orang-orang, jadi Anda mencoba untuk menghindari melakukan lebih banyak pengacakan daripada yang Anda perlukan.

Ini adalah masalah yang diketahui Sebastiano, karena pendekatannya dan pendekatan saya memiliki banyak kesamaan. Kita masing-masing mengambil pendekatan lama yang akan gagal dalam uji statistik modern (LCG dalam kasus saya, dan LFSR XorShift Marsaglia dalam kasusnya) dan menambahkan fungsi keluaran berebut untuk menebusnya. Kami berdua berusaha untuk membuat fungsi keluaran itu murah, dan kami berdua telah sedikit terperangkap di mana kekurangan pada generator yang mendasari yang kami coba tutupi dengan fungsi keluaran kami tetap terlihat. Dalam kasusnya, itu masalah linieritas yang telah ditunjukkan .

Tetapi dalam karya yang agak baru-baru ini yang sangat menyenangkan saya, dia juga menunjukkan berapa banyak desain berbasis LFSR yang memiliki masalah bobot-hamming (mencerminkan perhatian lama saya sendiri) yang tidak cukup tertutup oleh fungsi outputnya. Generatornya sendiri lulus ujian, jadi itu sesuatu, tetapi pada tahun 2018 ketika saya melihat xoshiro PRNG barunya , menurut saya masalah hamming-weight dari generator bawahan berhasil melewati fungsi outputnya. Dia sejak merevisi xoshiro dengan fungsi keluaran baru, dan saya harap itu berhasil (dia membuat beberapa perubahan lain juga, jadi mungkin itu juga memperbaiki masalah pengulangan, disorot oleh program pengujian ini ?).

Mengenai program korelasinya, pada tahun 2018 ketika dia memberikan kritik terhadap PCG di situsnya yang menyertakan program yang dia tulis dengan berbagai masalah (seperti penyemaian yang dibuat-buat, dll.), Saya menulis tanggapan yang berisi banyak program serupa untuk PRNG lama lainnya, termasuk corrsplitmix2.c yang membuat streaming terkait di SplitMix. Saya tidak begitu yakin apa yang dimaksud Sebastian ketika dia mengatakan itu tidak dapat dilakukan, tetapi saya akui saya belum memiliki kesempatan untuk melihat lebih dekat program pengujiannya untuk melihat apakah yang baru secara substansial berbeda dari yang dia tulis beberapa tahun lalu.

Mohon maafkan kurangnya pemahaman saya - tetapi bisakah saya meminta seseorang untuk membuat kesimpulan ringkasan pada tahap ini? Apakah ada keadaan realistis di mana PCG default tidak aman? Apa argumen untuk mengganti default?

Jalan yang mudah adalah dengan menambahkan beberapa dokumentasi tentang aplikasi-aplikasi berdimensi tinggi (ultra-high?) ​​Dan probabilitas urutan-urutan yang berkorelasi.

Jalur yang lebih sulit adalah mengganti fungsi keluaran yang akan memutus aliran. Saya tidak yakin seberapa kuat janji yang dibuat oleh default_rng . Dokumen tampaknya tidak memperingatkan bahwa ini mungkin berubah sehingga mungkin perlu siklus penghentian untuk berubah. Ini akan membutuhkan penambahan fungsi keluaran baru sebagai generator bit mandiri (atau dapat dikonfigurasi dari PCG64, yang akan lebih masuk akal) dan kemudian memperingatkan pengguna bahwa itu akan berubah setelah tahun XXXX / rilis Y.ZZ.

Jalur tersulit adalah menemukan rng default baru. Itu tidak mudah untuk pertama kalinya dan saya tidak berpikir ada yang berubah untuk menggerakkan jarum ke arah tertentu selama 18 bulan terakhir.

Saya membuka gh-16493 tentang modifikasi default_rng() , saya rasa tidak ada kaitannya dengan masalah ini, bahkan tidak yakin kita harus membahasnya, mungkin kita sudah menetapkan aturannya sejak lama dan saya hanya tidak ' t ingat.


Saya tidak mengklaim memahami diskusi ini sepenuhnya, tetapi tampaknya ada dua hal yang perlu dipikirkan:

  1. Yakin bahwa kita memiliki kemajuan yang cukup, saya harus mempercayai Robert dalam hal ini dan sekarang kedengarannya seperti itu seharusnya baik-baik saja sejauh pengetahuan kita? (Yaitu kemungkinan tabrakan yang sebenarnya mungkin sangat rendah bahkan di lingkungan yang besarnya lebih besar daripada apa pun yang dapat digunakan NumPy? Apakah itu mungkin menjamin perubahan default di masa depan adalah masalah yang berbeda.)
  2. Kami menyatakan:

    dan mendukung [...] serta: math: 2^{127} stream

    yang mana, tidak tahu persis dari mana nomor itu berasal, kedengarannya seperti pernyataan berlebihan di pihak kami dan kami dapat mempertimbangkan untuk menyesuaikannya sedikit agar benar? Atau tautkan ke beberapa sumber daya eksternal yang memberikan detail tambahan?

Hal termudah untuk dilakukan saat ini adalah menambahkan PCG64DXSM BitGenerator , varian PCG64 dengan "pengali murah" dan fungsi keluaran DXSM lebih kuat. Saya pikir semua orang setuju bahwa itu adalah langkah maju dari fungsi keluaran XSL-RR yang kita miliki sekarang dalam implementasi PCG64 , berkinerja lebih baik secara statistik tanpa merusak kinerja runtime. Ini adalah peningkatan langsung di ceruk yang PCG64 melayani untuk BitGenerator s yang kami sediakan. Saya pikir kita harus menambahkannya di samping PCG64 .

Kebetulan, saya lebih suka itu menjadi nama terpisah BitGenerator daripada opsi ke PCG64 konstruktor. Opsi semacam itu bagus di randomgen , yang tujuannya adalah untuk menyediakan banyak algoritme dan varian yang berbeda, tetapi untuk numpy , saya pikir kami ingin pilihan kami menjadi "ambil-dan-pergi" sebagai sebanyak yang kami bisa.

Saya tidak berpikir kami benar-benar menyelesaikan kebijakan untuk membuat perubahan pada apa yang disediakan default_rng() . Ketika saya mengusulkannya, saya mengemukakan gagasan bahwa salah satu alasan saya lebih suka untuk hanya menempatkan fungsinya ke dalam konstruktor Generator() adalah bahwa kami dapat mencela dan pindah ke fungsi dengan nama berbeda jika perlu. Namun, pada saat itu kami mempertimbangkan bahwa default_rng() mungkin perlu mengungkap banyak detail dari BitGenerator , yang kemudian kami hindari. Karena PCG64DXSM memperlihatkan API yang sama ( .jumped() khususnya) sebagai PCG64 , satu-satunya pertimbangan yang kami miliki adalah bahwa menggunakan sebagai default baru akan mengubah bitstream. Saya pikir akan masuk akal bagi kita untuk mengikuti garis waktu yang sama seperti modifikasi lainnya pada aliran yang berasal dari Generator metode per NEP 19 (yaitu pada rilis fitur X.Y.0 ). Kita dapat memilih untuk sedikit lebih berhati-hati, jika kita mau, dan pertama-tama mengekspos PCG64DXSM sebagai BitGenerator dalam 1.20.0 dan dokumen (tetapi bukan warn() , terlalu berisik hingga tidak berpengaruh) bahwa default_rng() akan berubah menjadi 1.21.0 .

Sebagai bagian dari menambahkan BG baru, sebaiknya perbarui catatan ke PCG64 untuk mulai berfungsi sebagai panduan dan memberikan alasan untuk memilih varian yang lebih baru.

  1. Yakin bahwa kita memiliki kemajuan yang cukup, saya harus mempercayai Robert dalam hal ini dan sekarang kedengarannya seperti itu seharusnya baik-baik saja sejauh pengetahuan kita? (Yaitu kemungkinan tabrakan yang sebenarnya mungkin sangat rendah bahkan di lingkungan yang besarnya lebih besar daripada apa pun yang dapat digunakan NumPy? Apakah itu mungkin menjamin perubahan default di masa depan adalah masalah yang berbeda.)

Itu mungkin sedikit terlalu fasih. Itu tergantung pada berapa banyak aliran, berapa banyak data yang Anda tarik dari setiap aliran, dan apa toleransi risiko Anda untuk benturan ulang tahun. Saya belum sempat mengolah matematika itu menjadi paragraf yang dapat dipahami untuk membuat rekomendasi yang mudah diikuti, itulah sebabnya saya belum meninjau kembali masalah Github ini untuk beberapa saat. Saya tidak berpikir itu adalah masalah rambut-on-fire yang perlu diperbaiki _ sekarang juga.

Saya akan menulis sesuatu lebih lama nanti, tetapi seperti yang saya lihat di utas ini, kami telah melakukan vulkanisir atas dasar yang telah kami bahas tahun lalu. Tidak ada yang berubah selain Sebastiano menemukan bahwa NumPy telah mengirimkan PCG. Analisis dari tim NumPy tahun lalu lebih mendalam, dan dianggap skenario yang lebih masuk akal.

Preferensi saya adalah meningkatkan default secepat mungkin - hanya untuk mengurangi kebingungan. Maksud saya, jangan menunggu siklus depreksi.

@imneme - terima kasih banyak - Saya akan menemukan hal yang lebih lama sangat berguna.

Mungkin ledakan terbaik sebelumnya tentang itu adalah yang ini. Saya pikir itu pasti layak dibaca. Anda dapat menggulir kembali utas dari sana untuk melihat kami membicarakan masalah ini. Itu tentang PCG 32.

Ada di kepala saya apa yang ingin saya katakan, tetapi saya menemukan melihat posting dari setahun yang lalu, saya sudah mengatakan semuanya, baik di sini dan di tempat lain ( blog saya (2017), reddit , blog saya lagi (2018) , dan dalam diskusi NumPy, dll.)

Tentang aliran dan kemiripan dirinya (yang @rkern menulis penguji ketergantungan aliran ), saya menulis tahun lalu:

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 kemudian membahas lebih dalam dalam komentar ini dan yang ini .)

Menurut saya, kuncinya adalah bahwa untuk hampir semua PRNG, dengan sedikit waktu dan energi Anda dapat membuat pembibitan patologis. PCG berada dalam posisi yang agak tidak biasa karena memiliki seseorang yang senang bekerja dalam penyemaian yang tampak masuk akal untuk PCG khususnya yang memiliki patologi buatan tangan (yaitu, Sebastiano). Sebagai hasil dari pekerjaan itu, saya telah berbalik dan melakukan hal yang sama untuk PRNG-nya dan PRNG lama lainnya.

Secara umum, Anda ingin menginisialisasi status PRNG dengan sesuatu yang terlihat "agak acak". Itu sangat universal, bahkan jika orang ingin melakukan yang sebaliknya . Misalnya, untuk LFSR PRNG apa pun (XorShift-style, Mersenne Twister, dll.), Anda tidak boleh menginisialisasi dengan status semua-nol karena akan tetap tertahan di sana. Tetapi bahkan keadaan yang sebagian besar nol sering bermasalah untuk LFSR (fenomena yang dikenal sebagai nol, dan mengapa orang-orang C ++ menghasilkan seed_seq .). Jika Anda ingin memainkan permainan “ayo lakukan penyemaian yang dibuat-buat”, tidak sulit untuk membuat kumpulan inisialisasi untuk 100 LFSR dan membuat semuanya berjarak 1K dari mencapai lahan kosong. Inisialisasi yang dibuat-buat akan terlihat cukup polos, tetapi mereka semua akan mengalami penurunan berat yang aneh ini pada saat yang bersamaan.

Jika Anda menggunakan generator PCG yang diinisialisasi dengan entropi yang wajar, tidak masalah. Jika Anda ingin memulainya dengan sampah seperti 1, 2, 3, itu sebenarnya bermasalah dengan PRNG apa pun . Dan dengan PCG, 99,9% dari waktu, bahkan menggunakan sesuatu yang agak bermutu rendah akan baik-baik saja. Ia tidak memiliki masalah seperti yang dimiliki LFSR.

Tapi DXSM jelas lebih kuat. Saya pikir itu lebih baik atau saya tidak akan berhasil, tetapi ada baiknya memiliki beberapa perspektif dan menyadari bahwa dalam praktiknya pengguna tidak akan mengalami masalah dengan implementasi PCG64 klasik.

Saya ingin memisahkan kritik / pembelaan aliran PCG64 (melalui kenaikan LCG) dari diskusi ini. Meskipun ada dualitas tertentu yang terlibat karena matematika LCG, itu bukanlah masalah inti yang awalnya diangkat di sini. Selain itu, ada lebih banyak detail di sini untuk dipertimbangkan daripada yang ada dalam kritik asli Sebastiano, tanggapan Anda , atau mega-thread lama. Mungkin hubungannya lebih jelas bagi para ahli yang telah menghabiskan lebih banyak waktu untuk matematika, tetapi konsekuensi praktis sekarang lebih jelas bagi saya, setidaknya.

Menurut saya, kuncinya adalah bahwa untuk hampir semua PRNG, dengan sedikit waktu dan energi Anda dapat membuat pembibitan patologis.

Memang, tetapi bukan biner can / can't yang mendorong keputusan di depan saya. Jika saya menarik terlalu banyak angka dari PRNG yang terbatas, akhirnya PractRand akan membuangnya. Fakta biner itu tidak membatalkan algoritma PRNG itu. Beranjak dari biner itu dan menetapkan konsep ruang kepala adalah salah satu hal yang sangat saya hargai tentang kertas PCG asli. Dengan adanya patologi yang dihasilkan secara berlawanan, kita dapat melihat seberapa sering patologi tersebut dapat muncul secara acak dari penyemaian entropi yang baik. Saya ingin mengukurnya, dan mengubahnya menjadi saran praktis bagi pengguna.

Diberikan dua status yang berbagi 58 bit lebih rendah dan kenaikan yang sama (kami akan memasukkan pin di dalamnya), interleaving instans PCG64 XSL-RR dari status tersebut menunjukkan kegagalan yang dapat diamati secara praktis di PractRand sekitar 32 GiB. Saya pikir masuk akal untuk ingin menghindari itu. Jadi mari kita anggap itu sebagai patokan kita dan lihat seberapa sering hal itu muncul dengan penyemaian entropi yang baik. Untungnya, skema permusuhan ini dapat menerima analisis probabilistik (tidak semuanya ramah). Untuk n instance, probabilitas dari 2 yang berbagi 58 bit yang sama lebih rendah adalah n**2 / 2**58 , berikan atau ambil faktor 2 untuk penghitungan ganda. Jadi pada setengah miliar kasus, kemungkinan besar ada satu pasangan seperti itu yang akan gagal dalam PractRand jika disisipkan. Setengah miliar itu banyak! Menurut penilaian saya, kita mungkin tidak akan pernah melihat program numpy yang mencoba membuat instance PCG64 . numpy kemungkinan besar akan menjadi alat yang salah.

Saya pikir itu juga masuk akal untuk ingin menghindari status awal yang penarikan berikutnya akan _cross_ salah satu status tabrakan 58-bit yang lebih rendah dari status awal lainnya. Saya masih mencoba memikirkan logika tentang itu, tetapi saya pikir panjangnya memengaruhi probabilitas secara linier daripada secara kuadrat. Jika saya benar, dan saya ingin menarik 16 GiB dari setiap contoh ( 2**28 draw), yaitu berapa banyak yang kita tarik dari masing-masing pasangan yang menunjukkan kegagalan PractRand, maka saya hanya dapat bekerja dengan sekitar 2**15 instance, atau sekitar 32k, sebelum kemungkinan besar untuk mengamati persimpangan. Itu masih cukup banyak contoh untuk Python! Dan jumlah total data yang dihasilkan sekitar setengah petabyte, itu sangat banyak! Tapi itu ada di cakrawala kepraktisan, dan jika saya ingin menjaga probabilitas tetap rendah, tidak hanya di bawah setengah, saya harus menurunkan salah satunya. Saya tidak terlalu khawatir dengan angka-angka ini; Saya tidak berpikir program numpy yang nyata cenderung mengalami masalah menggunakan PCG64 dengan fungsi keluaran XSL-RR. Tetapi beberapa aplikasi mungkin mulai mendekat ( pembelajaran penguatan terdistribusi besar berjalan, misalnya).

Mari kita ambil pin kenaikan itu dan mengatasinya. Saya pikir adil untuk mengatakan bahwa dengan fungsi keluaran XSL-RR, juga entropi-seeding kenaikan selain status tidak mengubah analisis khusus ini. Tampaknya untuk pasangan peningkatan entropi-seeded tertentu, ada jumlah keadaan yang secara praktis bertabrakan sama. Prosedur konkret untuk secara sengaja membangun status tersebut terlihat lebih rumit daripada bashing di 58 bit yang sama lebih rendah, tetapi tampaknya jumlah status bertabrakan adalah sama, jadi perhitungan probabilitasnya tetap sama. Ini tidak intrinsik dengan skema PCG secara umum. Fungsi output DXSM tampaknya cukup kuat sehingga mengubah kenaikan (bahkan dengan +2 ) tampaknya cukup untuk menahan bahkan keadaan kasus terburuk untuk LCG yang mendasarinya (ketika metrik jarak memberikan 0 ), setidaknya sejauh yang saya lakukan untuk menguji dengan PractRand.

Saya ingin mengakhiri dengan mengulangi apa yang tampaknya kita semua sepakat tentang: PCG64DXSM adalah ide yang bagus. Jika tidak ada yang lain, sifat statistiknya yang ditingkatkan menyederhanakan model mental yang saya rasa harus didokumentasikan, dan apa pun yang berarti saya harus menulis lebih sedikit dokumentasi bagus untuk buku saya.

Aliran masih agak relevan karena masalah hanya muncul jika kita memiliki generator di aliran yang sama.

Tetapi dalam keadaan apa mereka memiliki 58 bit yang lebih rendah yang sama dan berada di aliran yang sama? Apakah ada kasus penggunaan di mana hal ini akan terjadi?

Satu kasus yang agak realistis yang saya tahu adalah yang kita bicarakan tahun lalu (ketika kita berbicara tentang jumped ), dan saya bicarakan di posting ini yang saya tautkan sebelumnya.

Aliran masih agak relevan karena masalah hanya muncul jika kita memiliki generator di aliran yang sama.

Sayangnya, tidak demikian halnya dengan XSL-RR. Mari pertimbangkan dua instance PCG64 XSL-RR. Kami entropi-seed kenaikan sewenang-wenang dan entropi-seed salah satu state. Kita dapat membuat 2**70 status buruk untuk instance PCG64 yang gagal dalam PractRand dengan cara yang sama seperti kegagalan peningkatan yang sama-lower-58-bits-state. Ini hanya lebih rumit untuk dilakukan daripada dalam kasus kenaikan yang sama. Alih-alih membagikan 58-bit yang lebih rendah sebagai status pertama dengan kenaikan yang berbeda, itu berbagi 58-bit yang lebih rendah dari status yaitu 0 jarak (sesuai dengan ukuran jarak LCG Anda) dari instans pertama, memperhitungkan kenaikan. Saya memiliki bukti konstruktif (kode Python), tetapi saya harus pergi tidur sekarang dan membersihkannya besok.

@rern , poin yang bagus. Saya akui, saya belum menguji skenario itu untuk melihat bagaimana tarifnya.

Menurut saya, kuncinya adalah bahwa untuk hampir semua PRNG, dengan sedikit waktu dan energi Anda dapat membuat pembibitan patologis. PCG berada dalam posisi yang agak tidak biasa karena memiliki seseorang yang senang bekerja dalam penyemaian yang tampak masuk akal untuk PCG khususnya yang memiliki patologi buatan tangan (yaitu, Sebastiano). Sebagai hasil dari pekerjaan itu, saya telah berbalik dan melakukan hal yang sama untuk PRNG-nya dan PRNG lama lainnya.

Seperti yang telah saya katakan, ini salah. Saya tidak tahu ada contoh sepasang urutan yang berkorelasi dan tidak tumpang tindih, katakanlah, dari xoshiro256 ++ seperti yang dapat Anda temukan dengan mudah dalam PCG.

PRNG yang dengan cepat mencampurkan seluruh negara bagian mereka tidak memiliki masalah ini. Jika Anda dapat menyediakan program yang menghasilkan dua urutan yang tidak tumpang tindih dari xoshiro256 ++ yang berkorelasi, seperti contoh yang saya posting di sini, lakukanlah.

Mengenai program korelasinya, pada tahun 2018 ketika dia memberikan kritik terhadap PCG di situsnya yang menyertakan program yang dia tulis dengan berbagai masalah (seperti penyemaian yang dibuat-buat, dll.), Saya menulis tanggapan yang berisi banyak program serupa untuk PRNG lama lainnya, termasuk corrsplitmix2.c yang membuat aliran terkait di SplitMix. Saya tidak begitu yakin apa yang dimaksud Sebastian ketika dia mengatakan itu tidak dapat dilakukan, tetapi saya akui saya belum memiliki kesempatan untuk melihat lebih dekat program pengujiannya untuk melihat apakah yang baru secara substansial berbeda dari yang dia tulis beberapa tahun lalu.

Program yang dikutip di atas _memilih aliran_. Jelas mudah untuk menulisnya.

Tapi itu tidak ada hubungannya dengan masalah PCG. Program yang saya sediakan membiarkan _user_ memilih aliran, dan kemudian menunjukkan korelasi.

Saya mengundang, sekali lagi, @inmeme untuk menyediakan program untuk SplitMix di mana pengguna dapat memilih dua aliran berbeda secara sewenang-wenang, status awal sembarang dari generator pertama, dan _then_ program menemukan urutan yang berkorelasi di generator lain, seperti http: / /prng.di.unimi.it/corrpcgnumpy.c tidak.

Membiarkan pengguna memilih aliran secara sewenang-wenang menunjukkan bentuk korelasi yang lebih kuat.

Seperti yang telah saya katakan, ini salah. Saya tidak tahu ada contoh sepasang urutan yang berkorelasi dan tidak tumpang tindih, katakanlah, dari xoshiro256 ++ seperti yang dapat Anda temukan dengan mudah dalam PCG.

Sepertinya kita berbicara melewati satu sama lain di sini. Saya tidak mengatakan bahwa saya dapat menghasilkan urutan yang berkorelasi dan tidak tumpang tindih untuk PRNG mana pun, saya mengatakan saya dapat membuat pembenihan patologis secara umum, seperti yang ditunjukkan dengan berbagai program korelasi yang saya tulis sebelumnya, dan lainnya seperti sebagai program demonstrasi berulang yang buruk untuk Xoshiro ** .

Selain itu, PRNG yang tidak mencampur seluruh statusnya memiliki sejarah panjang, termasuk XorWow, generator dalam resep numerik, dll. Argumen Sebastiano mewakili sudut pandang tetapi argumennya akan mengatakan bahwa entah bagaimana Marsaglia membuat XorShift _worse_ di XorWow dengan menambahkan Weyl urutan, karena itu menciptakan sejumlah besar generator serupa.

Sepertinya kita berbicara melewati satu sama lain di sini. Saya tidak mengatakan bahwa saya dapat menghasilkan urutan yang berkorelasi dan tidak tumpang tindih untuk PRNG mana pun, saya mengatakan saya dapat membuat pembenihan patologis secara umum, seperti yang ditunjukkan dengan berbagai program korelasi yang saya tulis sebelumnya, dan lainnya seperti sebagai program demonstrasi berulang yang buruk untuk Xoshiro ** .

Harap coba untuk menjaga diskusi pada tingkat teknis. "Patologis" tidak memiliki arti matematis.

Cara yang benar secara teknis untuk memeriksa korelasi diri adalah menemukan dua benih yang menghasilkan dua urutan yang tidak tumpang tindih (tidak tumpang tindih selama durasi pengujian — mereka pasti akan tumpang tindih jika Anda melangkah cukup jauh), menyisipkan mereka dan meneruskannya ke baterai tes.

Jika Anda menganggap dua urutan yang tumpang tindih, mereka akan dikorelasikan untuk setiap generator, bahkan satu kripto, hanya karena keluaran yang sama akan terjadi dua kali setelah urutan tumpang tindih, dan pengujian yang masuk akal akan mengambilnya.

"Penyemaian patologis" menggunakan urutan yang tumpang tindih adalah tugas yang sepele untuk setiap generator (apa pun arti "patologis").

Sekali lagi, karena Anda mengklaim telah menemukan korelasi yang mirip dengan PCG (di mana urutannya tidak tumpang tindih, seperti yang ditunjukkan pengujian) di generator lain, dapatkah Anda memberikan sepasang urutan yang berkorelasi dan tidak tumpang tindih, katakanlah, dari xoshiro256 ++ atau SFC64 ?

Cara yang benar secara teknis untuk memeriksa korelasi diri adalah menemukan dua benih yang menghasilkan dua urutan yang tidak tumpang tindih (tidak tumpang tindih selama durasi pengujian — mereka pasti akan tumpang tindih jika Anda melangkah cukup jauh), menyisipkan mereka dan meneruskannya ke baterai tes.

Dapatkah Anda menunjuk ke literatur untuk definisi korelasi ini sehingga saya dapat memastikan bahwa saya tetap "secara teknis benar" tentang itu juga?

Sebastiano, Anda tetap ingin saya menjawab tantangan yang ditetapkan sesuai keinginan Anda. Apa yang Anda tunjukkan berkaitan dengan sifat intrinsik LCG, di mana ada kemiripan diri. Anda tidak akan menemukan masalah yang sama pada PRNG yang kacau atau berbasis LFSR.

Tetapi untuk PRNG lainnya akan ada titik lemah lainnya.

LFSR memiliki nol, status buruk, masalah hamming-weight, linearitas, dan seperti yang kami pelajari dengan upaya Anda dengan xoshiro, terkadang keanehan lain seperti masalah aneh dengan pengulangan.

PRNG yang kacau memiliki risiko siklus pendek (meskipun dengan penghitung menghindari hal itu - urutan Weyl FTW!) Dan bias intrinsiknya.

Jika urutannya tumpang tindih, seperti yang saya tulis, pengujian _always_ akan gagal. Anda tidak memerlukan literatur untuk memahami bahwa pengujian yang _selalu gagal_ bukanlah pengujian.

Sekali lagi, karena Anda mengklaim telah menemukan korelasi yang mirip dengan PCG (di mana urutannya tidak tumpang tindih, seperti yang ditunjukkan pengujian) di generator lain, dapatkah Anda memberikan sepasang urutan yang berkorelasi dan tidak tumpang tindih, katakanlah, dari xoshiro256 ++ atau SFC64 ?

Sepertinya Anda benar-benar menghindari pertanyaan itu. Akan sangat mudah bagi Anda, mengikuti klaim Anda, untuk memberikan bukti seperti itu, jika Anda punya.

Hal termudah untuk dilakukan saat ini adalah menambahkan PCG64DXSM BitGenerator , varian PCG64 dengan "pengali murah" dan fungsi keluaran DXSM lebih kuat. Saya pikir semua orang setuju bahwa itu adalah langkah maju dari fungsi keluaran XSL-RR yang kita miliki sekarang dalam implementasi PCG64 , berkinerja lebih baik secara statistik tanpa merusak kinerja runtime. Ini adalah peningkatan langsung di ceruk yang PCG64 melayani untuk BitGenerator s yang kami sediakan. Saya pikir kita harus menambahkannya di samping PCG64 .

Perhatikan bahwa "pengganda murah" 64-bit memiliki cacat yang dapat dibuktikan. Ini diketahui sejak lama:

W. Hörmann dan G. Derflinger, Generator bilangan acak portabel yang cocok untuk
metode penolakan, ACM Trans. Matematika. Softw. 19 (1993), no. 4, 489–495.

Secara umum, pengali yang lebih kecil dari akar kuadrat modulus memiliki batas yang melekat pada skor spektral f₂.

Batasan ini dapat dengan mudah diatasi dengan menggunakan pengali 65-bit, yang akan diubah oleh kompilator hanya dengan operasi "tambah" tambahan, bahkan mungkin tidak mengubah kecepatan generator.

Guy Steele dan saya mengerjakan masalah ini sedikit dan menerbitkan tabel skor spektral untuk pengganda murah dalam berbagai ukuran: https://arxiv.org/pdf/2001.05304.pdf . Semakin besar semakin baik, tetapi ada celah yang dapat dibuktikan dari 64 hingga 65 bit (untuk LCG dengan status 128 bit).

Misalnya, dari Tabel 7 makalah Anda mendapatkan 0x1d605bbb58c8abbfd, yang memiliki skor f₂ 0,9919. Tidak ada pengali 64-bit yang dapat melampaui 0,9306 (Teorema 4.1 di atas kertas).

Setelah campuran dan segala sesuatu, peningkatan skor f₂ mungkin sepenuhnya luput dari perhatian dari sudut pandang statistik. Tetapi mengingat peningkatan besar yang Anda dapatkan untuk dimensi yang paling relevan hanya dengan operasi penambahan tambahan, saya pikir (yah, kami pikir, atau kami tidak akan menulis makalahnya) itu sepadan dengan usaha.

Sebastiano, Anda tetap ingin saya menjawab tantangan yang ditetapkan sesuai keinginan Anda. Apa yang Anda tunjukkan berkaitan dengan sifat intrinsik LCG, di mana ada kemiripan diri. Anda tidak akan menemukan masalah yang sama pada PRNG yang kacau atau berbasis LFSR.

Wah, butuh waktu lama untuk sampai di sana!

LFSR memiliki nol, status buruk, masalah hamming-weight, linearitas, dan seperti yang kami pelajari dengan upaya Anda dengan xoshiro, terkadang keanehan lain seperti masalah aneh dengan pengulangan.

Saya sangat setuju — itulah mengapa Anda harus mengacaknya. Perhatikan bahwa generator LFSR dan F₂-linear adalah hal yang berbeda; terkait, tetapi berbeda.

"Masalah aneh dengan pengulangan", seperti biasa, adalah istilah non-teknis yang tidak dapat saya komentari.

PRNG yang kacau memiliki risiko siklus pendek (meskipun dengan penghitung menghindari hal itu - urutan Weyl FTW!) Dan bias intrinsiknya.

[Pembaruan: Saya melewatkan pengamatan tanggapan dalam tanda kurung, jadi saya memperbarui komentar saya.]

Ya, SFC64 tidak memiliki masalah seperti itu (ini menggunakan penghitung), jadi saya tidak akan menggeneralisasi ke seluruh kategori. Ada generator kacau yang dirancang dengan hati-hati yang memiliki panjang siklus terpendek yang dapat dibuktikan.

"Masalah aneh dengan pengulangan", seperti biasa, adalah istilah non-teknis yang tidak dapat saya komentari.

Tampaknya aneh untuk tidak dapat berkomentar karena saya tidak menggunakan jargon yang tepat - jalankan program ini dan kemudian silakan mencerahkan saya dengan cara terbaik untuk menggambarkan masalah dalam jargon yang tepat dan kemudian memberikan komentar apa pun yang tampaknya sesuai. Saya akan membayangkan bahwa Anda dan David Blackman akan membahas masalah ini ketika pertama kali terungkap karena saya berkorespondensi dengannya tentang hal itu, tetapi saya belum pernah melihat Anda mengomentarinya.

Diskusi PRNG tidak ada di numpy luar topik. Silakan gunakan forum Anda sendiri untuk melanjutkan diskusi itu. Terima kasih.

@rkern - yang tampaknya agak ketat sebagai kriteria. Jika terdapat kekurangan dalam implentasi Numpy yang tidak dimiliki oleh implementasi lain, tampaknya masuk akal untuk dibahas.

Saya dapat mengonfirmasi bahwa pertukaran yang saya maksud tidak membantu saya membuat keputusan yang ada di depan kita dalam masalah ini. Sampai kita membuat kemajuan, saya perlu percakapan tetap fokus.

Saya pikir akan sangat membantu untuk memahami konteks yang lebih luas. Sebastiano memiliki sedikit hal tentang PCG dan telah mencercanya selama bertahun-tahun. Saya pikir hari ini beberapa orang mungkin melihat kami berdua dan memutar mata mereka dan berkata "kalian berdua sama buruknya satu sama lain" karena saya juga mengkritik PRNG-nya, tetapi sebenarnya saya hanya melakukannya setelah dia berkeliling membuat klaim itu Saya mencoba menyembunyikan sesuatu dengan tidak pernah membicarakan barang-barangnya (padahal dalam kenyataannya, saya hanya tidak punya waktu / kecenderungan — sebenarnya, saya hanya menganggap mereka baik-baik saja).

Kritiknya berguna, dan saya senang dia memilih untuk menghabiskan begitu banyak hidupnya memikirkan pekerjaan saya, tetapi penting untuk menyadari bahwa ujiannya bersifat permusuhan. Dia menggunakan pengetahuan tentang struktur PCG untuk merancang pengaturan yang dapat dimasukkan ke penguji RNG dan pengujian yang gagal.

Mengingat betapa menakutkannya hal itu, tampaknya masuk akal untuk menunjukkan bahwa pendekatan permusuhan serupa juga akan membuat banyak generator lain tersandung dan bahwa banyak kekhawatiran yang dia tunjukkan tentang PCG akan berlaku untuk skema generasi lain juga, seperti yang telah saya amati tentang skema pembangkitan seperti XorWow, dan saya sering menggunakan SplitMix sebagai contoh, seperti yang akan saya lakukan di bawah ini. (Tidak satu pun dari kita yang secara khusus berinvestasi di SplitMix dengan satu atau lain cara, saya bayangkan.)

Kita bisa sangat menakutkan tentang SplitMix, misalnya, dan menunjukkan bahwa dengan aliran default konstan, jika kita melihat setiap keluaran 35185, itu gagal dalam rangkaian pengujian PRNG. Oh tidak! Ini karena secara internal menambahkan penghitung (urutan Weyl!) Sebesar 0x9e3779b97f4a7c15 (berdasarkan φ, rasio emas), tetapi 35185 * 0x9e3779b97f4a7c15 = 0x86a100000c480245 , yang hanya memiliki 14 bit diatur dan petak besar tidak ada di tengah. Atau jika kita melihat setiap keluaran 360998717, kita turun menjadi setara dengan penambahan ke keadaan internal 0x48620000800401 , yang hanya 8 bit yang ditambahkan dan lagi sesuatu yang sulit untuk fungsi keluarannya untuk sepenuhnya menutupi .

Kami dapat terus menakut-nakuti tentang SplitMix dan berkata lihat, bagaimana jika saya memiliki dua aliran, satu dengan konstanta aditif 0x9e3779b97f4a7c15 dan lainnya dengan 0xdaa66d2c7ddf743f , kami akan melihat kekurangan jika kami memasukkannya ke suite uji PRNG !!! Tapi itu karena yang kedua dibikin jadi 3x saja.

Dan akhirnya, jika seseorang berkata "Saya akan memberikan Anda kedua streaming, lakukan sesuatu yang menakutkan dengan itu!", Dan katakanlah mereka didasarkan pada π ( 0x243f6a8885a308d3 ) dan _e_ ( 0xb7e151628aed2a6b ), kita dapat mengatakan, tentu, mari kita lakukan lebih banyak menakut-nakuti dan mengambil setiap item 6561221343-th dari aliran Pi dan mencampurkannya dengan setiap item 6663276199-th dari aliran E dan rendah-dan-belhold, mereka menghasilkan dua identik urutan. Dan _lebih buruk lagi, saya kemudian menunjukkan bahwa untuk setiap lompatan di aliran a, ada lompatan yang cocok di aliran b untuk memberikan hasil yang sama, jadi sebenarnya ada 2 ^ 64 cara di mana mereka berkorelasi !!! (Dan kami dapat melakukan ini untuk dua aliran mana pun, tidak ada yang istimewa tentang π dan _e_.)

Kembali ke PCG, pengujian Sebastiano mengandalkan dua generator PCG64 XSH RR yang diselaraskan secara tepat sehingga keluaran yang cocok disisipkan. Jika kita hanya memajukan salah satu PRNG dengan jumlah kecil, merusak keselarasan sempurna sedikit saja, akan jauh lebih sulit untuk mendeteksi apa pun yang mencurigakan.

Tes permusuhan serupa ke arah lain (membebani Sebastiano) akan memberikan output dari PCG64 XSH RR yang memenuhi klaimnya bahwa mereka berkorelasi tetapi kami tidak memberi tahu dia dengan tepat bagaimana mereka diselaraskan (mereka hanya di lingkungan umum yang tepat). Tugasnya adalah menemukan keselarasan untuk menunjukkan bahwa mereka berkorelasi.

Secara keseluruhan, saya tidak berpikir ini adalah masalah dalam praktiknya dengan kebakaran yang mendesak untuk dipadamkan, tetapi di sisi lain, versi DXSM lebih baik seperti yang ditulis tahun lalu untuk mengurangi dengan tepat masalah semacam ini, dan saya akan senang Anda beralih ke sana.

PS Anda dapat membuat konstanta aditif Weyl ajaib dari bilangan real favorit Anda menggunakan kode ini:

WeylConst[r_,bits_] = BitOr[Floor[(r-Floor[r])*2^bits],1]

Itu Mathematica, saya akan membiarkan versi Python sebagai latihan.

Inilah cara saya membuat tabrakan bit rendah untuk peningkatan yang berbeda.

Hasil dengan PCG64 XSL-RR dan tabrakan 58-bit yang lebih rendah

❯ ./pcg64_correlations.py -m 58 | stdbuf -oL ./RNG_test stdin64 -tf 2 -te 1 -tlmaxonly -multithreaded
s0 = 0b01110010100110011101000110010010101111111001100011001011001011111001001110101010011101111101001101011000011100001111111111100001
s1 = 0b10110001011001100111100010000110101110011010101010011011010100011001011111001100010001101001001011010010110101001011101111111100
dist = 0x2eb6ec432b0ea0f4fc00000000000000
[
    {
        "bit_generator": "PCG64",
        "state": {
            "state": 152330663589051481538402839025803132897,
            "inc": 228410650821285501905570422998802152525
        },
        "has_uint32": 0,
        "uinteger": 0
    },
    {
        "bit_generator": "PCG64",
        "state": {
            "state": 235805414096687854712168706130903874556,
            "inc": 70910205337619270663569052684874994465
        },
        "has_uint32": 0,
        "uinteger": 0
    }
]
RNG_test using PractRand version 0.93
RNG = RNG_stdin64, seed = 0x12d551b8
test set = expanded, folding = extra

rng=RNG_stdin64, seed=0x12d551b8
length= 128 megabytes (2^27 bytes), time= 2.8 seconds
  no anomalies in 891 test result(s)

rng=RNG_stdin64, seed=0x12d551b8
length= 256 megabytes (2^28 bytes), time= 9.4 seconds
  no anomalies in 938 test result(s)

rng=RNG_stdin64, seed=0x12d551b8
length= 512 megabytes (2^29 bytes), time= 18.1 seconds
  no anomalies in 985 test result(s)

rng=RNG_stdin64, seed=0x12d551b8
length= 1 gigabyte (2^30 bytes), time= 31.2 seconds
  Test Name                         Raw       Processed     Evaluation
  [Low1/8]FPF-14+6/16:cross         R=  +4.9  p =  1.7e-4   unusual          
  [Low4/16]FPF-14+6/16:all          R=  +8.4  p =  2.3e-7   very suspicious  
  [Low4/16]FPF-14+6/16:all2         R=  +8.3  p =  8.1e-5   unusual          
  [Low8/32]FPF-14+6/32:all          R=  +6.3  p =  2.1e-5   mildly suspicious
  [Low8/32]FPF-14+6/16:all          R=  +5.7  p =  8.0e-5   unusual          
  ...and 1034 test result(s) without anomalies

rng=RNG_stdin64, seed=0x12d551b8
length= 2 gigabytes (2^31 bytes), time= 52.7 seconds
  Test Name                         Raw       Processed     Evaluation
  [Low4/16]FPF-14+6/32:all          R=  +7.4  p =  2.0e-6   suspicious       
  [Low4/16]FPF-14+6/16:(0,14-0)     R=  +7.7  p =  9.4e-7   unusual          
  [Low4/16]FPF-14+6/16:all          R=  +8.0  p =  5.9e-7   suspicious       
  [Low4/16]FPF-14+6/16:all2         R= +12.2  p =  2.1e-6   mildly suspicious
  [Low4/16]FPF-14+6/4:(0,14-0)      R=  +7.9  p =  6.3e-7   mildly suspicious
  [Low4/16]FPF-14+6/4:all           R=  +5.8  p =  6.7e-5   unusual          
  [Low4/16]FPF-14+6/4:all2          R= +11.5  p =  3.1e-6   mildly suspicious
  [Low8/32]FPF-14+6/32:(0,14-0)     R=  +7.8  p =  8.4e-7   unusual          
  [Low8/32]FPF-14+6/32:all          R=  +7.3  p =  2.3e-6   suspicious       
  [Low8/32]FPF-14+6/32:all2         R= +14.3  p =  3.8e-7   suspicious       
  [Low8/32]FPF-14+6/16:(0,14-0)     R=  +7.7  p =  8.8e-7   unusual          
  [Low8/32]FPF-14+6/16:(1,14-0)     R=  +7.7  p =  9.3e-7   unusual          
  [Low8/32]FPF-14+6/16:all          R=  +6.9  p =  5.3e-6   mildly suspicious
  [Low8/32]FPF-14+6/16:all2         R= +18.3  p =  8.0e-9   very suspicious  
  ...and 1078 test result(s) without anomalies

rng=RNG_stdin64, seed=0x12d551b8
length= 4 gigabytes (2^32 bytes), time= 90.2 seconds
  Test Name                         Raw       Processed     Evaluation
  [Low1/8]BCFN_FF(2+0):freq         R= +14.8  p~=   6e-18     FAIL !         
  [Low1/8]BCFN_FF(2+1):freq         R=  +7.4  p~=   1e-6    mildly suspicious
  [Low1/8]FPF-14+6/16:cross         R=  +8.4  p =  2.1e-7   very suspicious  
  [Low4/16]FPF-14+6/32:(0,14-0)     R=  +8.9  p =  8.1e-8   mildly suspicious
  [Low4/16]FPF-14+6/32:(1,14-0)     R=  +8.5  p =  1.9e-7   mildly suspicious
  [Low4/16]FPF-14+6/32:all          R=  +9.4  p =  2.4e-8   very suspicious  
  [Low4/16]FPF-14+6/32:all2         R= +23.9  p =  5.2e-11   VERY SUSPICIOUS 
  [Low4/16]FPF-14+6/16:(0,14-0)     R= +13.8  p =  2.2e-12   VERY SUSPICIOUS 
  [Low4/16]FPF-14+6/16:(1,14-0)     R= +10.0  p =  7.3e-9   suspicious       
  [Low4/16]FPF-14+6/16:all          R= +12.1  p =  8.0e-11   VERY SUSPICIOUS 
  [Low4/16]FPF-14+6/16:all2         R= +52.5  p =  1.3e-22    FAIL !!        
  [Low4/16]FPF-14+6/4:(0,14-0)      R= +12.2  p =  7.0e-11   VERY SUSPICIOUS 
  [Low4/16]FPF-14+6/4:all           R=  +7.1  p =  3.7e-6   mildly suspicious
  [Low4/16]FPF-14+6/4:all2          R= +29.8  p =  7.1e-14    FAIL           
  [Low4/16]FPF-14+6/4:cross         R=  +5.3  p =  7.8e-5   unusual          
  [Low4/32]FPF-14+6/32:(0,14-0)     R=  +7.6  p =  1.3e-6   unusual          
  [Low4/32]FPF-14+6/32:all          R=  +6.0  p =  4.4e-5   unusual          
  [Low4/32]FPF-14+6/32:all2         R=  +9.4  p =  2.9e-5   unusual          
  [Low4/32]FPF-14+6/16:(0,14-0)     R=  +7.3  p =  2.5e-6   unusual          
  [Low4/32]FPF-14+6/16:all          R=  +6.5  p =  1.4e-5   mildly suspicious
  [Low4/32]FPF-14+6/16:all2         R=  +8.2  p =  8.0e-5   unusual          
  [Low8/32]FPF-14+6/32:(0,14-0)     R= +17.2  p =  1.7e-15    FAIL           
  [Low8/32]FPF-14+6/32:(1,14-0)     R= +12.7  p =  2.3e-11   VERY SUSPICIOUS 
  [Low8/32]FPF-14+6/32:all          R= +15.3  p =  7.9e-14    FAIL           
  [Low8/32]FPF-14+6/32:all2         R= +86.1  p =  1.2e-35    FAIL !!!       
  [Low8/32]FPF-14+6/16:(0,14-0)     R= +16.8  p =  3.5e-15    FAIL           
  [Low8/32]FPF-14+6/16:(1,14-0)     R= +12.2  p =  6.6e-11   VERY SUSPICIOUS 
  [Low8/32]FPF-14+6/16:all          R= +13.1  p =  8.9e-12   VERY SUSPICIOUS 
  [Low8/32]FPF-14+6/16:all2         R= +82.1  p =  1.7e-34    FAIL !!!       
  [Low8/32]FPF-14+6/4:(0,14-0)      R= +12.8  p =  2.0e-11   VERY SUSPICIOUS 
  [Low8/32]FPF-14+6/4:(1,14-0)      R=  +9.4  p =  2.5e-8   suspicious       
  [Low8/32]FPF-14+6/4:all           R= +10.5  p =  2.2e-9    VERY SUSPICIOUS 
  [Low8/32]FPF-14+6/4:all2          R= +42.0  p =  5.8e-19    FAIL !         
  ...and 1118 test result(s) without anomalies

Hasil dengan PCG64 DXSM dan tabrakan 64-bit yang lebih rendah (untuk memicu masalah lebih cepat, meskipun saya tidak melihat ada)

❯ ./pcg64_correlations.py -m 64 --dxsm | stdbuf -oL ./RNG_test stdin64 -tf 2 -te 1 -tlmaxonly -multithreaded
s0 = 0b10001000010110111101010101010101111100100011011111011111011111001011110101111100101101101100110101110001101101111111010101111111
s1 = 0b11000101110100011001011000001110100001001111001001100101010000101100011001010111011001100000010010011100101110001110101000011100
dist = 0x3a26b19c91e6da1d0000000000000000
[
    {
        "bit_generator": "PCG64DXSM",
        "state": {
            "state": 181251833403477538233003277050491434367,
            "inc": 46073632738916603716779705377640239269
        },
        "has_uint32": 0,
        "uinteger": 0
    },
    {
        "bit_generator": "PCG64DXSM",
        "state": {
            "state": 262946148724842088422233355148768897564,
            "inc": 125105549038853892415237434774494719583
        },
        "has_uint32": 0,
        "uinteger": 0
    }
]
RNG_test using PractRand version 0.93
RNG = RNG_stdin64, seed = 0x85cea9
test set = expanded, folding = extra

rng=RNG_stdin64, seed=0x85cea9
length= 128 megabytes (2^27 bytes), time= 2.6 seconds
  no anomalies in 891 test result(s)

rng=RNG_stdin64, seed=0x85cea9
length= 256 megabytes (2^28 bytes), time= 9.4 seconds
  no anomalies in 938 test result(s)

rng=RNG_stdin64, seed=0x85cea9
length= 512 megabytes (2^29 bytes), time= 18.5 seconds
  no anomalies in 985 test result(s)

rng=RNG_stdin64, seed=0x85cea9
length= 1 gigabyte (2^30 bytes), time= 32.3 seconds
  Test Name                         Raw       Processed     Evaluation
  [Low4/32]BCFN_FF(2+3,13-3,T)      R=  -8.3  p =1-9.5e-5   unusual          
  ...and 1035 test result(s) without anomalies

rng=RNG_stdin64, seed=0x85cea9
length= 2 gigabytes (2^31 bytes), time= 55.8 seconds
  no anomalies in 1092 test result(s)

rng=RNG_stdin64, seed=0x85cea9
length= 4 gigabytes (2^32 bytes), time= 93.1 seconds
  no anomalies in 1154 test result(s)

rng=RNG_stdin64, seed=0x85cea9
length= 8 gigabytes (2^33 bytes), time= 175 seconds
  no anomalies in 1222 test result(s)

rng=RNG_stdin64, seed=0x85cea9
length= 16 gigabytes (2^34 bytes), time= 326 seconds
  no anomalies in 1302 test result(s)

rng=RNG_stdin64, seed=0x85cea9
length= 32 gigabytes (2^35 bytes), time= 594 seconds
  no anomalies in 1359 test result(s)

rng=RNG_stdin64, seed=0x85cea9
length= 64 gigabytes (2^36 bytes), time= 1194 seconds
  no anomalies in 1434 test result(s)

rng=RNG_stdin64, seed=0x85cea9
length= 128 gigabytes (2^37 bytes), time= 2334 seconds
  no anomalies in 1506 test result(s)
...

@rkern , terima kasih telah membagikan kode Anda. Akan bermanfaat untuk menambahkan opsi untuk menambahkan kemiringan untuk memberi makan output yang disisipkan ke penguji yang tidak selaras dengan sempurna. Itu adalah sesuatu yang sedikit saya jelajahi.

Yup, saya telah melakukannya secara informal dengan memasukkan bg0.advance(N) untuk berbagai N sebelum return . Saya menggunakan tabrakan 64-bit yang lebih rendah untuk memastikan saya akan melihat sesuatu. Pergeseran kecil seperti 16 tidak banyak mengubah kegagalan, tetapi bahkan perubahan kecil seperti 128 memperpanjang kegagalan hingga 32 GiB.

Sepertinya kita harus menambahkan PCG64 DXSM sebagai bitgenerator opsional dan akhirnya menjadikannya sebagai default. Untuk kita memiliki implementasi?

Saya pikir akan sangat membantu untuk memahami konteks yang lebih luas. Sebastiano memiliki sedikit hal tentang PCG dan telah mencercanya selama bertahun-tahun. Saya pikir hari ini beberapa orang mungkin melihat kami berdua dan memutar mata mereka dan berkata "kalian berdua sama buruknya satu sama lain" karena saya juga mengkritik PRNG-nya, tetapi sebenarnya saya hanya melakukannya setelah dia berkeliling membuat klaim itu Saya mencoba menyembunyikan sesuatu dengan tidak pernah membicarakan barang-barangnya (padahal dalam kenyataannya, saya hanya tidak punya waktu / kecenderungan — sebenarnya, saya hanya menganggap mereka baik-baik saja).

Saya pikir pertimbangan ini sama sekali tidak tepat.

Berkeras untuk menyerang pekerjaan orang lain (misalnya, SplitMix) tanpa alasan apapun dan tanpa bukti apapun tidak akan membuat kekacauan PCG, atau generator Numpy, menjadi lebih baik. Pengganda yang lebih baik, atau pengacak yang dirancang lebih baik, mungkin bisa membantu.

Saya masih menunggu tes yang menunjukkan korelasi di SplitMix ketika pengguna dapat memilih aliran. Untuk memperjelas, untuk generator Numpy saya membuktikan pernyataan formulir tersebut

∀c ∀d ∀x ∃y berkorelasi

di mana c, d adalah kenaikan ("aliran"), dan x, y adalah keadaan awal. Faktanya, ada 2 ^ 72 y. Artinya, tidak peduli bagaimana Anda memilih c, d, dan x, ada korelasi yang menunjukkan 2 ^ 72 y.

Kode yang diduga sesuai yang Anda berikan untuk SplitMix menunjukkan hal itu

∃c ∃d ∃x ∃y berkorelasi

Artinya, memilih secara berlawanan c, d, x dan y Anda dapat menunjukkan korelasi.

Perbedaan kekuatan dalam kedua pernyataan tersebut cukup mencengangkan. Mencoba menggabungkan kedua pernyataan itu salah.

@vigna sekarang Anda telah diperingatkan dua kali tentang kode etik kami, oleh @mattip dan @rkern. Menggunakan bahasa seperti "meronta-ronta pekerjaan orang lain" dan "Mencoba menggabungkan dua pernyataan itu murni FUD" tidak diperbolehkan. Anggap ini peringatan terakhir Anda. Silakan ubah nada bicara Anda atau kami _will_ mencekal Anda. Argumen teknis masih diterima, yang lainnya tidak pada saat ini.

Saya memodifikasi pesan dengan mengganti ekspresi itu dengan yang netral. Saya masih berpikir bahwa menyerang secara pribadi peserta lain dalam diskusi ("Sebastiano memiliki sedikit hal tentang PCG dan telah mencercanya selama bertahun-tahun") sepenuhnya tidak pantas. Saya sangat terkejut bukan untuk Anda.

Untuk ketiga dan terakhir kalinya, diskusi tentang SplitMix, di kedua arah, tidak membantu saya sedikit pun. Saya dapat memahami mengapa menurut Anda ini memberikan konteks yang diperlukan, atau bahwa Anda merasa terdorong untuk menanggapi yang lain, tetapi percayalah bahwa saya mengatakan yang sebenarnya bahwa itu tidak memberi saya informasi apa pun yang membantu saya membuat keputusan di sini. Anda berdua memiliki situs web sendiri. Gunakan mereka.

Saya memodifikasi pesan dengan mengganti ekspresi itu dengan yang netral.

Terima kasih.

Saya masih berpikir bahwa menyerang secara pribadi peserta lain dalam diskusi ("Sebastiano memiliki sedikit hal tentang PCG dan telah mencercanya selama bertahun-tahun") sepenuhnya tidak pantas. Saya sangat terkejut bukan untuk Anda.

Aku memang lebih suka untuk tidak melihatnya. Namun nada pesan itu tidak seburuk itu.

Saya akan sangat menghargai jika Anda berdua dapat tetap berpegang pada pernyataan faktual konstruktif @vigna dan @imneme.

BAIK. Mari kita mulai dari awal: Anda menginginkan generator dengan semacam aliran berdasarkan LCG dengan modulus power-of-2 untuk kenyamanan dan kecepatan. Literatur menunjukkan bahwa mendasarkan aliran pada konstanta aditif LCG dapat membawa Anda ke dalam masalah (seperti yang terjadi sekarang), tetapi anggaplah itu yang Anda inginkan.

Mengapa tidak mengambil LCG dengan status 128-bit dan pengganda yang baik (setidaknya 65 bit) dan mengganggu bit atas menggunakan fungsi campuran dari SplitMix, yang telah banyak diuji dalam berbagai aplikasi (hashing, PRNG, dll.), memberikan hasil yang luar biasa?

Saya cukup yakin perbedaan kecepatan akan kecil. Dan Anda memiliki beberapa jaminan (statistik) bahwa hasilnya akan bergantung pada semua bit, yang menjadi masalah di sini.

Bagi saya ini lebih merupakan pendekatan "berdiri di bahu raksasa" daripada membuat fungsi pencampuran pada generator yang memiliki masalah korelasi diri.

@imneme Yang bisa saya gunakan adalah posting blog tentang DXSM yang lebih mudah ditautkan daripada komentar pengumuman ini di mega-issue lama. Tidak harus lebih dari apa yang ada di komentar itu, tetapi menyertakan status pengujian saat ini yang Anda sebutkan di sini akan bagus. Jika Anda ingin meringkas beberapa diskusi dari mega-isu yang mengarah pada perkembangan itu, hal itu pasti berguna, tetapi tidak sepenuhnya diperlukan.

@tokopedia

Mengapa tidak mengambil LCG dengan status 128-bit dan pengganda yang baik (setidaknya 65 bit) dan mengganggu bit atas menggunakan fungsi campuran dari SplitMix, yang telah banyak diuji dalam berbagai aplikasi (hashing, PRNG, dll.), memberikan hasil yang luar biasa?

Saya mohon maaf jika ini kedengarannya aneh (meskipun pasti akan menunjuk), tetapi juga tulus: Saya berharap dapat melihat hasil implementasi, analisis, tolok ukur, dan PractRand di situs web Anda atau di arXiv. Kami adalah praktisi (dengan informasi yang masuk akal) di sini, bukan peneliti PRNG, dan tidak diperlengkapi dengan baik untuk melaksanakan saran ini. Saya dapat melihat pengertiannya, tetapi mengingat kendala lain pada waktu pribadi saya, saya tidak memiliki kecenderungan untuk menghabiskan upaya untuk mengambil ini dari saran ke implementasi dan analisis. Jika Anda menanggapi saran ini secara berlebihan, kami membutuhkan peneliti PRNG untuk melakukan pekerjaan itu. Jika Anda benar-benar menyampaikan saran ini kepada orang lain, gunakan situs web Anda.

Arsitektur Generator -> BitGenerator -> SeedSequence secara acak di NumPy dimaksudkan untuk dapat dicolokkan. Saya pikir kita sampai pada titik diskusi di mana kita membutuhkan seseorang untuk membuka PR untuk BitGenerator, sehingga kita dapat membandingkan atribut praktisnya dengan yang saat ini ada di NumPy. Setelah menjadi bagian dari proyek, kami dapat terus mengujinya dan dapat memutuskan untuk menjadikannya sebagai default. Keputusan itu, saya harap, akan didasarkan

  • kurangnya bias (dan kriteria lainnya? Saya menyerah kepada ahlinya)
  • kinerja
  • kemungkinan berbagai jenis tabrakan aliran melalui antarmuka normatif yang kami promosikan: menggunakan BitGenerator.spawn dan SeedSequence .

Secara pribadi, diskusi ini membuat saya bingung ketika menghindari membahas manfaat BitGenerators melalui kode yang menggunakan antarmuka spawn . Ada alasan mengapa kami mempromosikannya sebagai praktik terbaik, dan saya berharap pembahasan PR di masa mendatang akan berfokus pada praktik terbaik untuk pengguna NumPy .

Mungkin salah satu kesimpulan di sini adalah bahwa kita hanya boleh mengizinkan spawn sebagai metode, karena menggunakan jumped atau advance dapat melanggar praktik yang baik. Masalah baru atau NEP yang berfokus pada hal ini mungkin juga produktif.

@ Mattip Tabrakan ulang tahun bit rendah yang dicatat @vigna memengaruhi antarmuka SeedSequence.spawn() juga. Yakinlah bahwa setiap bagian dari diskusi yang saya ikuti relevan dengan penggunaan yang tepat dari API kami.

Ini hanya perlu menambahkan sekitar 8 baris ke pcg64.c dengan beberapa blok #ifdef untuk menggunakan pendekatan pilihan

Saya mungkin akan lebih eksplisit tentang itu, terutama untuk matematika 128-bit yang ditiru untuk platform yang membutuhkannya.

https://github.com/rkern/numpy/compare/v1.17.4...rkern%3Awip/pcg64-dxsm

Tampaknya lebih mudah daripada itu bagi saya karena menggunakan pengali 64 bit "murah". Anda bisa menambahkan mixer keluaran baru (yang tidak berubah) dan kemudian ifdef di sekitar baris terakhir dari generator acak yang mengambil keluaran dari LCG dan kemudian menerapkan mixer.

https://github.com/bashtage/randomgen/commit/63e50a63f386b5fd725025f2199ff89454321f4c#diff -879bd64ee1e2b88fec97b5315cf77be1R115

Jika seseorang mau, Anda bahkan bisa menambahkan Murmur Hash 3 pada saat ini, apakah orang itu cenderung.

Apakah pernyataan if akan dikompilasi? Saya tidak berpikir kita ingin kelipatannya di dalam hot loop.

Sekali lagi, ini tergantung pada perbedaan tujuan antara randomgen dan numpy . Masuk akal di randomgen untuk membuat keluarga berparameter, tetapi di numpy , menurut saya bukan ide yang baik untuk melibatkan implementasi warisan BitGenerator dari default aktif BitGenerator . Jika kita harus melakukan pemeliharaan atau pemfaktoran ulang untuk kinerja satu atau yang lain, itu hanya akan membuat upaya itu lebih buruk daripada lebih baik.

Setuju dengan Robert di sini. Saya tidak ragu untuk memasang pembuat bit baru di rilis 1.19.0, itu tidak akan mengubah perilaku apa pun saat ini.

@bashtage Juga, perhatikan bahwa pcg_cm_random_r() menggunakan status pra-iterasi untuk menghasilkan daripada status pasca-iterasi , jadi tidak akan sesederhana mempertahankan jalur kode yang sama dengan #ifdef atau if saklar.

Apakah pernyataan if akan dikompilasi? Saya tidak berpikir kita ingin kelipatannya di dalam hot loop.

Tidak, di NumPy if else harus menjadi seperti

#if defined(PCG_DXSM)
    pcg_output_dxsm(state.high, state.low)
#else 
   <old way>
#endif

Ini perlu ditentukan secara terpisah dalam versi uint128 dan versi cadangan untuk menangani pengalihan uint128 secara manual ke tinggi dan rendah.

@bashtage Juga, perhatikan bahwa pcg_cm_random_r() menggunakan status pra-iterasi ke keluaran daripada status pasca-iterasi , jadi tidak akan sesederhana mempertahankan jalur kode yang sama dengan #ifdef atau if saklar.

Hmm, saya menguji implementasi referensi @imneme dan mendapatkan kecocokan 100% pada 1000 nilai menggunakan 2 seed berbeda:

https://github.com/bashtage/randomgen/blob/master/randomgen/src/pcg64/pcg_dxsm-test-data-gen.cpp

Saya tidak yakin apa yang Anda coba katakan di sana.

Tidak jelas apa PCG64 DXSM kanonik itu. Dalam kedua kasus tersebut, fungsi keluaran hanya menggunakan operasi 64-bit. Versi yang Anda miliki menggunakan pengganda 64 bit di lokasi lain agar lebih cepat dan menampilkan pra, daripada posting. setseq_dxsm_128_64 sepertinya merupakan perpanjangan alami dari PCG64 yang ada dan hanya mengubah fungsi keluaran.

Oh begitu. Tidak, Anda menggunakan generator C ++ yang berbeda dari yang saya terapkan di C. Saya menerapkan setara dengan cm_setseq_dxsm_128_64 yang menggunakan "pengganda murah" dalam iterasi LCG, bukan setseq_dxsm_128_64 yang masih menggunakan pengali besar dalam iterasi LCG. "Pengganda murah" digunakan kembali di dalam fungsi keluaran DXSM, tapi itu adalah sumbu desain ortogonal.

Mengapa tidak memilih setseq_dxsm_128_64?

@imneme mengatakan bahwa dia akhirnya akan mengubah pcg64 resmi dalam versi C ++ untuk menunjuk ke cm_setseq_dxsm_128_64 , bukan setseq_dxsm_128_64 . Pengganda yang murah mengimbangi sebagian dari biaya tambahan DXSM dibandingkan dengan XSL-RR. Dan saya pikir itu adalah varian yang dia habiskan selama beberapa bulan untuk mengujinya.

Mengeluarkan status pra-iterasi juga merupakan bagian dari peningkatan kinerja .

Berikut beberapa pengaturan waktu:

In [4]: %timeit p.random_raw(1000000)
3.24 ms ± 4.61 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

In [5]: p = rg.PCG64(mode="sequence",use_dxsm=False)

In [6]: %timeit p.random_raw(1000000)
3.04 ms ± 8.47 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

In [7]: import numpy as np

In [8]: p = np.random.PCG64()

In [9]: %timeit p.random_raw(1000000)
3.03 ms ± 2.54 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

Semua di Ubuntu-20.04, kompiler default.

6% lebih lambat. Sepertinya perbedaan kecil bagi saya. Semua pengaturan waktu di NumPy / randomgen cukup jauh dari apa yang bisa Anda dapatkan dalam loop ketat kode asli.

Membandingkan

In [10]: x = rg.Xoroshiro128(mode="sequence")

In [11]: %timeit x.random_raw(1000000)
2.59 ms ± 35.7 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

untuk apa yang telah diterbitkan dari kode C (150% lebih lambat ??).

Memang, dalam konteks numpy , itu tidak terlalu penting. Itu lebih penting dalam konteks C ++, yang mendorong alokasi cluster-bulan ke pengujian dan nominasi sebagai default masa depan pcg64 dalam kode C ++ resmi. Itu adalah motivasi terdekat untuk numpy , IMO.

Perbedaan antara saham PCG64 dan PCG64DXSM saya di cabang saya ("pengganda murah", fungsi keluaran DXSM, keluaran keadaan pra-iterasi, alur kode terpisah):

[practrand]
|1> s = np.random.SeedSequence()

[practrand]
|2> pcg64 = np.random.PCG64(s)

[practrand]
|3> pcg64dxsm = np.random.PCG64DXSM(s)

[practrand]
|4> %timeit pcg64.random_raw(1000000)
100 loops, best of 3: 3.46 ms per loop

[practrand]
|5> %timeit pcg64dxsm.random_raw(1000000)
100 loops, best of 3: 2.9 ms per loop

Saya masih mengatakan itu hanya sedikit (lebih dari yang saya miliki) #ifdefs antara keduanya, bahkan dengan implementasi khusus untuk MSVC. Ditambah pengguna RSN MS akan dapat menggunakan dentang # 13816 👍.

Apakah kita memperdebatkan duplikasi kode? Saya lebih suka memiliki implementasi terputus-putus daripada khawatir tentang beberapa baris kode yang dikaburkan dengan #ifdefs :)

Itu sebagian besar hanya lelucon, meskipun itu menyoroti kebutuhan akan pernyataan yang benar-benar jelas yang mendefinisikan "PCG 2.0" (lebih disukai di tempat yang bukan masalah GitHub NumPy).

Terima kasih, @rkern et al.

@imneme Yang bisa saya gunakan adalah posting blog tentang DXSM yang lebih mudah ditautkan daripada komentar pengumuman ini di mega-issue lama. Tidak harus lebih dari apa yang ada di komentar itu, tetapi menyertakan status pengujian saat ini yang Anda sebutkan di sini akan bagus. Jika Anda ingin meringkas beberapa diskusi dari mega-isu yang mengarah pada perkembangan itu, hal itu pasti berguna, tetapi tidak sepenuhnya diperlukan.

Apakah Anda sudah memikirkan kerangka waktu? Saya sudah lama bermaksud untuk melakukan ini selama beberapa waktu dan membuatnya didorong oleh hal-hal lain, jadi sebenarnya memiliki tenggat waktu yang diusulkan akan menjadi motivator yang berguna bagi saya. Mungkin seminggu? Dua?

@rkern juga mengutip @vigna , yang menulis:

Mengapa tidak mengambil LCG dengan status 128-bit dan pengganda yang baik (setidaknya 65 bit) dan mengganggu bit atas menggunakan fungsi campuran dari SplitMix, yang telah banyak diuji dalam berbagai aplikasi (hashing, PRNG, dll.), memberikan hasil yang luar biasa?

FWIW, pendekatan ini telah dibahas di kertas PCG asli, menggunakan _FastHash_ sebagai fungsi hash off-the-shelf, yang merupakan fungsi hash multiply-xorshift yang sangat mirip. Dalam pengujian saya, itu tidak secepat permutasi lainnya, tetapi berkualitas tinggi. Sebastiano juga menyebutkan ide ini dalam kritiknya pada 2018 terhadap PCG dan saya membahasnya di bagian tanggapan saya terhadap kritik itu.

Dalam versi asli dari kritik PCG-nya, dia mengakhirinya dengan menulis varian PCG-nya sendiri, yang akan saya kutip di bawah ini:

        #include <stdint.h>

        __uint128_t x;

        uint64_t inline next(void) {
            // Put in z the top bits of state
            uint64_t z = x >> 64;
            // Update state
            x = x * ((__uint128_t)0x2360ed051fc65da4 << 64 ^ 0x4385df649fccf645)
                  + ((__uint128_t)0x5851f42d4c957f2d << 64 ^ 0x14057b7ef767814f);
            // Compute mix
            z = (z ^ (z >> 30)) * 0xbf58476d1ce4e5b9;
            z = (z ^ (z >> 27)) * 0x94d049bb133111eb;
            return z ^ (z >> 31);
        }

Dia sejak itu memperbarui kode dalam kritiknya ke versi yang lebih cepat yang menggunakan pengganda yang lebih murah dan memotong konstanta aditif menjadi hanya 64 bit,

        #include <stdint.h>

        __uint128_t x;

        uint64_t inline next(void) {
            // Put in z the top bits of state
            uint64_t z = x >> 64;
            // Update state (multiplier from https://arxiv.org/abs/2001.05304)
            x = x * ((__uint128_t)1 << 64 ^ 0xd605bbb58c8abbfd) + 0x14057b7ef767814f;
            // Compute mix
            z = (z ^ (z >> 30)) * 0xbf58476d1ce4e5b9;
            z = (z ^ (z >> 27)) * 0x94d049bb133111eb;
            return z ^ (z >> 31);
        }

Masalah saya dengan kedua varian ini adalah bahwa permutasi tidak dapat dibalik karena status terpotong (bagian atas) diizinkan / diacak - Anda dapat menjalankannya mundur dan menguraikan pengacakan sehingga Anda hanya memiliki LCG yang terpotong dengan semua kekurangan yang melekat di dalamnya. Preferensi saya adalah mengubah / mengacaukan seluruh negara bagian dan kemudian mengeluarkan pemotongan itu. (Tentu saja, mengubah / mengacak bit yang lebih sedikit akan menjadi cara yang lebih cepat - seperti biasa ada pertukaran. Orang yang berakal sehat dapat tidak menyetujui apa yang penting.)

Tetapi karyanya membuat varian PCG sendiri memberikan inspirasi yang sangat berguna untuk permutasi DXSM ketika saya menulisnya tahun lalu.

@charris Apa keinginan Anda untuk membuat implementasi PCG64DXSM tersedia (tapi belum default) ke 1.19.0? Apa garis waktu itu? Saya melihat kami sudah merilis 1.19.0rc2, yang tidak _great_ untuk memperkenalkan fitur baru. Sekali lagi, saya tidak terlalu bersemangat tentang masalah ini. Saya cenderung merilis 1.19.0 hanya dengan mendokumentasikan kebijakan kami tentang perubahan pada default_rng() dan memperkenalkan hal-hal baru di 1.20.0.

@rkern RC terakhir harus tersedia selama> dua minggu, jadi kami akan merilisnya sekitar paruh kedua bulan Juni. Saya mendukung menempatkan PCG64DXSM sebagai pilihan opsional jika memfasilitasi pengujian, saya tidak terlalu menganggapnya sebagai fitur baru, lebih seperti aksesori baru. Dan terkadang membantu memindahkan berbagai hal untuk memiliki kode kerja aktual di luar sana. NumPy adalah trend setter :)

EDIT: Dengan asumsi, tentu saja, bahwa tidak ada masalah besar dengan kode baru, dan sepertinya tidak ada. Saya juga tidak terlalu khawatir tentang masalah dengan PCG64, sepertinya tidak mungkin ada orang yang akan mengalami masalah dalam menggunakan prosedur yang kami rekomendasikan.

@imneme Satu minggu akan menjadi luar biasa. Dua minggu sudah cukup. Terima kasih!

Ada pertanyaan yang saya tanyakan pada diri saya sendiri yang agak di luar topik. Kami ingin pembuat bit kami menghasilkan bit acak, tetapi AFAICT, sebagian besar pengujian melibatkan bilangan bulat. Seberapa baik sebenarnya pengujian yang ada dalam menguji bit? Jika seseorang yang lebih akrab dengan area tersebut dapat menjawab pertanyaan itu, saya akan sangat berterima kasih.

Apa yang diuji adalah aliran bit. Kami memberi tahu perangkat lunak pengujian ukuran kata alami dari PRNG yang kami keluarkan, tetapi hanya agar ia dapat melakukan lipatan bit terbaik agar paling efisien memicu kesalahan yang cenderung muncul di bit rendah atau tinggi dari bit kata dalam PRNGs buruk. Perangkat lunak yang cenderung kita gunakan saat ini adalah PractRand, dan pengujiannya didokumentasikan dengan ringan di sini . Makalah terbaik untuk dibaca mungkin adalah yang untuk TestU01 , rangkaian pengujian standar emas sebelumnya. Panduan Pengguna memiliki detail lebih lanjut tentang pengujian.

Saya mohon maaf jika ini kedengarannya aneh (meskipun pasti akan menunjuk), tetapi juga tulus: Saya berharap dapat melihat hasil implementasi, analisis, tolok ukur, dan PractRand di situs web Anda atau di arXiv. Kami adalah praktisi (dengan informasi yang masuk akal) di sini, bukan peneliti PRNG, dan tidak diperlengkapi dengan baik untuk melaksanakan saran ini. Saya dapat melihat pengertiannya, tetapi mengingat kendala lain pada waktu pribadi saya, saya tidak memiliki kecenderungan untuk menghabiskan upaya untuk mengambil ini dari saran ke implementasi dan analisis. Jika Anda menanggapi saran ini secara berlebihan, kami membutuhkan peneliti PRNG untuk melakukan pekerjaan itu. Jika Anda benar-benar menyampaikan saran ini kepada orang lain, gunakan situs web Anda.

Saya sangat memahami sudut pandang Anda. Kode dan benchmark telah berada di bagian bawah halaman yang mengomentari masalah PCG (http://prng.di.unimi.it/pcg.php) sejak beberapa tahun dengan nama LCG128Mix. Dibutuhkan 2.16ns pada perangkat keras saya, Intel (R) Core (TM) i7-7700 CPU @ 3.60GHz, dengan gcc 9.2.1 dan -fno-move-loop-invariants -fno-unroll-loops.

Kode ini sangat sederhana — ini menggabungkan LCG standar dengan fungsi pencampuran standar (finalizer MurmurHash3 yang ditingkatkan dari Stafford). Saya sedikit memodifikasinya agar memiliki konstanta yang dapat diprogram:

    #include <stdint.h>
    __uint128_t x; // state
    __uint64_t c;  // stream constant (odd)

    uint64_t inline next(void) {
        // Put in z the top bits of state
        uint64_t z = x >> 64;
        // Update LCG state
        x = x * ((__uint128_t)1 << 64 ^ 0xd605bbb58c8abbfd) + c;
        // Compute mix
        z = (z ^ (z >> 30)) * 0xbf58476d1ce4e5b9;
        z = (z ^ (z >> 27)) * 0x94d049bb133111eb;
        return z ^ (z >> 31);
    }

Seperti yang saya jelaskan sebelumnya, konstanta 65-bit jauh lebih baik daripada konstanta 64-bit sebagai pengali, karena masalah teoretis pengali lebih kecil dari akar kuadrat modulus.

Jika Anda tertarik dengan desain yang lebih berprinsip, saya akan menjalankan tes PractRand. Anda harus mempertimbangkan, bagaimanapun, bahwa fungsi pencampuran ini menghasilkan generator yang sangat baik, SplitMix, bahkan dengan generator dasar yang jauh lebih lemah (itu hanya aditif), dan dengan status yang lebih kecil (64 bit). Jadi itu hanya akan menjadi "lebih baik" dari SplitMix, yang melewati PractRand pada 32TB.

Dan generator yang mendasarinya adalah LCG, jadi Anda memiliki semua lonceng dan peluit yang biasa dari tahun 60-an: lompatan, jarak, dll. Tetapi Anda juga memiliki jaminan statistik bahwa setiap bit hasilnya bergantung pada setiap bit 64 bit yang lebih tinggi. negara.

Jika Anda ingin melakukan benchmark terhadap beberapa generator lain, atau menggunakan kompiler lain, beri tahu saya.

Tapi, tolong, dengan cara yang sama tulusnya: hanya jika Anda benar-benar tertarik mempertimbangkan desain "berdiri di atas bahu raksasa" hanya dengan menggunakan komponen standar. Ada kendala pribadi pada waktu saya juga, dan saya dengan senang hati berkontribusi, tetapi saya ingin menghindari menghabiskan waktu pada generator yang tidak memiliki kesempatan untuk dipertimbangkan.

BTW, untuk memberikan ukuran yang lebih nyata tentang bagaimana meningkatkan kualitas pengali yang terlibat, saya menghitung skor spektral, dari f₂ ke f₈, dari pengali 64-bit saat ini yang digunakan oleh PCG DXS dan beberapa alternatif.

Skor spektral adalah cara standar untuk menilai kebaikan pengganda. 0 buruk, 1 bagus sekali. Setiap skor menggambarkan seberapa baik distribusi pasangan, tripel, 4-tuple, dll. Dalam output.

Ketujuh angka ini dapat dilanjutkan dalam pengukuran klasik, minimum, atau pengukuran tertimbang (skor pertama, ditambah yang kedua dibagi dua, dll., Dinormalisasi), untuk membuat skor pertama lebih penting, seperti yang disarankan oleh Knuth dalam TAoCP , dan ini adalah ukuran minimum dan tertimbang untuk pengali saat ini:

0xda942042e4dd58b  0.633  0.778

Ada konstanta 64-bit yang jauh lebih baik dari itu:

0xff37f1f758180525  0.761  0.875

Jika Anda menggunakan 65 bit, pada dasarnya dengan kecepatan yang sama (setidaknya, untuk LCG128Mix adalah kecepatan yang sama) Anda mendapatkan ukuran tertimbang yang lebih baik:

0x1d605bbb58c8abbfd  0.761  0.899

Alasannya adalah bahwa pengganda 64-bit memiliki batas intrinsik untuk skor f₂ mereka (≤0.93), yang menurut Knuth adalah yang paling relevan:

0xda942042e4dd58b5  0.795
0xff37f1f758180525  0.928
0x1d605bbb58c8abbfd  0.992

Jadi pengali pertama memiliki skor f₂ biasa-biasa saja. Pengganda kedua mendekati optimal untuk pengganda 64-bit. Pengganda 65-bit tidak memiliki batasan ini dan memiliki skor yang mendekati 1, yang terbaik secara umum.

Berikut skornya:

 0xda942042e4dd58b5  0.794572 0.809219 0.911528 0.730396 0.678620 0.632688 0.639625
 0xff37f1f758180525  0.927764 0.913983 0.828210 0.864840 0.775314 0.761406 0.763689 
0x1d605bbb58c8abbfd  0.991889 0.907938 0.830964 0.837980 0.780378 0.797464 0.761493

Anda dapat menghitung ulang skor ini atau mencari pengganda Anda sendiri dengan kode Guy Steele dan saya distribusikan: https://github.com/vigna/CPRNG . Pengganda yang lebih baik diambil dari kertas terkait.

PCG mungkin akan menjadi prng default yang bagus untuk numpy, tetapi menurut saya ini tidak akan bertahan dalam ujian waktu, karena ada cara yang lebih menjanjikan, tetapi kurang teruji untuk melakukan ini. Saya mengusulkan satu hal berikut ini.

SFC64 setengah kacau adalah salah satu generator tercepat secara statistik dengan periode minumum besar yang wajar. SFC64 tidak memiliki fungsi lompat, tetapi _tanpa overhead kecepatan dapat diperpanjang untuk mendukung aliran unik yang dijamin 2 ^ 63_. Cukup tambahkan urutan Weyl dengan konstanta aditif pilihan pengguna k (harus ganjil), alih-alih hanya menambah penghitung satu. Setiap k ganjil menghasilkan periode penuh yang unik. Diperlukan tambahan 64-bit status untuk menahan konstanta Weyl:

typedef struct {uint64_t a, b, c, w, k;} sfcw64_t; // k = stream

static inline uint64_t sfcw64_next(sfcw64_t* s) {
    enum {LROT = 24, RSHIFT = 11, LSHIFT = 3};
    const uint64_t out = s->a + s->b + (s->w += s->k);
    s->a = s->b ^ (s->b >> RSHIFT);
    s->b = s->c + (s->c << LSHIFT);
    s->c = ((s->c << LROT) | (s->c >> (64 - LROT))) + out;
    return out;
}

Status 320 bit terkadang tidak diinginkan, jadi saya mencoba memerasnya untuk menggunakan 256 bit lagi. Perhatikan juga fungsi output yang diubah, yang lebih baik menggunakan urutan Weyl untuk pencampuran bit. Ini menggunakan 128/128 bit keadaan kacau / terstruktur, yang tampaknya mencapai keseimbangan yang baik:
/ EDIT: menghapus rotl64 () dari output func + pembersihan, 6 Agustus:

typedef struct {uint64_t a, b, w, k;} tylo64_t;

static inline uint64_t tylo64_next(tylo64_t* s) {
    enum {LROT = 24, RSHIFT = 11, LSHIFT = 3};
    const uint64_t b = s->b, out = s->a ^ (s->w += s->k);
    s->a = (b + (b << LSHIFT)) ^ (b >> RSHIFT);
    s->b = ((b << LROT) | (b >> (64 - LROT))) + out;
    return out;
}

Ini saat ini telah lulus 4 TB dalam pengujian PractRand tanpa anomali, dan saya secara singkat menjalankan uji bobot Hamming Vigna tanpa masalah sejauh ini (meskipun, lulus tes ini tidak ada jaminan untuk keluaran acak yang hampir benar, melainkan tes apakah prng tersebut cacat atau tidak ).

Catatan: seharusnya secara statistik merupakan keuntungan menggunakan konstanta Weyl acak (unik) dengan kira-kira 50% dari kumpulan bit, tetapi hanya pengujian atau analisis lebih lanjut yang akan mengungkapkan seberapa signifikan hal ini.

/ Editan: pembersihan.

@ tylo-work SFC64 sudah ada di NumPy, bersama dengan Philox, ini tentang generator default.

Oke, saya tidak tahu persis mana yang diterapkan, jadi ini hanya tentang memilih yang paling cocok secara keseluruhan dari itu? Cukup adil, dan terima kasih telah mengklarifikasi.

Saya akan mencoba menguji generator yang saya usulkan secara ekstensif untuk melihat bagaimana ia menumpuk dengan yang lain, dan sejauh ini terlihat sangat bagus dalam hal kecepatan, kualitas keluaran, kesederhanaan / ukuran / portabilitas, dan untuk penggunaan paralel besar-besaran. Tapi saya akan senang jika orang lain mengujinya juga.

Saya tidak berpikir kami membuka kembali diskusi tentang PRNG default dari awal. Kami memiliki masalah yang sangat spesifik dengan PRNG kami saat ini dan sedang mencari varian yang tersedia dan terkait erat yang menangani masalah khusus tersebut. Salah satu kekhawatiran kami adalah bahwa PRNG default saat ini memperlihatkan fitur-fitur tertentu dari PRNG, seperti jumpability, yang harus tetap diekspos oleh varian yang menggantikannya. SFC64 (baik milik kami maupun milik Anda) tidak memiliki fitur itu.

Ada kemungkinan bahwa @bashtage bersedia menerima PR untuk randomgen guna menambahkan varian Weyl-stream Anda dari SFC64.

@ tylo-work Jika Anda tertarik dengan eksekusi paralel, Anda mungkin ingin melihat implementasi SeedSequence NumPy.

Saya tidak berpikir kami membuka kembali diskusi tentang PRNG default dari awal. Kami memiliki masalah yang sangat spesifik dengan PRNG kami saat ini dan sedang mencari varian yang tersedia dan terkait erat yang menangani masalah khusus tersebut.

Dengan asumsi Anda menginginkan sesuatu yang mirip PCG-DXS, ada perbaikan lebih lanjut yang dapat Anda lakukan hanya dengan konstanta yang lebih baik (dan perlambatan yang sangat kecil). Misalnya, PCG-DXS akan segera gagal dalam dua jenis pengujian yang berbeda pada dua interleave, urutan berkorelasi dengan status 112 bit yang sama lebih rendah:

rng=PCGDXS_int112, seed=0x4d198651
length= 128 gigabytes (2^37 bytes), time= 5700 seconds
  Test Name                         Raw       Processed     Evaluation
  [Low1/64]TMFn(0+2):wl             R= +57.3  p~=   2e-27     FAIL !!
  [Low8/64]FPF-14+6/64:(1,14-0)     R= +17.5  p =  8.0e-16    FAIL
  [other failures in the same tests]
  ...and 1893 test result(s) without anomalies

Perhatikan bahwa kita hanya berbicara tentang ≈65536 urutan berkorelasi — tidak ada yang perlu ditakuti.

Namun Anda dapat meningkatkan generator dengan memilih pengganda yang lebih baik, seperti 0x1d605bbb58c8abbfd, dan mixer yang lebih baik, seperti 0x9e3779b97f4a7c15. Angka pertama adalah pengali 65-bit yang memiliki skor spektral jauh lebih baik. Angka kedua hanyalah rasio emas dalam representasi titik tetap 64-bit, dan ini dikenal memiliki properti pencampuran yang bagus (lihat Knuth TAoCP tentang pencirian multiplikatif); misalnya, digunakan oleh pustaka Koleksi Eclipse untuk mencampur kode hash.

Akibatnya, Anda gagal FPF hanya untuk jumlah data yang sama:

rng=PCG65-DXSϕ_int112, seed=0x4d198651
length= 128 gigabytes (2^37 bytes), time= 5014 seconds
  Test Name                         Raw       Processed     Evaluation
  [Low8/64]FPF-14+6/64:(0,14-0)     R= +16.1  p =  1.5e-14    FAIL
  [other failures in the same test]
  ...and 1892 test result(s) without anomalies

Faktanya, jika kita melangkah lebih jauh pada 2TB PCG-DXS gagal _tiga_ jenis tes untuk interleave yang sama, hubungan selanjutnya:

rng=PCGDXS_int112, seed=0x4d198651
length= 2 terabytes (2^41 bytes), time= 53962 seconds
  Test Name                         Raw       Processed     Evaluation
  [Low1/32]TMFn(0+0):wl             R= +50.2  p~=   4e-23     FAIL !!
  [Low8/64]FPF-14+6/64:(1,14-0)     R=+291.1  p =  4.7e-269   FAIL !!!!!!
  [Low8/64]Gap-16:B                 R= +19.5  p =  1.4e-16    FAIL !
  [other failures in the same tests]
  ...and 2153 test result(s) without anomalies

sedangkan PCG65-DXSϕ masih gagal hanya FPF:

rng=PCGDXS65ϕ_int112, seed=0x4d198651
length= 2 terabytes (2^41 bytes), time= 55280 seconds
  Test Name                         Raw       Processed     Evaluation
  [Low8/64]FPF-14+6/64:(0,14-0)     R=+232.1  p =  2.0e-214   FAIL !!!!!!
  [other failures in the same test]
  ...and 2153 test result(s) without anomalies

Cepat atau lambat, tentu saja, PCG65-DXSϕ juga akan gagal Gap dan TMFn. Tetapi Anda perlu melihat lebih banyak keluaran daripada dengan PCG-DXS.

Ini adalah kode lengkap untuk PCG65-DXSϕ, yang merupakan PCG-DXS dengan konstanta yang lebih baik:

#include <stdint.h>

__uint128_t x; // State
uint64_t c; // Additive constant

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

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

static uint64_t inline next(void) {
    __uint128_t old_x = x;
    x = x *  ((__uint128_t)1 << 64 ^ 0xd605bbb58c8abbfd) + c;
    return output(old_x);
}

Perlambatan marjinal disebabkan oleh instruksi penambahan (disebabkan oleh pengali 65-bit), dan memiliki dua konstanta 64-bit untuk dimuat.

Saya tidak mendukung generator semacam ini secara umum, tetapi PCG65-DXSϕ jauh lebih baik daripada PCG-DXS dalam menyembunyikan korelasi.

@Vigna , FYI, saya juga melakukan beberapa pengujian interleaving, dan melihat bahwa xoshiro256 ** gagal agak cepat saat membuat 128 aliran interleave atau lebih. Dengan 256 itu gagal dengan cepat. Inti dari pengujian ini adalah untuk memeriksa seberapa baik PRNG berperilaku ketika setiap aliran diinisialisasi dengan beberapa dependensi linier. Pada dasarnya, status diinisialisasi menjadi s[0]=s[1]=s[2]=s[3] = k1 + stream*k2 . Kemudian 12 keluaran dilewati, yang pada dasarnya adalah cara sfc64 diinisialisasi.

Saya menyadari, ini bukan inisialisasi yang disarankan untuk xoshiro, tetapi masih menarik - dan sedikit mengkhawatirkan - bahwa pengujian untuk xoshiro tampaknya baik-baik saja dengan beberapa aliran interleaving, tetapi gagal dengan banyak aliran.

seed: 1591888413
RNG_test using PractRand version 0.95
RNG = RNG_stdin64, seed = unknown
test set = core, folding = standard (64 bit)
...
rng=RNG_stdin64, seed=unknown
length= 2 gigabytes (2^31 bytes), time= 29.6 seconds
  Test Name                         Raw       Processed     Evaluation
  [Low1/64]FPF-14+6/16:(1,14-1)     R=  +7.2  p =  3.7e-6   unusual
  [Low1/64]FPF-14+6/16:all          R=  +9.6  p =  1.8e-8   very suspicious
  ...and 261 test result(s) without anomalies

rng=RNG_stdin64, seed=unknown
length= 4 gigabytes (2^32 bytes), time= 55.5 seconds
  Test Name                         Raw       Processed     Evaluation
  [Low1/64]FPF-14+6/16:(0,14-0)     R= +13.4  p =  4.7e-12   VERY SUSPICIOUS
  [Low1/64]FPF-14+6/16:(1,14-0)     R=  +9.4  p =  2.6e-8   suspicious
  [Low1/64]FPF-14+6/16:(2,14-1)     R=  +7.7  p =  1.3e-6   unusual
  [Low1/64]FPF-14+6/16:all          R= +17.4  p =  8.8e-16    FAIL !
  ...and 275 test result(s) without anomalies

Saya juga mencoba melemahkan inisialisasi untuk SFC64 dan TYLO64 untuk melewatkan hanya 2 keluaran, namun mereka masih tampak oke.
Mengenai kinerja: xoshiro256 ** berjalan 33% lebih lambat di komputer saya daripada dua lainnya. TYLO64 hanya memperbarui 196 bit vars negara. Berikut program tesnya:

int main()
{
    //FILE* f = freopen(NULL, "wb", stdout);  // Only necessary on Windows, but harmless.
    enum {THREADS = 256};
    uint64_t seed = 1591888413; // <- e.g. this fails. // (uint64_t) time(NULL); 
    fprintf(stderr, "seed: %lu\n", seed);

    static tylo64_t tyl[THREADS];
    static sfc64_t sfc[THREADS];
    static uint64_t xo[THREADS][4];

    for (size_t i = 0; i < THREADS; ++i) {
    tyl[i] = tylo64_seed(seed + (12839732 * i), 19287319823 * i);
    sfc[i] = sfc64_seed(seed + (12839732 * i));
    xo[i][0] = xo[i][1] = xo[i][2] = xo[i][3] = seed + (12839732 * i);
    for (int j=0; j<12; ++j) xoshiro256starstar_rand(xo[i]);
    }
    static uint64_t buffer[THREADS];
    size_t n = 1024 * 1024 * 256 / THREADS;

    while (1/*n--*/) {
        for (int i=0; i<THREADS; ++i) {
        //buffer[i] = tylo64_rand(&tyl[i]);
        //buffer[i] = sfc64_rand(&sfc[i]);
            buffer[i] = xoshiro256starstar_rand(xo[i]);
        }
        fwrite((void*) buffer, sizeof(buffer[0]), THREADS, stdout);
    }
    return 0;
}

Saya akan menyertakan beberapa kode tajuk yang relevan:

typedef struct {uint64_t a, b, w, k;} tylo64_t; // k = stream

static inline uint64_t tylo64_rand(tylo64_t* s) {
    enum {LROT = 24, RSHIFT = 11, LSHIFT = 3};
    const uint64_t b = s->b, w = s->w, out = (s->a + w) ^ (s->w += s->k);
    s->a = (b + (b << LSHIFT)) ^ (b >> RSHIFT);
    s->b = ((b << LROT) | (b >> (64 - LROT))) + out;
    return out;
}

/* stream in range [0, 2^63) */
static inline tylo64_t tylo64_seed(const uint64_t seed, const uint64_t stream) {
    tylo64_t state = {seed, seed, seed, (stream << 1) | 1};
    for (int i = 0; i < 12; ++i) tylo64_rand(&state);
    return state;
}

static inline uint64_t rotl(const uint64_t x, int k) {
    return (x << k) | (x >> (64 - k));
}
static inline uint64_t xoshiro256starstar_rand(uint64_t* s) {
    const uint64_t result = rotl(s[1] * 5, 7) * 9;
    const uint64_t t = s[1] << 17;
    s[2] ^= s[0];
    s[3] ^= s[1];
    s[1] ^= s[2];
    s[0] ^= s[3];
    s[2] ^= t;
    s[3] = rotl(s[3], 45);
    return result;
}

@ tylo-work Saya menghargai analisisnya, tetapi saya benar-benar membutuhkan masalah ini agar tetap fokus. Jika Anda ingin melanjutkan baris diskusi tersebut, saya mendorong Anda untuk memposting pekerjaan Anda di repo Github Anda sendiri, dan membuat satu posting lagi di sini dengan mengundang orang ke sini. Semua orang, tolong tanggapi di sana. Terima kasih atas kerja sama anda.

@imneme @rkern Waktu hampir habis untuk rilis 1,19.

@rkern Sepertinya PCG64DXSM tidak akan berhasil mencapai 1.19.0, saya akan merilisnya akhir pekan ini. Jika Anda dapat menulis catatan tentang kebijakan perubahan kami / perubahan mendatang yang Anda sebutkan di atas, saya akan sangat menghargainya.

Maaf, saya telah berurusan dengan beberapa hal lain yang tidak terkait. Berdasarkan diskusi kami, menurut saya penundaan kecil bukanlah masalah besar, karena PCG64DXSM direncanakan sebagai opsi alternatif, bukan default baru (setidaknya untuk saat ini).

Sekarang 1,20 telah dimulai, apakah sudah waktunya untuk mengunjungi kembali ini dan pindah ke DXSM?

Kami masih memiliki waktu untuk melakukan pemindahan sebelum bercabang, tetapi mungkin bagus untuk memulainya dalam minggu depan atau lebih. @bashtage Saya rasa Anda memiliki PCG64DXSM siap digunakan dan ini terutama membutuhkan keputusan untuk membalik tombol pada aliran default?

Dari apa yang dilihatnya, sepertinya kita hanya perlu melakukan ini untuk 1,20 jika kita memilikinya tersedia.

IIRC, kami menunggu referensi yang bisa ditautkan. Tetapi jika orang nomor acak senang dengan perubahan itu, kita harus menggunakannya. Apakah kami memerlukan kode khusus untuk windows?

Ini hanyalah konstanta yang berbeda dan fungsi pengacakan yang berbeda. Tidak ada yang lebih baru dari apa yang ditulis @rkern untuk implementasi PCG64 asli di Windows. Saya pikir keputusannya adalah memiliki PCG64DXSM yang sepenuhnya berdiri sendiri daripada berbagi beberapa kode (untuk kinerja).

Mungkin masuk akal untuk memulai dari cabang WIP rkern .

Saya berkata bahwa saya akan menulis beberapa posting blog tentang itu, yang menurut saya diinginkan @rkern , tetapi saya telah memperhatikan beberapa masalah lain dan itu belum terjadi (maaf). Sementara itu, permutasi DXSM telah diuji dan terus tampak seperti peningkatan dari aslinya. Dari komentar sebelumnya di utas, saya pikir @rkern mungkin menyukai permutasi keluaran yang lebih kuat, tetapi melakukannya akan membuat Anda

Apakah halaman ini membantu?
0 / 5 - 0 peringkat