Numpy: تنفيذ PCG المقدم من Numpy له ارتباط ذاتي كبير وخطير

تم إنشاؤها على ٢٠ مايو ٢٠٢٠  ·  104تعليقات  ·  مصدر: numpy/numpy

يحتوي مولد PCG الذي تستخدمه Numpy على قدر كبير من الارتباط الذاتي. أي أنه لكل تسلسل تم إنشاؤه من بذرة يوجد عدد كبير من المتواليات المترابطة وغير المتداخلة التي تبدأ من البذور الأخرى. أعني بكلمة "مرتبطة" أن تشذير تسلسلين من هذا القبيل واختبار النتيجة تحصل على إخفاقات لم تظهر في كل تسلسل على حدة.

احتمالية حصول مولدين من مجموعة كبيرة من المحطات على اثنين من هذه المتواليات غير قابلة للتجاهل. لماذا يحدث هذا من وجهة نظر رياضية معروف جيدًا ولكن يتم شرحه بالتفصيل هنا: http://prng.di.unimi.it/pcg.pgp (انظر "النتائج داخل نفس المولد").

لإظهار هذه المشكلة مباشرة ، كتبت برنامج C البسيط هذا بإعادة استخدام كود Numpy: http://prng.di.unimi.it/intpcgnumpy.c . يأخذ البرنامج حالتين من 128 بت من مولدين (مع نفس LCG ثابت أو "تيار") في شكل بتات عالية ومنخفضة ، ويقوم بتشذير إخراجهم وكتابته في شكل ثنائي. بمجرد إرساله عبر PractRand ، يجب ألا نرى أي فشل إحصائي ، حيث يجب أن يكون المساران مستقلين. ولكن إذا حاولت البدء من حالتين بنفس 64 بتًا أقل ، فستحصل على:

./intpcgnumpy 0x596d84dfefec2fc7 0x6b79f81ab9f3e37b 0x8d7deae980a64ab0 0x6b79f81ab9f3e37b | stdbuf -oL ~ / svn / c / xorshift / Practicerand / RNG_test stdin -tf 2 -te 1 -tlmaxonly-multithreaded
RNG_test باستخدام الإصدار PractRand 0.94
RNG = RNG_stdin ، البذرة = غير معروف
مجموعة الاختبار = ممتدة ، قابلة للطي = إضافية

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

يمكنك أيضًا الانتقال إلى مستوى أقل - تحتاج فقط إلى نفس 58 وحدة بت أقل:

./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

لاحظ أنه للحصول على احتمال أكبر بنسبة 50٪ أن يبدأ مولدان من بذرتين مترابطتين (يتم اختيارهما عشوائيًا) ، فأنت تحتاج فقط إلى حوالي نصف مليون مولدات تبدأ عشوائيًا (مفارقة عيد الميلاد). وإذا كنت تفكر في احتمال أنها لا تبدأ بالضبط من نفس الحالة ، ولكن لها تسلسلات ارتباط متداخلة كبيرة ، فأنت بحاجة إلى أقل من ذلك بكثير.

فإن أي مولد معقول من الأدب لا تتصرف مثل ذلك. يمكنك اختيار أي حالتين ابتدائيتين من MRG32k3a و SFC64 و CMWC و xoshiro256 ++ وما إلى ذلك ، وما دمت تقوم بإنشاء تسلسلات غير متداخلة فلن ترى حالات الفشل أعلاه. يعد هذا عيبًا رئيسيًا يمكن أن يظهر عندما يستخدم عدد من الأجهزة المولد ويفترض المرء (كما ينبغي أن يكون) أن هذه التسلسلات يجب ألا تظهر ارتباطًا. يمكن أن يؤدي الارتباط إلى سلوك غير مرغوب فيه يصعب اكتشافه.

يرجى على الأقل توثيق في مكان ما أنه لا ينبغي استخدام المولد في محطات متعددة أو في بيئة متوازية للغاية.

يمكن أن يحدث الشيء نفسه مع "تدفقات" مختلفة ، حيث أن التتابعات التي تم إنشاؤها بواسطة LCG عن طريق تغيير الثابت الإضافي هي جميعها نفس النمط تغيير في الإشارة وثابت مضاف. يمكنك مشاهدة بعض المناقشة هنا: https://github.com/rust-random/rand/issues/907 ومناقشة رياضية كاملة للمشكلة هنا: https://arxiv.org/abs/2001.05304 .

numpy.random

ال 104 كومينتر

imneme ، bashtage ، rkern ستكون السلطات هنا ، لكنني أعتقد أننا تجاوزنا هذا الأمر ولهذا فضلنا واجهة SeedSequence.spawn على jumped واحد. على سبيل المثال ، كان هناك هذا النقاش عندما كنا نناقش API. يرجى مراجعة النصائح هنا https://numpy.org/devdocs/reference/random/parallel.html واقترح التحسينات حسب الحاجة.

mattip هذا ليس له علاقة بالقفز.

أعتقد من الناحية العملية أنه من الصعب إجراء تغييرات بالجملة ، على الرغم من أن التوثيق المحسن دائمًا فكرة جيدة.

من المحتمل أن أوصي بـ AESCounter لأي شخص لديه AES-NI أو SPECK128 لأي شخص بدون إعدادات متوازية للغاية.

يمكن أن يحدث الشيء نفسه مع "تدفقات" مختلفة ، حيث أن التتابعات التي تم إنشاؤها بواسطة LCG عن طريق تغيير الثابت الإضافي هي جميعها نفس النمط تغيير في الإشارة وثابت مضاف.

هل يمكنك تحديد هذا؟ يمكنني تكرار حالات الفشل باستخدام نفس الزيادة ، لكننا نزرع الزيادة بالإضافة إلى الحالة ، ولم ألاحظ بعد فشلًا بزيادتين عشوائيتين مختلفتين. إذا كان يجب أيضًا إنشاء الزيادات بعناية ، فسيؤثر ذلك على تكرار تصادم عيد الميلاد العملي.

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

حسنًا ، سأحاول مرة أخرى.

لا توجد تدفقات متعددة في LCG بمعامل قوة 2. صدقه الكثيرون في الأيام الأولى ، وهناك حتى أوراق قديمة طويلة تدعي أنها تقوم بأشياء مثيرة للاهتمام مع تلك "التدفقات" ، ولكن من المعروف منذ عقود أن المدارات التي تحصل عليها من خلال تغيير الثوابت هي كلها نفس الطريقة مادة مضافة ثابت وربما علامة التغيير_. أبعد ما يمكنني تتبعه هو

مارك ج.دورست ، باستخدام المولدات المتطابقة الخطية لتوليد الأرقام العشوائية المتوازية ،
1989 إجراءات مؤتمر المحاكاة الشتوية ، مطبعة IEEE ، 1989 ، ص 462-466.

لذلك ، كتبت برنامجًا آخر http://prng.di.unimi.it/corrpcgnumpy.c يمكنك من خلاله تعيين:

  • حالة أولية لـ PRNG.
  • حالة أولية لـ PRNG آخر.
  • "تيار ثابت" تعسفي لـ PRNG الأول.
  • "ثابت تيار" تعسفي لـ PRNG الثاني (يجب أن يكون كلاهما زوجي أو كلاهما فردي ؛ يمكن إزالة هذا التقييد ببعض التلاعب الإضافي).
  • عدد ثابت من البتات السفلية التي سنقوم بتعيينها بشكل عكسي في PRNG الثاني ، بشكل أساسي بحيث يبدأ بنفس البتات من أول PRNG. سيتم أخذ باقي البتات من الحالة الأولية لـ PRNG الثانية التي قدمتها.

إذن هذا _ بالضبط _ إعداد البرنامج الأول ، لكن يمكنك أيضًا اختيار الثوابت.

./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

لذلك هناك _ على الأقل 2 ^ 72 مترابط لاحقًا ، بغض النظر عن كيفية اختيار "ثوابت التدفق" ، تمامًا كما في الحالة الثابتة نفسها.

وقد أعطينا قدرًا سخيفًا من الركود للمولد: حتى لو كنت تستخدم حالة قبلها أو بعدها قليلاً ، فسيظهر الارتباط على أي حال بدلاً من نقطة البداية الدقيقة التي أحسبها. يمكنك تعديل البرنامج بسهولة باستخدام معلمة إضافية للقيام بذلك.

أكرر ، مرة أخرى: لا يوجد مولد حديث موجود من الأدبيات العلمية لديه هذا السلوك السيئ (بالطبع ، قوة 2 LCG لديها هذا السلوك ، ولكن بحق الله ، هذا _ ليس مولدًا حديثًا).

تم تناول انتقادات Sabastiano لـ PCG في منشور المدونة هذا من 2018.

النسخة القصيرة هي أنه إذا سمح لك بابتكار بذور معينة ، فيمكنك إظهار سلوك "سيء المظهر" من أي PRNG تقريبًا. على الرغم من ادعائه بأن PCG فريد إلى حد ما ، فإن PCG هو في الواقع تقليدي جدًا - تدفقات PCG ليست أسوأ من ، على سبيل المثال ، SplitMix's ، وهو PRNG آخر مستخدم على نطاق واسع.

هذا خطأ تماما. لإثبات أنني مخطئ ، أظهر تسلسلين مرتبطين غير متراكبين من MRG32k3a أو xoshiro256 ++.

لم أقل عدم تداخل. أرني اختبارًا متاحًا حاليًا لـ xoshiro256 ++. أن البذور اثنين تجنب التداخل.

في المقابل ، لدي اختبار PCG يوضح أن "الارتباطات" التي أظهرتها هي في الأساس شكل من أشكال التداخل.

لا يمكنني محاربة FUD مثل "بشكل أساسي" و "نموذج" ، لكنني قمت بتعديل http://prng.di.unimi.it/intpcgnumpy.c بحيث يتكرر في البداية كل PRNG 10 مليارات مرة ، ويخرج مع وجود خطأ رسالة إذا كان التسلسل الذي تم إنشاؤه يتجاوز الحالة الأولية لـ PRNG الآخر. هذا يضمن أن أول 160 جيجا بايت من البيانات في Practrand تأتي من تسلسلات غير متداخلة:

./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

تحتوي بيانات التهيئة الخاصة هذه على 56 بتًا ثابتًا أقل فقط ، لذلك يمكن للمرء إنشاء 2 ^ 72 تسلسلًا مترابطًا عن طريق قلب البتات الأعلى. تحدث حالات الفشل الإحصائي بعد 64 جيجابايت فقط من البيانات ، مما يدل على أن التداخلات ليست مسؤولة عن الارتباط. من الممكن أن يحدث التداخل مع الخيارات المستهدفة الأخرى قبل 64 جيجابايت بالطبع - وهذا مثال محدد. ولكن من السهل الآن التحقق من أن التداخل ليس هو المشكلة - فالمولد لديه الكثير من الارتباط الداخلي غير المرغوب فيه.

يرجى احترام مدونة السلوك . حاول أن تجعل تعليقاتك متناسقة مع التوجيهات بأن تكون "متعاطفًا ، ومرحبًا ، وودودًا ، وصبورًا" و "توخي الحذر في الكلمات التي نختارها. نحن حريصون ومحترمون في تواصلنا".

لم أقل عدم تداخل. أرني اختبارًا متاحًا حاليًا لـ xoshiro256 ++. أن البذور اثنين تجنب التداخل.

حسنًا ، إنه أمر تافه: حدد طول الدفق ، وكرر ، وتحقق من أن الدفقين لا يعبران الحالة الأولية. إنه نفس الكود الذي استخدمته لإظهار تدفقات PCG المرتبطة في البرنامج http://prng.di.unimi.it/intpcgnumpy.c لا تتداخل.

على الرغم من ادعائه بأن PCG فريد إلى حد ما ، فإن PCG هو في الواقع تقليدي جدًا - تدفقات PCG ليست أسوأ من ، على سبيل المثال ، SplitMix's ، وهو PRNG آخر مستخدم على نطاق واسع.

IMHO ، الارتباط الذاتي داخل PCG أسوأ بكثير. لا توجد نتيجة لمولد المواد المضافة الكامن وراء مثيل SplitMix مماثل لنتائج Durst الدرامية لعام 1989 حول LCGs.

لكن المشاكل الخفيفة جدًا في SplitMix معروفة ، وسيوفر JEP 356 فئة جديدة من المولدات القابلة للتقسيم ، LXM ، في محاولة لمعالجة هذه المشكلات. لقد حان الوقت للمضي قدمًا واستبدال PCG أيضًا بشيء أقل عيوبًا.

المشكلة الأساسية معروفة لكلا المولدين ، وهي ترجع إلى عدم وجود مزيج الدولة. إذا قمت بتغيير البت _k_ من حالة أحد تلك المولدات ، فلن ينتشر التغيير أبدًا تحت البت _k_. لا يحدث هذا في LCGs ذات المعامل الأولي ، في مولدات F₂ الخطية ، ومولدات CMWC ، إلخ. تحاول جميع المولدات الأخرى مزج حالتها بأسرع ما يمكن وبأكبر قدر ممكن.

معادلة مشاكل PCG و SplitMix هو خداع أحمر. يحتوي SplitMix على منشئ أساسي بسيط للغاية ، مجرد مادة مضافة ، ولكن علاوة على ذلك ، هناك وظيفة تخليط قوية جدًا: إنها أداة إنهاء 64 بت من Appleby لوظيفة التجزئة MurmurHash3 ، والتي تم استخدامها على نطاق واسع في عدد من السياقات و تم تحسينه بواسطة Stafford (http://zimbry.blogspot.com/2011/09/better-bit-mixing-improving-on.html). تم تدريب ثوابت الوظيفة على أن يكون لها خصائص جليدية محددة وقابلة للقياس. حتى التغييرات في عدد صغير من البتات تميل إلى الانتشار على كل المخرجات. بمعنى آخر ، يقف SplitMix على كتف العمالقة.

على العكس من ذلك ، فإن مولدات PCG الأساسية لـ LCG لديها نفس مشاكل عدم الخلط ، لكن وظائف التخليط هي مجرد سلسلة بسيطة من العمليات الحسابية والمنطقية التي تم تجميعها من قبل المؤلف دون أي ضمان نظري أو إحصائي. إذا تم ابتكارها مع مراعاة حقيقة أن جميع متواليات LCG الأساسي هي نفس النموذج الثابت الإضافي وربما تغير علامة ، لكان من الممكن معالجة المشكلة.

لكن لم يكن لدى المؤلف أي فكرة عن أن التسلسلات يمكن اشتقاقها بسهولة من أخرى. يمكن رؤية ذلك بسهولة من هذا البيان في القسم 4.2.3 من التقرير الفني لـ PCG (https://www.pcg-random.org/pdf/hmc-cs-2014-0905.pdf):

"كل اختيار لـ _c_ ينتج عنه تسلسل مختلف من الأرقام ليس له أي من أزواج المخرجات المتتالية المشتركة مع تسلسل آخر."

يؤخذ هذا كدليل على أن التسلسلات مختلفة ، أي أن LCG الأساسي يوفر تدفقات متعددة. لا تظهر النتائج السلبية لدورست عام 1989 حول هذا الموضوع في أي مكان في الورقة. كما أشرت سابقًا ، من خلال هذه النتائج ، تكون كل هذه التسلسلات هي نفسها ، وهي ثابتة مضافة وربما تغير إشارة (بالنسبة إلى LCGs مع معامل قوة 2 بأقصى قدر من الفعالية ، كما يحدث في PCG).

أنا متأكد من أن عدم الاستشهاد بنتائج Durst يعد خطأً حسنًا ، ولكن المشكلة هي أنه بمجرد اقتناعك بأن LCG الأساسي الذي تستخدمه يوفر "تدفقات" "مختلفة" بمعنى ما ، وعندما لا تكون كذلك ، ينتهي بك الأمر مع مولد مثل PCG حيث يوجد 2 ^ 72 متتالية غير متداخلة ومرتبطة ، حتى لو قمت بتغيير "الدفق".

شكرا لكم جميعا على آرائكم. في الوقت الحالي ، لست مهتمًا بالأحكام الثنائية مثل "PCG جيد / سيء". الرجاء استخدام المنتديات الخاصة بك لمثل هذه المناقشات. ما يتعلق بالموضوع هنا هو ما سيفعله numpy ، وهذا الحكم النهائي يعود إلى مطوري البرامج الخادمين. نحن نقدر الخبرة التي تجلبونها جميعًا إلى هذه المناقشة ، لكني أريد أن أركزها على الحقائق الأساسية بدلاً من الحكم النهائي. أنا أقدر بشكل خاص البيانات الكمية التي تعطيني فكرة عن مقدار الارتفاع الذي نمتلكه. إذا كانت أحكامي السابقة خاطئة ، فذلك لأنني قفزت إلى الحكم في وقت مبكر جدًا ، لذلك سأكون ممتنًا لمساعدتك في تجنب ذلك مرة أخرى. شكرا لك.

لاحظ أنه للحصول على احتمال أكبر بنسبة 50٪ أن يبدأ مولدان من بذرتين مترابطتين (يتم اختيارهما عشوائيًا) ، فأنت تحتاج فقط إلى حوالي نصف مليون مولدات تبدأ عشوائيًا (مفارقة عيد الميلاد).

vigna هل يمكنك n -bit عند عناصر 2**(n/2) (إعطاء أو أخذ عامل 2). نصف مليون هو 2**19 ، لذا يبدو أنك تدعي أن العلاقات الخطيرة تبدأ عند تصادم 40 بت في البتات السفلية ، لكنني لم أر دليلًا على أن هذا يمكن ملاحظته عمليًا. لقد اختبرت زوجًا يتقاسم أقل 40 بتًا وحصلت على 16 تيرابايت في PractRand قبل إلغاء الاختبار. إذا كنت قد لاحظت فشلًا في تصادم 40 بت ، فكم عدد TiB الذي كان عليك اختباره لرؤيته؟

أنا مقتنع بأن تغيير الزيادة لا يؤثر على احتمال الاصطدام. مزيد من المناقشة حول مزايا "تدفقات PCG" خارج الموضوع. إن استخدام هذه المناقشة كذريعة للتطرق بشكل متكرر على "المؤلف" هو أمر غير مرحب به بشكل خاص ويتناول قواعد السلوك لدينا. المثابرة تعني أنه سيتعين علينا المضي قدمًا بدون مدخلاتك. شكرا لك.

imneme يبدو أن هذا يتعلق بالمشكلات المتعلقة بالقفز بمضاعفات قوة كبيرة تبلغ 2. عندما أقوم بتكوين زوج من مثيلات PCG64 بنفس الزيادة ومشاركة أقل n بت ، المسافة التي أحسبها بين الاثنين هي مضاعف 1 << n . يبدو أنه يبدو أن دالة الإخراج الأقوى DXSM تعمل على حل هذا المظهر أيضًا. لقد اختبرت زوجًا من مثيلات PCG64DXSM تشترك في زيادة و 64 بت أقل من الحالة إلى 2 TiB بدون مشكلة.

حسنًا ، هذا محرج: كان نصف مليار وليس نصف مليون. يمكن لحرف واحد أن يحدث فرقًا كبيرًا. أعتذر عن الزلة.

ولكن ، كما قلت سابقًا ، هذا هو احتمال الوصول إلى نفس حالة البداية تمامًا ، وليس احتمال حدوث تداخل كبير في التكرارات اللاحقة المرتبطة. أنا شخصياً أفضل استخدام PRNGs بدون تكرارات لاحقة مرتبطة ، نظرًا لوجود الكثير منها ، ولكن كما قلت بحق ، القرار لك وحدك.

إن إصلاح وظيفة الخلط بحيث يكون لها خصائص خلط أفضل يبدو وكأنه حل معقول تمامًا.

كان من المفترض أن تكون رسالتي توضيحًا للاختلافات الهيكلية بين PCG و SplitMix ، نظرًا لأن المنشور السابق ادعى أن لديهم مشكلات مماثلة ، ولا أعتقد أن هذا بيان صحيح. لا يمكنك كتابة برنامج مثل http://prng.di.unimi.it/corrpcgnumpy.c لـ SplitMix.

لقد سألت

imneme يبدو أن هذا يتعلق بالمشكلات المتعلقة بالقفز بمضاعفات قوة كبيرة تبلغ 2. عندما أقوم بإنشاء زوج من مثيلات PCG64 بنفس الزيادة ومشاركة n الأقل بت ، فإن المسافة التي أحسبها بين الاثنين هي مضاعف 1 << n . يبدو أنه يبدو أن دالة الإخراج الأقوى DXSM تعمل على حل هذا المظهر أيضًا. لقد اختبرت زوجًا من مثيلات PCG64DXSM التي تشترك في زيادة و 64 بت أقل من الحالة إلى 2 TiB بدون مشكلة.

نشكرك على البحث والربط مرة أخرى بسلسلة المناقشة من العام الماضي. نعم ، كما يلاحظ سيباستيانو في رده ،

إن إصلاح وظيفة الخلط بحيث يكون لها خصائص خلط أفضل يبدو وكأنه حل معقول تمامًا.

XSL-RR في الطرف الأضعف للأشياء. في المقابل ، تعمل كل من وظيفة إخراج RXS-M الأصلية من ورق PCG ووظيفة إخراج DXSM الجديدة بشكل أكبر في طريقة التخليط ، وبالتالي لا تظهر هذه الأنواع من المشكلات. تم تصميم DXSM (الذي تمت إضافته إلى مصدر PCG في هذا الالتزام العام الماضي) خصيصًا ليكون أقوى من XSL-RR ولكن له نفس الأداء الزمني (راجع ، RXS-M ، وهو أبطأ). لقد اختبرت DXSM بصعوبة إلى حد ما العام الماضي ، ولكن بعد مرور 67 يومًا على التشغيل ، كان لدينا انقطاع طويل في التيار الكهربائي أدى إلى توقف الخادم (نفدت بطارية UPS) وأنهت الاختبار التجريبي ، ولكن في تلك المرحلة أثبتت نفسها بشكل جيد في الوضع العادي. الاختبار (تم اختبار 128 تيرابايت من المخرجات) ويقفز بمقدار 2 ^ 48 (تم اختبار 64 تيرابايت من المخرجات ، حيث يعمل ذلك بشكل أبطأ).

إذا ، حتى بدون تصميم DXSM ، فإن RXS-M كان سيهتم بالمشكلة ، فإن أحد الأسئلة هو لماذا استخدمت التقليب XSL-RR الأضعف بدلاً من ذلك - لماذا لا أستخدم دائمًا خلط بتات قوي جدًا في وظيفة الإخراج؟ الجواب هو أن الأمر يتعلق بالدورات. السرعة مهمة للناس ، لذلك تحاول تجنب القيام بمجهود أكبر مما تحتاج إليه.

هذه قضية يعرفها سيباستيانو ، لأن مقاربته وأسلوبه لديهما الكثير من القواسم المشتركة. كل منا يتبع نهجًا راسخًا منذ فترة طويلة قد يفشل في الاختبارات الإحصائية الحديثة (LCGs في حالتي ، و XorShift LFSRs من Marsaglia في بلده) ويضيف وظيفة إخراج الهرولة لاستردادها. كلانا نسعى جاهدين لجعل وظيفة الإخراج هذه رخيصة ، وقد اكتشفنا بعض الشيء حيث تظهر أوجه القصور في المولد الأساسي الذي نحاول إخفاءه من خلال وظيفة الإخراج الخاصة بنا. في حالته ، كانت القضايا الخطية التي ظهرت من خلال .

ولكن في العمل الحديث إلى حد ما الذي أسعدني كثيرًا ، أظهر أيضًا عدد التصميمات المستندة إلى LFSR التي بها مشكلات ذات وزن ثقيل (تعكس اهتمامي الخاص منذ فترة طويلة) والتي لم يتم حجبها بشكل كافٍ بوظائف الإخراج الخاصة بها. اجتازت مولداته اختباره ، وهذا شيء ما ، ولكن في عام 2018 برنامج الاختبار هذا ؟).

بالنسبة لبرامج الارتباط الخاصة به ، في عام 2018 عندما وضع نقدًا لـ PCG على موقعه على الويب والذي تضمن البرامج التي كتبها مع العديد من القضايا (مثل البذر المبتكر ، وما إلى ذلك) ، كتبت ردًا يحتوي على مجموعة من البرامج المماثلة بالنسبة إلى PRNGs الأخرى المنشأة منذ فترة طويلة ، بما في ذلك corrsplitmix2.c الذي ينشئ تدفقات مرتبطة في SplitMix. لست متأكدًا تمامًا مما يعنيه سيباستيان عندما يقول إنه لا يمكن القيام بذلك ، لكنني سأعترف أنه لم تتح لي الفرصة للنظر عن كثب في برنامج الاختبار الخاص به لمعرفة ما إذا كان برنامجه الجديد مختلفًا بشكل جوهري عن البرامج التي هو كتب قبل عامين.

أرجو أن تغفر عدم فهمي - لكن هل يمكنني أن أسأل أحدهم عن استنتاج موجز في هذه المرحلة؟ هل هناك ظروف واقعية يعتبر فيها PCG الافتراضي غير آمن؟ ما هي الحجج لتبديل الافتراضي؟

المسار السهل هو إضافة بعض الوثائق حول التطبيقات ذات الأبعاد العالية (عالية جدًا؟) واحتمال وجود تسلسلات مرتبطة.

سيكون المسار الأصعب هو استبدال وظيفة الإخراج التي قد تؤدي إلى كسر التيار. لست متأكدًا من مدى قوة الوعد default_rng . لا يبدو أن المستندات تحذر من أن هذا قد يتغير ، لذا من المحتمل أن يحتاج إلى تغيير دورة الإيقاف. سيتطلب ذلك إضافة وظيفة الإخراج الجديدة كمولد بت مستقل (أو قابل للتكوين من PCG64 ، والذي سيكون أكثر منطقية) ثم تحذير المستخدمين من أنه سيتغير بعد عام XXXX / إصدار Y.ZZ.

سيكون أصعب مسار هو العثور على rng افتراضي جديد. لم يكن الأمر سهلاً في المرة الأولى ولا أعتقد أن أي شيء قد تغير لتحريك الإبرة في أي اتجاه معين خلال الـ 18 شهرًا الماضية.

لقد فتحت gh-16493 حول تعديل default_rng() ، ولا أعتقد أنه مرتبط بهذه المشكلة ، ولست متأكدًا من أنه يتعين علينا مناقشتها ، فمن المحتمل أننا قد وضعنا القواعد بالفعل منذ فترة طويلة وأنا لا أفعل ذلك. ر أتذكر.


لا أدعي أنني فهمت هذه المناقشة تمامًا ، ولكن يبدو أن هناك شيئين يجب فهمهما:

  1. مع التأكد من أن لدينا تقدمًا كافيًا ، يجب أن أثق في روبرت في هذا الأمر ، ويبدو لي الآن أنه يجب أن يكون جيدًا على حد علمنا؟ (على سبيل المثال ، من المحتمل أن يكون احتمال حدوث تصادم فعلي منخفضًا بشكل محرج حتى في البيئات ذات المقادير الأكبر من أي شيء يمكن استخدام NumPy فيه؟ سواء كان ذلك يستدعي تغيير الإعداد الافتراضي في المستقبل أم لا ، فهذه مشكلة مختلفة.)
  2. نقول:

    ويدعم [...] بالإضافة إلى: الرياضيات: تدفقات 2^{127}

    الذي ، دون معرفة من أين يأتي الرقم بالضبط ، يبدو أنه قد يكون مبالغة طفيفة من جانبنا ويمكننا أن نعتبر تعديله قليلاً ليكون صحيحًا تمامًا؟ أو الارتباط ببعض الموارد الخارجية مع إعطاء تفاصيل إضافية؟

أسهل ما يمكن فعله الآن هو إضافة PCG64DXSM BitGenerator ، متغير PCG64 مع "المضاعف الرخيص" و DXSM دالة الإخراج الأقوى. أعتقد أن الجميع متفقون على أن هذه خطوة للأعلى من وظيفة إخراج XSL-RR التي لدينا الآن في تنفيذ PCG64 ، حيث يؤدي أداء أفضل إحصائيًا دون الإضرار بأداء وقت التشغيل. إنها ترقية مباشرة في المجال الذي يقدمه PCG64 لـ BitGenerator s التي نقدمها. أعتقد أنه يجب علينا إضافته إلى جانب PCG64 .

بالمناسبة ، أفضل أن يكون اسمًا منفصلاً باسم BitGenerator بدلاً من خيار مُنشئ PCG64 . هذه الخيارات رائعة في randomgen ، والغرض منها هو توفير الكثير من الخوارزميات والمتغيرات المختلفة ، ولكن بالنسبة لـ numpy ، أعتقد أننا نريد أن تكون اختياراتنا "انتزاع والذهاب" بقدر ما نستطيع.

لا أعتقد أننا حسمنا سياسة إجراء تغييرات على ما يقدمه default_rng() . عندما اقترحته ، طرحت فكرة أن أحد الأسباب التي جعلتني أفضلها فقط لوضع وظائفها في المُنشئ Generator() هو أنه يمكننا إهمالها والانتقال إلى وظيفة مختلفة إذا احتجنا إلى ذلك. ومع ذلك ، في ذلك الوقت كنا نفكر في أن default_rng() قد يحتاج إلى كشف الكثير من التفاصيل عن BitGenerator ، والذي تجنبناه لاحقًا. نظرًا لأن PCG64DXSM يعرض واجهة برمجة التطبيقات نفسها ( .jumped() وجه الخصوص) مثل PCG64 ، فإن الاعتبار الوحيد الذي سيكون لدينا هو أن استخدام الإعداد الافتراضي الجديد سيغير تدفق البتات. أعتقد أنه سيكون من المعقول بالنسبة لنا اتباع نفس الجدول الزمني مثل أي تعديل آخر للدفق قادم من طرق Generator لكل NEP 19 (أي في إصدارات الميزة X.Y.0 ). يمكننا اختيار أن نكون أكثر حذرًا ، إذا أردنا ذلك ، ونكشف أولاً عن PCG64DXSM كمتوفر BitGenerator في 1.20.0 والمستند (لكن ليس warn() ، صاخبة جدًا إلى عدم التأثير) أن default_rng() سيتغير إلى استخدامه في 1.21.0 .

كجزء من إضافة BG الجديد ، سيكون من الجيد تحديث الملاحظات إلى PCG64 لبدء العمل كدليل ولتقديم سبب منطقي لتفضيل المتغير الأحدث.

  1. مع التأكد من أن لدينا تقدمًا كافيًا ، يجب أن أثق في روبرت في هذا الأمر ، ويبدو لي الآن أنه يجب أن يكون جيدًا على حد علمنا؟ (على سبيل المثال ، من المحتمل أن يكون احتمال حدوث تصادم فعلي منخفضًا بشكل محرج حتى في البيئات ذات المقادير الأكبر من أي شيء يمكن استخدام NumPy فيه؟ سواء كان ذلك يستدعي تغيير الإعداد الافتراضي في المستقبل أم لا ، فهذه مشكلة مختلفة.)

من المحتمل أن يكون هذا بسيطًا جدًا. يعتمد ذلك على عدد التدفقات ، وكمية البيانات التي تسحبها من كل تدفق ، وما هو تحملك للمخاطر لتضارب عيد الميلاد. لم أقم بتحليل هذه الرياضيات في فقرة مفهومة حتى الآن لتقديم توصيات سهلة المتابعة حتى الآن ، وهذا هو السبب في أنني لم أعد النظر في مشكلة Github هذه منذ فترة. لا أعتقد أنها مشكلة حادة تحتاج إلى إصلاح _ الآن _ ، بالرغم من ذلك.

سأكتب شيئًا أطول في وقت لاحق ، لكن كما أراه في هذا الموضوع ، فقد قمنا بتجديد الأرضية التي ذهبنا إليها العام الماضي. لم يتغير شيء بخلاف اكتشف سيباستيانو أن NumPy قد شحنت PCG. كان التحليل الذي أجراه فريق NumPy العام الماضي أكثر تعمقًا ، واعتبر سيناريوهات أكثر منطقية.

أفضّل ترقية الإعداد الافتراضي بأسرع ما يمكن بشكل معقول - فقط لتقليل الارتباك. أعني ، لا تنتظر دورة كساد.

imneme - شكرًا جزيلاً - سأجد شيئًا أطول مفيدًا جدًا.

ربما يكون هذا هو أفضل انفجار من المنشور السابق عنه. أعتقد أنه بالتأكيد يستحق القراءة. يمكنك التمرير احتياطيًا في سلسلة الرسائل من هناك لمشاهدتنا نتحدث عن هذه المشكلات. كان حول PCG 32.

كان لدي ما أريد قوله في رأسي ، لكني أجد النظر إلى المنشورات منذ عام مضى ، لقد قلت كل شيء بالفعل ، هنا وفي أي مكان آخر ( مدونتي (2017) ، reddit ، مدونتي مرة أخرى (2018) ، وفي مناقشات NumPy ، إلخ.)

حول التدفقات والتشابه مع الذات (التي كتب rkern من أجلها اختبار اعتماد على التدفق ) ، كتبت العام الماضي:

كما هو مذكور في منشور المدونة الخاص بي الذي تم ذكره سابقًا ، فإن تدفقات PCG لها الكثير من القواسم المشتركة مع SplitMix.

فيما يتعلق بالرسم البياني mdickinson ، بالنسبة إلى _ كل_ PRNG الذي يسمح لك ببذر حالته بالكامل ، بما في ذلك حالات التشفير القائمة على العداد ، يمكننا إنشاء مجموعات حيث يكون لدينا PRNGs التي ترتبط مخرجاتها بطريقة ما (أسهل طريقة للقيام بذلك) هو جعل حالات PRNG التي تكون على بعد مسافة قصيرة ، ولكن في كثير من الأحيان يمكننا القيام بأشياء أخرى بناءً على فهم كيفية عملها). وعلى الرغم من أن PRNGs التي لا تسمح بالبذر بالحالة الكاملة يمكن أن تتجنب هذه المشكلة ، فإن القيام بذلك يقدم فقط مشكلة جديدة ، ويوفر فقط وصولاً عمليًا إلى جزء صغير من حالاتهم المحتملة.

الطريقة الصحيحة للتفكير في التدفقات هي مجرد حالة عشوائية أكثر تحتاج إلى بذور. يعد استخدام قيم صغيرة مثل 1،2،3 فكرة سيئة عمومًا لأي أغراض بذر لأي _ PRNG (لأنه إذا فضل الجميع هذه البذور ، فسيتم تمثيل تسلسلها الأولي المقابل بشكل زائد).

يمكننا أن نختار عدم تسميته تيارًا على الإطلاق وأن نسميه الحالة فقط. هذا ما فعلته Marsaglia في counter لا يتفاعل مع بقية الولاية على الإطلاق ، ومثل LCGs ، والاختلافات في القيمة الأولية تصل فقط إلى ثابت مضاف.

تدفقات SplitMix و PCG و XorWow هي ما يمكن أن نطلق عليه تدفقات "غبية". إنها تشكل إصلاحًا تافهًا للمولد. ومع ذلك ، هناك قيمة في هذا. افترض أنه بدون التدفقات ، سيكون لـ PRNG تكرارًا مثيرًا للاهتمام لـ 42 ، حيث يتم اقتصاص 42 عدة مرات في تتابع سريع ويفعل هذا فقط لـ 42 وليس أي رقم آخر. مع تدفقات "مجرد زيادة" أو "مجرد xor" غبية ، سنتجنب في الواقع ربط التكرار الغريب بـ 42 ؛ كل الأرقام لها دفق تكون فيه تكرار غريب. (لهذا السبب ، فإن الإصلاح الذي سأطبقه لإصلاح Weyl .)

(ثم ذهبت إلى أكثر عمقا في هذا التعليق و هذا واحد ).

أود أن أقول إن الشيء الأساسي هو أنه في أي PRNG تقريبًا ، مع القليل من الوقت والطاقة ، يمكنك صنع نبتة مرضية. PCG في وضع غير معتاد إلى حد ما حيث أن لديه شخصًا يستمتع بعمل بذور ذات مظهر معقول لـ PCG على وجه التحديد التي لديها علم أمراض مصنوع يدويًا (مثل Sebastiano). كنتيجة لهذا العمل ، استدرت وفعلت الشيء نفسه لكل من PRNGs الخاصة به ولأخرى طويلة الأمد.

بشكل عام ، تريد تهيئة حالة PRNG بشيء يبدو "عشوائيًا نوعًا ما". هذا عالمي جدًا ، حتى لو أراد الناس القيام بخلاف ذلك . على سبيل المثال ، بالنسبة إلى أي LFSR PRNG (XorShift-style ، Mersenne Twister ، إلخ) ، يجب ألا تهيئته بحالة جميع الأصفار لأنها ستبقى عالقة هناك. ولكن حتى الحالات التي تكون في الغالب صفرية غالبًا ما تكون مشكلة بالنسبة إلى LFSRs (ظاهرة تُعرف باسم zeroland ، ولماذا كسب الأشخاص C ++ seed_seq .). إذا كنت تريد أن تلعب لعبة "دعونا نفعل بعض البذر المفتعل" ، فليس من الصعب إنشاء مجموعة من التهيئة لـ 100 LFSRs وجعلهم جميعًا على بعد 1K من الوصول إلى أرض الصفر. ستبدو جميع عمليات التهيئة المصطنعة بريئة بدرجة كافية ، لكنها ستصيب جميعًا هذا الانخفاض الغريب في وزن المطرقة في نفس الوقت.

إذا كنت تستخدم مولد PCG تمت تهيئته باستخدام إنتروبيا معقولة ، فلا بأس بذلك. إذا كنت ترغب في تهيئته مع البريد غير الهام مثل 1 ، 2 ، 3 ، فهذا في الواقع يمثل مشكلة مع أي PRNG . ومع PCG ، 99.9 ٪ من الوقت ، حتى استخدام شيء غير مرغوب فيه سيكون جيدًا. ليس لديها أي شيء مثل هذا النوع من القضايا التي لديها LFSRs.

لكن DXSM أقوى بالتأكيد. أعتقد أنه أفضل أو ما كنت سأفعله ، لكن الأمر يستحق أن يكون لديك بعض المنظور وأن ندرك أنه من الناحية العملية لن يواجه المستخدمون مشاكل في تنفيذ PCG64 الكلاسيكي.

أرغب في فصل النقد / الدفاع عن تدفقات PCG64 (عبر زيادة LCG) عن المناقشة الحالية. في حين أن هناك ازدواجية معينة متضمنة بسبب رياضيات LCG ، إلا أنها ليست القضية الأساسية التي تم طرحها هنا في الأصل. أيضًا ، هناك المزيد من التفاصيل التي يجب مراعاتها أكثر مما كانت موجودة في نقد سيباستيانو ردك ، أو الموضوع الضخم القديم. ربما تكون الصلة أكثر وضوحًا للخبراء الذين أمضوا وقتًا أطول في الرياضيات ، لكن العواقب العملية أصبحت الآن أوضح بالنسبة لي ، على الأقل.

أود أن أقول إن الشيء الأساسي هو أنه في أي PRNG تقريبًا ، مع القليل من الوقت والطاقة ، يمكنك صنع نبتة مرضية.

منحت ، ولكن ليس الخيار الثنائي هو الذي يدفع القرار أمامي. إذا قمت برسم عدد كبير جدًا من الأرقام من PRNG محدود ، فإن PractRand في النهاية سوف يزيلها. هذه الحقيقة الثنائية لا تبطل خوارزمية PRNG. كان الابتعاد عن هذا الثنائي وتأسيس مفهوم الإرتفاع أحد الأشياء التي أقدرها حقًا بشأن ورقة PCG الأصلية. بالنظر إلى علم الأمراض الناتج عن العداء ، يمكننا إلقاء نظرة على عدد المرات التي يمكن أن تنشأ فيها هذه الأمراض بشكل عشوائي من بذر الانتروبيا الجيد. أريد تحديد ذلك ، وتحويله إلى نصيحة عملية للمستخدمين.

بالنظر إلى حالتين تشتركان في 58 بت أقل ونفس الزيادة (سنضع دبوسًا في ذلك) ، يُظهر تشذير مثيلات PCG64 XSL-RR من تلك الحالات حالات فشل ملحوظة عمليًا في PractRand عند حوالي 32 جيجا بايت. أعتقد أنه من المعقول أن ترغب في تجنب ذلك. لذلك دعونا نأخذ ذلك على أنه معيارنا وننظر إلى عدد المرات التي ينشأ فيها ذلك مع البذر الجيد للأنتروبيا لحسن الحظ ، فإن مخطط الخصومة هذا قابل للتحليل الاحتمالي (ليست كلها ودية للغاية). بالنسبة لمثيلات n ، فإن احتمال مشاركة أي 2 من نفس 58 بت أقل هو n**2 / 2**58 ، أو إعطاء أو أخذ عامل 2 للعد المزدوج. لذلك في نصف مليار حالة ، من المحتمل أن يكون هناك اقتران واحد من شأنه أن يفشل PractRand إذا تم تشذيره. نصف مليار كثير! في رأيي ، ربما لن نرى أبدًا برنامج numpy يحاول إنشاء العديد من الأمثلة PCG64 . إذن ، من المحتمل أن يكون numpy هو الأداة الخطأ.

أعتقد أنه من المعقول أيضًا تجنب الحالات الأولية التي ستتقاطع سحبها اللاحقة مع أي من حالات الاصطدام المنخفضة ذات 58 بت للحالات الأولية الأخرى. ما زلت أحاول التفكير في المنطق في ذلك ، لكنني أعتقد أن الطول يؤثر على الاحتمال خطيًا وليس تربيعيًا. إذا كنت على حق ، وأريد أن أرسم 16 جيجا بايت من كل حالة ( 2**28 تعادل) ، وهو المبلغ الذي رسمناه من كل زوج من الأزواج التي أظهرت حالات فشل PractRand ، فعندئذ يمكنني العمل بحوالي 2**15 مثيل ، أو حوالي 32 ألفًا ، قبل أن يصبح من المحتمل جدًا ملاحظة التقاطع. لا يزال هذا عددًا كبيرًا من الأمثلة لبايثون! ويبلغ إجمالي حجم البيانات المتولدة حوالي نصف بيتابايت ، وهو عدد كبير! لكنها تلوح في أفق التطبيق العملي ، وإذا كنت أرغب في إبقاء الاحتمال منخفضًا ، وليس أقل من النصف بقليل ، يجب أن أخفض أحدهما. لا أهتم بشكل خاص بهذه الأرقام. لا أعتقد أن أي برامج numpy حقيقية من المحتمل أن تواجه مشاكل باستخدام PCG64 مع دالة الإخراج XSL-RR. ولكن قد تبدأ بعض التطبيقات في الاقتراب (على سبيل المثال ، تشغيل التعلم المعزز الموزع الكبير).

دعونا نأخذ هذه الزيادة ونناقشها. أعتقد أنه من العدل أن نقول أنه مع وظيفة إخراج XSL-RR ، فإن زيادة الانتروبيا بالإضافة إلى الحالة لا تغير هذا التحليل المعين. يبدو أنه بالنسبة لأي زوج معين من الزيادات المصنفة في الانتروبيا ، هناك نفس عدد حالات الاصطدام عمليًا. يبدو الإجراء الملموس لبناء تلك الحالات بشكل متعمد أكثر تعقيدًا من التقريع في نفس 58 بت أقل ، ولكن يبدو أن عدد حالات الاصطدام هو نفسه ، لذلك تظل حسابات الاحتمال كما هي. هذا ليس جوهريًا في مخطط PCG بشكل عام. يبدو أن دالة الإخراج DXSM قوية بما يكفي بحيث يبدو أن تغيير الزيادة (حتى مع +2 بسيط) كافٍ لمقاومة حتى أسوأ حالة لـ LCG الأساسي (عندما يعطي مقياس المسافة 0 ) ، على الأقل بقدر ما أزعجت نفسي للاختبار مع PractRand.

أريد أن أختم بتكرار ما يبدو أننا جميعًا على اتفاق تام بشأن: PCG64DXSM فكرة جيدة. إذا لم يكن هناك شيء آخر ، فإن خصائصه الإحصائية المحسّنة تبسط النماذج العقلية التي أشعر أنني مضطر لتوثيقها ، وأي شيء يعني أنني يجب أن أكتب توثيقًا أقل هو أمر جيد في كتابي.

لا تزال التدفقات ذات صلة إلى حد ما لأن المشكلة تظهر فقط إذا كان لدينا المولدات في نفس الدفق.

ولكن في أي ظروف سيكون لديهم نفس 58 بت أقل ويكونون على نفس التيار؟ هل هناك حالة استخدام حيث سيحدث هذا؟

الحالة الواقعية إلى حد ما التي أعرفها هي الحالة التي تحدثنا عنها العام الماضي (عندما تحدثنا عن jumped ) ، وتحدثت عنها في هذا المنشور الذي ربطته سابقًا.

لا تزال التدفقات ذات صلة إلى حد ما لأن المشكلة تظهر فقط إذا كان لدينا المولدات في نفس الدفق.

لسوء الحظ ، هذا ليس هو الحال مع XSL-RR. لنفكر في مثيلين PCG64 XSL-RR. نحن نبذر الإنتروبيا الزيادات بشكل تعسفي ونبذر الإنتروبيا إحدى الحالات. يمكننا إنشاء 2**70 حالات سيئة للمثيل الآخر PCG64 الذي يفشل PractRand بنفس طريقة فشل نفس الزيادة في الحالة الأدنى 58 بت. الأمر أكثر تعقيدًا من القيام به في نفس حالة الزيادة. بدلاً من مشاركة الـ 58 بت الأقل كحالة أولى مع الزيادة المختلفة ، فإنها تشترك في أقل 58 بتًا من الحالة التي تكون مسافة 0 (وفقًا لمقياس مسافة LCG) من المثال الأول ، مع مراعاة الزيادات. لدي دليل بناء (كود Python) ، لكن يجب أن أنام الآن وأنظفه غدًا.

rkern ، نقطة جيدة. سأعترف ، لم أختبر هذا السيناريو لأرى كيف ستسير الأمور.

أود أن أقول إن الشيء الأساسي هو أنه في أي PRNG تقريبًا ، مع القليل من الوقت والطاقة ، يمكنك صنع نبتة مرضية. PCG في وضع غير معتاد إلى حد ما حيث أن لديه شخصًا يستمتع بعمل بذور ذات مظهر معقول لـ PCG على وجه التحديد التي لديها علم أمراض مصنوع يدويًا (مثل Sebastiano). كنتيجة لهذا العمل ، استدرت وفعلت الشيء نفسه لكل من PRNGs الخاصة به ولأخرى طويلة الأمد.

كما أشرت بالفعل ، هذا خطأ. لا أعرف أي مثال على زوج من التسلسلات المترابطة وغير المتداخلة ، على سبيل المثال ، من xoshiro256 ++ كما يمكنك أن تجده بسهولة داخل PCG.

لا توجد هذه المشكلة في PRNGs التي تخلط حالتها بالكامل بسرعة. إذا كان بإمكانك توفير برنامج يقوم بإنشاء تسلسلين غير متداخلين من xoshiro256 ++ مترابطين ، مثل الأمثلة التي نشرتها هنا ، فيرجى القيام بذلك.

بالنسبة لبرامج الارتباط الخاصة به ، في عام 2018 عندما وضع نقدًا لـ PCG على موقعه على الويب والذي تضمن البرامج التي كتبها مع العديد من القضايا (مثل البذر المبتكر ، وما إلى ذلك) ، كتبت ردًا يحتوي على مجموعة من البرامج المماثلة بالنسبة إلى PRNGs الأخرى القائمة منذ فترة طويلة ، بما في ذلك corrsplitmix2.c الذي ينشئ تدفقات مرتبطة في SplitMix لست متأكدًا تمامًا مما يعنيه سيباستيان عندما يقول إنه لا يمكن القيام بذلك ، لكنني سأعترف أنه لم تتح لي الفرصة للنظر عن كثب في برنامج الاختبار الخاص به لمعرفة ما إذا كان برنامجه الجديد مختلفًا بشكل جوهري عن البرامج التي هو كتب قبل عامين.

البرنامج المقتبس أعلاه _ يختار التدفقات_. من الواضح أنه من السهل كتابتها.

لكن هذا لا علاقة له بمشاكل PCG. يسمح البرنامج الذي قدمته للمستخدم باختيار التدفقات ، ثم يظهر الارتباط.

أدعو ، مرة أخرى ، inmeme لتوفير برنامج لـ SplitMix حيث يمكن للمستخدم تحديد دفقين مختلفين بشكل تعسفي ، حالة أولية عشوائية للمولد الأول ، ثم يجد البرنامج تسلسلًا مرتبطًا في المولد الآخر ، مثل http: / /prng.di.unimi.it/corrpcgnumpy.c يفعل.

يُظهر السماح للمستخدم باختيار الدفق بشكل تعسفي شكلاً أقوى بكثير من الارتباط.

كما أشرت بالفعل ، هذا خطأ. لا أعرف أي مثال على زوج من التسلسلات المترابطة وغير المتداخلة ، على سبيل المثال ، من xoshiro256 ++ كما يمكنك أن تجده بسهولة داخل PCG.

يبدو أننا نتحدث عن بعضنا البعض هنا. لم أقل إنني أستطيع التوصل إلى متواليات مترابطة وغير متداخلة لأي PRNG ، قلت إن بإمكاني الخروج ببذور مرضية بشكل عام ، كما هو موضح في برامج الارتباط المختلفة التي كتبتها سابقًا ، وغيرها مثل كما يكرر البرنامج التوضيحي السيئ ل Xoshiro ** .

أيضًا ، PRNGs التي لا تخلط بين دولتها بأكملها لها تاريخ طويل ، بما في ذلك XorWow ، والمولدات في الوصفات الرقمية ، وما إلى ذلك. تمثل حجة سيباستيانو وجهة نظر ولكن حجته تقول أن Marsaglia بطريقة ما جعل XorShift _worse_ في XorWow عن طريق إضافة Weyl التسلسل ، لأنه يخلق عددًا كبيرًا من المولدات المماثلة.

يبدو أننا نتحدث عن بعضنا البعض هنا. لم أقل إنني أستطيع التوصل إلى متواليات مترابطة وغير متداخلة لأي PRNG ، قلت إن بإمكاني الخروج ببذور مرضية بشكل عام ، كما هو موضح في برامج الارتباط المختلفة التي كتبتها سابقًا ، وغيرها مثل كما يكرر البرنامج التوضيحي السيئ ل Xoshiro ** .

يرجى محاولة إبقاء المناقشة على المستوى الفني. "الباثولوجية" ليس لها معنى رياضي.

الطريقة الصحيحة تقنيًا للتحقق من الارتباط الذاتي هي العثور على بذرتين ينتج عنه تسلسلين غير متداخلين (غير متداخلين طوال مدة الاختبار - سيتداخلان بشكل لا مفر منه إذا ذهبت بعيدًا بما فيه الكفاية) ، قم بتشذيرهما وتمريرهما إلى بطارية من الاختبارات.

إذا كنت تفكر في وجود تسلسلين متداخلين ، فسيتم ربطهما لكل مولد ، حتى لو كان مولدًا مشفرًا ، وذلك ببساطة لأن نفس المخرجات ستحدث مرتين بعد تداخل التسلسلات ، وأي اختبار معقول سوف يلتقط ذلك.

"البذر المرضي" باستخدام التسلسلات المتداخلة هو مهمة تافهة لكل مولد (مهما كانت الوسائل "المرضية").

مرة أخرى ، نظرًا لأنك تدعي أنك وجدت ارتباطًا مشابهًا لـ PCG (حيث لا تتداخل التسلسلات ، كما يظهر الاختبار) في المولدات الأخرى ، هل يمكنك توفير زوج من المتواليات المترابطة وغير المتداخلة ، على سبيل المثال ، من xoshiro256 ++ أو SFC64 ؟

الطريقة الصحيحة تقنيًا للتحقق من الارتباط الذاتي هي العثور على بذرتين ينتج عنه تسلسلين غير متداخلين (غير متداخلين طوال مدة الاختبار - سيتداخلان بشكل لا مفر منه إذا ذهبت بعيدًا بما فيه الكفاية) ، قم بتشذيرهما وتمريرهما إلى بطارية من الاختبارات.

هل يمكنك الإشارة إلى الأدبيات الخاصة بتعريف الارتباط هذا حتى أتمكن من التأكد من أنني أبقى "على صواب تقنيًا" بشأن ذلك أيضًا؟

سيباستيانو ، أنت تريدني أن أجيب على التحدي الذي تم وضعه وفقًا لشروطك. ما تشير إليه يتعلق بالخصائص الجوهرية لـ LCGs ، حيث يوجد تشابه ذاتي. لن تجد نفس المشكلة في PRNG الفوضوي أو المستندة إلى LFSR.

ولكن بالنسبة لـ PRNGs الأخرى ستكون هناك نقاط ضعف أخرى.

تحتوي LFSRs على zeroland ، وحالات سيئة ، ومشكلات وزن المطرقة ، والخطية ، وكما تعلمنا من محاولاتك مع xoshiro ، وأحيانًا غريبة أخرى مثل مشاكل غريبة مع التكرارات.

تتعرض PRNGs الفوضوية لخطر الدورات القصيرة (على الرغم من أن الدورات ذات العداد تتجنب ذلك - تسلسلات Weyl FTW!) وتحيزها الجوهري.

إذا تداخلت التسلسلات ، كما كتبت ، فسوف يفشل الاختبار دائمًا. لا تحتاج إلى الأدب لفهم أن الاختبار الذي _ يفشل دائمًا_ ليس اختبارًا.

مرة أخرى ، نظرًا لأنك تدعي أنك وجدت ارتباطًا مشابهًا لـ PCG (حيث لا تتداخل التسلسلات ، كما يظهر الاختبار) في المولدات الأخرى ، هل يمكنك توفير زوج من المتواليات المترابطة وغير المتداخلة ، على سبيل المثال ، من xoshiro256 ++ أو SFC64 ؟

يبدو أنك تتهرب من السؤال حقًا. سيكون من السهل جدًا عليك ، بعد ادعاءاتك ، تقديم مثل هذه الأدلة ، إذا كان لديك أي منها.

أسهل ما يمكن فعله الآن هو إضافة PCG64DXSM BitGenerator ، متغير PCG64 مع "المضاعف الرخيص" و DXSM دالة الإخراج الأقوى. أعتقد أن الجميع متفقون على أن هذه خطوة للأعلى من وظيفة إخراج XSL-RR التي لدينا الآن في تنفيذ PCG64 ، حيث يؤدي أداء أفضل إحصائيًا دون الإضرار بأداء وقت التشغيل. إنها ترقية مباشرة في المجال الذي يقدمه PCG64 لـ BitGenerator s التي نقدمها. أعتقد أنه يجب علينا إضافته إلى جانب PCG64 .

لاحظ أن "المضاعفات الرخيصة" 64 بت بها عيوب يمكن إثباتها. هذا معروف منذ زمن طويل:

W. Hörmann و G. Derflinger ، مولد رقم عشوائي محمول مناسب تمامًا لـ
طريقة الرفض ، ACM Trans. رياضيات. سوفتو. 19 (1993) ، لا. 4 ، 489-495.

بشكل عام ، المضاعفات الأصغر من الجذر التربيعي للمعامل لها حدود متأصلة في درجاتها الطيفية f₂.

يمكن تجاوز الحد بسهولة باستخدام مُضاعِف 65 بت ، والذي سيقوم المترجم بتحويله فقط في عملية "إضافة" إضافية ، وربما حتى عدم تغيير سرعة المولد.

عملت أنا وجاي ستيل على هذه القضية قليلاً ونشرنا جداول النتائج الطيفية للمضاعفات الرخيصة ذات الأحجام المختلفة: https://arxiv.org/pdf/2001.05304.pdf . كلما كان ذلك أفضل ، كان ذلك أفضل ، ولكن هناك فجوة يمكن إثباتها من 64 إلى 65 بت (بالنسبة إلى LCG مع 128 بت من الحالة).

على سبيل المثال ، من الجدول 7 بالورقة تحصل على 0x1d605bbb58c8abbfd ، والتي لها درجة f₂ 0.9919. لا يمكن لمضاعف 64 بت أن يتجاوز 0.9306 (نظرية 4.1 في الورقة).

بعد المزج وكل شيء ، قد يمر التحسن في درجة f₂ دون أن يلاحظه أحد تمامًا من وجهة نظر إحصائية. لكن بالنظر إلى التحسين الكبير الذي تحصل عليه بالنسبة للبعد الأكثر صلة مع مجرد عملية إضافة إضافية ، أعتقد (حسنًا ، نعتقد ، أو لم نكن لكتابة الورقة) يستحق الجهد.

سيباستيانو ، أنت تريدني أن أجيب على التحدي الذي تم وضعه وفقًا لشروطك. ما تشير إليه يتعلق بالخصائص الجوهرية لـ LCGs ، حيث يوجد تشابه ذاتي. لن تجد نفس المشكلة في PRNG الفوضوي أو المستندة إلى LFSR.

واو ، لقد استغرق الأمر بعض الوقت للوصول إلى هناك!

تحتوي LFSRs على zeroland ، وحالات سيئة ، ومشكلات وزن المطرقة ، والخطية ، وكما تعلمنا من محاولاتك مع xoshiro ، وأحيانًا غريبة أخرى مثل مشاكل غريبة مع التكرارات.

أنا أتفق تمامًا - لهذا السبب عليك أن تدافع عنهم. لاحظ أن المولدات LFSRs و F₂-linear هي أشياء مختلفة ؛ ذات صلة ولكنها مختلفة.

"مشاكل غريبة مع التكرارات" ، كالعادة ، مصطلح غير تقني لا يمكنني التعليق عليه.

تتعرض PRNGs الفوضوية لخطر الدورات القصيرة (على الرغم من أن الدورات ذات العداد تتجنب ذلك - تسلسلات Weyl FTW!) وتحيزها الجوهري.

[تحديث: فاتني الملاحظة المضادة بين قوسين ، لذلك أقوم بتحديث تعليقي.]

نعم ، لا يحتوي SFC64 على مثل هذه المشكلات (يستخدم عدادًا) ، لذلك لن أعمم على الفئة بأكملها. هناك مولدات فوضوية مصممة بعناية ولها أقصر دورة يمكن إثباتها.

"مشاكل غريبة مع التكرارات" ، كالعادة ، مصطلح غير تقني لا يمكنني التعليق عليه.

يبدو من الغريب ألا أكون قادرًا على التعليق لأنني لم أستخدم المصطلحات الصحيحة - قم بتشغيل هذا البرنامج ثم لا تتردد في تنويرني بأفضل طريقة لوصف المشكلة باللغة المناسبة ثم تقديم أي تعليق يبدو مناسبًا. كنت أتخيل أنك ودايفيد بلاكمان كنتم ستناقشون القضية عندما ظهرت لأول مرة لأنني تراسلت معه حول هذا الموضوع ، لكنني لم أره أبدًا تعلق عليه.

مناقشة PRNGs ليست في numpy خارج الموضوع. الرجاء استخدام المنتديات الخاصة بك لمواصلة هذا النقاش. شكرا لك.

rkern - يبدو هذا صارمًا بعض الشيء كمعيار. إذا كان هناك نقص في Numpy الضمني الذي لا تشاركه التطبيقات الأخرى ، يبدو من المعقول مناقشته.

أستطيع أن أؤكد أن التبادل الذي أشير إليه لا يساعدني في اتخاذ القرارات التي أمامنا في هذا الموضوع. حتى نحرز تقدمًا في ذلك ، أحتاج إلى تركيز المحادثة.

أعتقد أنه من المفيد فهم السياق الأوسع. سيباستيانو لديه القليل من الشيء حول PCG وكان يهاجمها لسنوات. أعتقد أن بعض الأشخاص في هذه الأيام قد ينظرون إلينا ويديرون أعينهم ويقولون "كلاكما سيء مثل بعضكما البعض" لأنني أيضًا انتقدت PRNGs الخاصة به ، لكنني في الواقع لم أفعل ذلك إلا بعد أن ذهب يدعي أن كنت أحاول إخفاء شيء ما من خلال عدم الحديث مطلقًا عن أغراضه (بينما في الواقع ، لم يكن لدي الوقت / الميل - في الواقع ، كنت أفترض أنهم بخير).

ومع ذلك ، فإن انتقاداته مفيدة ، ويسعدني أنه اختار قضاء الكثير من حياته في التفكير في عملي ، ولكن من المهم أن ندرك أن اختباراته ذات طبيعة عدائية. إنه يستخدم المعرفة بهيكل PCG لإنشاء ترتيبات يمكن إدخالها في مختبري RNG واختبارات الفشل.

بالنظر إلى كيف يمكن أن يبدو ذلك مخيفًا ، يبدو من المعقول إظهار أن نهجًا عدائيًا مشابهًا سيؤدي أيضًا إلى تعثر العديد من المولدات الأخرى وأن العديد من المخاوف التي يثيرها حول PCG ستنطبق على مخططات الأجيال الأخرى أيضًا ، كما لاحظت حول مخططات التوليد مثل XorWow ، وغالبًا ما أستخدم SplitMix كمثال ، كما سأفعل أدناه. (لا أحد منا مستثمر بشكل خاص في SplitMix بطريقة أو بأخرى ، كما أتخيل).

يمكن أن نكون مخيفين للغاية بشأن SplitMix ، على سبيل المثال ، ونبين أنه مع ثابت التدفق الافتراضي ، إذا نظرنا إلى كل إخراج 35185 ، فإنه يفشل في مجموعة اختبار PRNG. أوه لا! هذا بسبب زيادة العداد داخليًا (تسلسل Weyl!) بمقدار 0x9e3779b97f4a7c15 (بناءً على φ ، النسبة الذهبية) ، ولكن 35185 * 0x9e3779b97f4a7c15 = 0x86a100000c480245 ، الذي يحتوي فقط مجموعة 14 بتة ومجموعة كبيرة من لا شيء في المنتصف. أو إذا نظرنا إلى كل ناتج رقم 360998717 ، فإننا نصل إلى أن نكون معادلين لإضافة إلى الحالة الداخلية 0x48620000800401 ، والتي تتم إضافة 8 بتات فقط ومرة ​​أخرى شيء صعب لإخفاء وظيفة الإخراج الخاصة به بالكامل .

يمكننا أن نواصل التخويف حول SplitMix ونقول انظر ، ماذا لو كان لدي دفقان ، أحدهما بالثابت الإضافي 0x9e3779b97f4a7c15 والآخر بـ 0xdaa66d2c7ddf743f ، سنرى عيوبًا إذا أدخلنا هذا في مجموعة اختبار PRNG !!! لكن هذا بسبب أن الثاني تم اختراعه ليكون 3x الآخر.

وأخيرًا ، إذا قال أحدهم "سأقدم لك كلا البث ، افعل شيئًا مخيفًا مع ذلك!" ، ولنفترض أن مجموعتهما كانت تستند إلى π ( 0x243f6a8885a308d3 ) و _e_ ( 0xb7e151628aed2a6b ) ، يمكننا أن نقول ، بالتأكيد ، دعونا نحصل على المزيد من التخويف ونأخذ كل عنصر 6561221343 من تيار Pi وخلطه مع كل عنصر 6663276199 من تيار E و low-and-belhold ، فإنهما ينتجان عنصرين متطابقين التسلسلات. والأسوأ من ذلك ، أتابع بعد ذلك إظهار أنه لكل قفزة في الدفق أ ، هناك قفزة متطابقة في الدفق ب لإعطاء نفس المخرجات ، لذلك توجد بالفعل 2 ^ 64 طريقة ترتبط بها !!! (ويمكننا القيام بذلك لأي دفقين ، لم يكن هناك شيء مميز حول π و _e_.)

بالعودة إلى PCG ، يعتمد اختبار سيباستيانو على محاذاة مولدي PCG64 XSH RR بدقة بحيث يتم تشذير المخرجات المتطابقة. إذا تقدمنا ​​للتو بإحدى PRNGs بكمية صغيرة ، وكسرنا المحاذاة المثالية ، يصبح من الصعب للغاية اكتشاف أي شيء مشكوك فيه.

سيكون اختبار العداء المماثل في الاتجاه الآخر (وضع عبء على سيباستيانو) هو توفير مخرجات PCG64 XSH RR التي تلبي ادعائه بأنها مرتبطة ببعضها البعض ولكننا لا نخبره بالضبط كيف تتماشى (إنها فقط في الحي العام الصحيح). ستكون وظيفته العثور على المحاذاة لإظهار أنها مترابطة.

بشكل عام ، لا أعتقد أنها مشكلة من الناحية العملية تتعلق بإخماد الحرائق العاجلة ، ولكن من ناحية أخرى ، فإن إصدار DXSM أفضل لأنه تمت كتابته العام الماضي للتخفيف بدقة من هذه الأنواع من المشكلات ، وسأكون كذلك يسعدني أن تتحول إليه.

ملاحظة: يمكنك عمل ثوابت Weyl المضافة السحرية من الرقم الحقيقي المفضل لديك باستخدام هذا الكود:

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

هذا ماثيماتيكا ، سأترك نسخة بايثون كتدريب.

إليك كيفية إنشاء تصادمات بت أقل لزيادات مختلفة.

النتائج مع PCG64 XSL-RR وتصادم أقل بمقدار 58 بت

❯ ./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

النتائج مع PCG64 DXSM وتصادم 64 بت أقل (لإثارة المشاكل بشكل أسرع ، على الرغم من أنني لا أرى أيًا منها)

❯ ./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 ، شكرًا لمشاركة التعليمات البرمجية الخاصة بك. سيكون من المفيد إضافة خيار لإضافة انحراف لتغذية المخرجات المشذرة في جهاز الاختبار غير المحاذي تمامًا. هذا شيء استكشفته قليلاً.

نعم ، لقد فعلت ذلك بشكل غير رسمي عن طريق إدخال bg0.advance(N) لمختلف N قبل return الأخير. لقد استخدمت تصادم 64 بت السفلي للتأكد من أنني سأرى شيئًا ما. التحولات الصغيرة مثل 16 لا تغير الفشل كثيرًا ، ولكن حتى التحولات المتواضعة مثل 128 تطيل الفشل إلى 32 جيجا بايت.

يبدو أنه يجب علينا إضافة PCG64 DXSM كمولد بت اختياري وجعله في النهاية هو الإعداد الافتراضي. لدينا تنفيذ؟

أعتقد أنه من المفيد فهم السياق الأوسع. سيباستيانو لديه القليل من الشيء حول PCG وكان يهاجمها لسنوات. أعتقد أن بعض الأشخاص في هذه الأيام قد ينظرون إلينا ويديرون أعينهم ويقولون "كلاكما سيء مثل بعضكما البعض" لأنني أيضًا انتقدت PRNGs الخاصة به ، لكنني في الواقع لم أفعل ذلك إلا بعد أن ذهب يدعي أن كنت أحاول إخفاء شيء ما من خلال عدم الحديث مطلقًا عن أغراضه (بينما في الواقع ، لم يكن لدي الوقت / الميل - في الواقع ، كنت أفترض أنهم بخير).

أعتقد أن هذه الاعتبارات غير مناسبة تمامًا.

الإصرار على مهاجمة عمل الآخرين (على سبيل المثال ، SplitMix) دون أي ميزة وبدون أي دليل لن يجعل فوضى PCG أو مولد Numpy أفضل. قد يساعد استخدام مُضاعِف أفضل ، أو جهاز تشويش إذاعي بشكل أفضل.

ما زلت أنتظر اختبارًا يوضح الارتباط في SplitMix عندما يمكن للمستخدم اختيار التدفقات. فقط لكي أكون واضحًا ، بالنسبة لمولد Numpy ، فقد أثبتت بيانًا بالشكل

∀c ∀d ∀x ∃y مرتبط

حيث c ، d هي زيادات ("تدفقات") ، و x ، y حالات أولية. في الواقع ، هناك 2 ^ 72 ذ. هذا ، بغض النظر عن كيفية اختيارك لـ c و d و x ، هناك ارتباط يظهر 2 ^ 72 y.

يوضح الرمز المقابل المزعوم الذي قدمته لـ SplitMix ذلك

∃c ∃d ∃x ∃y مرتبط

وهذا يعني ، باختيار c و d و x و y بشكل متعاكس ، يمكنك إظهار الارتباط.

الاختلاف في القوة في البيانين مذهل للغاية. محاولة الخلط بين العبارتين غير صحيحة.

vigna لقد تم تحذيرك الآن مرتين بشأن قواعد السلوك الخاصة بنا ، بواسطة mattip وrkern. استخدام لغة مثل "تحطيم عمل الآخرين" و "محاولة الخلط بين العبارتين هو تلاعب محض" ليس جيدًا. اعتبر هذا آخر تحذير لك. يرجى تغيير نغمتك وإلا _ سنحظرك. الحجج الفنية لا تزال موضع ترحيب ، أي شيء آخر ليس في هذه المرحلة.

لقد قمت بتعديل الرسالة مع استبدال تلك التعبيرات بأخرى محايدة. ما زلت أعتقد أن مهاجمة مشارك آخر شخصيًا في المناقشة ("سيباستيانو لديه القليل من الشيء حول PCG وكان يهاجمها لسنوات") غير مناسب تمامًا. أنا مندهش جدا ليس لك.

للمرة الثالثة والأخيرة ، فإن المناقشة حول SplitMix ، في أي من الاتجاهين ، لا تساعدني على الإطلاق. يمكنني أن أفهم لماذا تعتقد أنه يوفر السياق المطلوب ، أو أنك تشعر بأنك مضطر للرد على الآخر ، ولكن يرجى الوثوق بأنني أخبرك بالحقيقة أنه لا يوفر لي أي معلومات تساعدني في اتخاذ قرار هنا. كلاكما لديه مواقع الويب الخاصة بك. استخدمهم.

لقد قمت بتعديل الرسالة مع استبدال تلك التعبيرات بأخرى محايدة.

شكرا لك.

ما زلت أعتقد أن مهاجمة مشارك آخر شخصيًا في المناقشة ("سيباستيانو لديه القليل من الشيء حول PCG وكان يهاجمها لسنوات") غير مناسب تمامًا. أنا مندهش جدا ليس لك.

أنا أفضل ألا أرى ذلك أيضًا. لكن نبرة هذه الرسالة ليست بهذا السوء تقريبًا.

سأكون ممتنًا للغاية إذا كان بإمكانكما التمسك ببيانات واقعية بناءة vigna وimneme.

حسنا. لنبدأ من نقطة الصفر: أنت تريد مولدًا بنوع من التدفقات على أساس LCG مع معامل طاقة 2 للراحة والسرعة. تشير الأدبيات إلى أن التدفقات المستندة إلى ثوابت LCG المضافة قد تقودك إلى مشاكل (كما يحدث الآن) ، لكن دعنا نفترض أن هذا ما تريده.

لماذا لا تأخذ LCG مع حالة 128 بت ومضاعف جيد (65 بت على الأقل) وتشوش البتات العلوية باستخدام وظيفة المزج من SplitMix ، والتي تم اختبارها بشدة في تطبيقات مختلفة (التجزئة ، PRNG ، إلخ) ، يعطي نتائج ممتازة؟

أنا متأكد من أن الفرق في السرعة سيكون هامشيًا. ولديك بعض الضمانات (الإحصائية) بأن النتيجة ستعتمد على جميع البتات ، وهذه هي المشكلة هنا.

يبدو لي هذا أكثر من نهج "الوقوف على كتف العمالقة" من وظائف الخلط اليدوية على مولد لديه مشاكل الارتباط الذاتي.

imneme ما يمكنني استخدامه هو منشور مدونة حول DXSM يسهل الارتباط به أكثر من تعليق الإعلان في الإصدار القديم الضخم. لا يجب أن يكون أكثر بكثير مما ورد في هذا التعليق ، ولكن تضمين الحالة الحالية للاختبار الذي ذكرته هنا سيكون جيدًا. إذا أردت تلخيص بعض المناقشات من القضية الكبرى التي أدت إلى هذا التطور ، فسيكون ذلك مفيدًا بالتأكيد ، لكنه ليس ضروريًا تمامًا.

تضمين التغريدة

لماذا لا تأخذ LCG مع حالة 128 بت ومضاعف جيد (65 بت على الأقل) وتشوش البتات العلوية باستخدام وظيفة المزج من SplitMix ، والتي تم اختبارها بشدة في تطبيقات مختلفة (التجزئة ، PRNG ، إلخ) ، يعطي نتائج ممتازة؟

أعتذر إذا كان هذا يبدو خادعًا (على الرغم من أنه سيتم الإشارة إليه بالتأكيد) ، ولكنه أيضًا صادق: أتطلع إلى رؤية التنفيذ والتحليل والمعايير ونتائج PractRand على موقع الويب الخاص بك أو على arXiv. نحن (على قدر معقول من المعلومات) ممارسون هنا ، ولسنا باحثين في PRNG ، ولسنا مجهزين بشكل جيد لتنفيذ هذا الاقتراح. أستطيع أن أرى معنى ذلك ، لكن بالنظر إلى القيود الأخرى على وقتي الشخصي ، ليس لدي ميل لبذل الجهد لأخذ هذا من الاقتراح إلى التنفيذ والتحليل. إذا كنت تعالج هذا الاقتراح إلى numpy ، فنحن بحاجة إلى باحثين PRNG للقيام بهذا العمل. إذا كنت تقوم بالفعل بتوجيه هذا الاقتراح إلى شخص آخر ، فاستخدم موقع الويب الخاص بك.

من المفترض أن تكون بنية Generator -> BitGenerator -> SeedSequence العشوائية في NumPy قابلة للتوصيل. أعتقد أننا وصلنا إلى النقطة في المناقشة حيث نحتاج إلى شخص ما لفتح علاقات عامة لـ BitGenerator ، حتى نتمكن من مقارنة سماته العملية مع السمات الموجودة حاليًا في NumPy. بمجرد أن يصبح جزءًا من المشروع ، يمكننا الاستمرار في اختباره وقد نقرر جعله افتراضيًا. آمل أن يستند هذا القرار إلى

  • عدم التحيز (ومعايير أخرى؟ أنا أتنازل للخبراء)
  • أداء
  • احتمال حدوث أنواع مختلفة من تضارب الدفق عبر الواجهات المعيارية التي نروج لها: باستخدام BitGenerator.spawn و SeedSequence .

شخصيًا ، فقدني هذا النقاش عندما تجنب مناقشة مزايا BitGenerators عبر الكود الذي يستخدم الواجهة spawn . هناك سبب يدعو إلى الترويج لها كأفضل ممارسة ، وآمل أن تركز مناقشة العلاقات العامة المستقبلية على أفضل الممارسات لمستخدمي NumPy .

ربما يكون أحد الاستنتاجات هنا هو أننا يجب أن نسمح فقط spawn كطريقة ، لأن استخدام jumped أو advance قد يتعارض مع الممارسات الجيدة. قد يكون إصدار قضية جديدة أو خطة تشغيل وطنية تركز على هذا الأمر مثمرًا أيضًا.

mattip يؤثر تضارب عيد الميلاد ذو البتات الأدنى الذي لاحظتهvigna على واجهة SeedSequence.spawn() أيضًا. يرجى التأكد من أن أي جزء من المناقشة التي شاركت فيها يتعلق بالاستخدام السليم لواجهات برمجة التطبيقات الخاصة بنا.

لا يتطلب الأمر سوى إضافة حوالي 8 أسطر إلى pcg64.c مع بعض كتل #ifdef لاستخدام

من المحتمل أن أكون أكثر وضوحًا حيال ذلك ، خاصةً بالنسبة لرياضيات 128 بت التي تمت مضاهاتها لتلك الأنظمة الأساسية التي تحتاجها.

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

بدا الأمر أسهل من ذلك بالنسبة لي لأنه يستخدم مضاعف 64 بت "رخيص". يمكنك فقط إضافة خلاط إخراج جديد (هذا ثابت) ثم ifdef حول السطر الأخير للمولد العشوائي الذي يأخذ إخراج LCG ثم يطبق الخلاط.

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

إذا أراد المرء أن يضيف حتى في Murmur Hash 3 في هذه المرحلة ، فهل تميل إلى ذلك.

هل سيتم تجميع بيانات if بعيدًا؟ لا أعتقد أننا نريد مضاعفات منهم داخل الحلقات الساخنة.

مرة أخرى ، يعود هذا إلى الاختلاف في الغرض بين randomgen و numpy . من المنطقي في randomgen عائلات ذات معلمات ، ولكن في numpy ، لا أعتقد أنها فكرة جيدة أن تشابك عمليات تنفيذ BitGenerator القديم من الإعداد الافتراضي النشط BitGenerator . إذا اضطررنا إلى إجراء أي صيانة أو إعادة بناء للأداء على أحدهما أو الآخر ، فسيؤدي ذلك فقط إلى جعل هذا الجهد أسوأ وليس أفضل.

أتفق مع روبرت هنا. ليس لدي أي مخاوف بشأن وضع مولد بت جديد في الإصدار 1.19.0 ، فلن يغير أي سلوك حالي.

bashtage أيضًا ، لاحظ أن pcg_cm_random_r() يستخدم الحالة التكرارية مسبقًا للإخراج بدلاً من الحالة اللاحقة التكرارية ، لذلك لن يكون من السهل الحفاظ على نفس مسار الكود مع #ifdef أو if مفاتيح

هل سيتم تجميع بيانات if بعيدًا؟ لا أعتقد أننا نريد مضاعفات منهم داخل الحلقات الساخنة.

لا ، في NumPy ، يجب أن يصبح if else شيئًا مثل

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

هذه تحتاج إلى تعريف منفصل في إصدار uint128 وفي الإصدار الخلفي للتعامل مع تحويل uint128 يدويًا إلى أعلى ومنخفض.

bashtage أيضًا ، لاحظ أن pcg_cm_random_r() يستخدم الحالة المتكرّرة مسبقًا للإخراج بدلاً من الحالة اللاحقة التكرارية ، لذلك لن يكون من السهل الحفاظ على نفس مسار الكود مع #ifdef أو if .

حسنًا ، لقد اختبرت التنفيذ المرجعي imneme وحصلت على تطابق 100٪ على 1000 قيمة باستخدام بذرتين متميزتين:

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

AFAICT (وربما أكون مخطئا)

https://github.com/imneme/pcg-cpp/blob/master/include/pcg_random.hpp#L174

و

https://github.com/imneme/pcg-cpp/blob/master/include/pcg_random.hpp#L1045

يعني أن المسار uint_128 يستخدم دائمًا مُضاعِفًا رخيصًا.

لست متأكدًا مما تحاول قوله هناك.

من غير الواضح ما هو PCG64 DXSM المتعارف عليه. في كلتا الحالتين ، تستخدم وظيفة الإخراج عمليات 64 بت فقط. الإصدار الذي تستخدمه يستخدم مضاعف 64 بت في مكان آخر ليكون أسرع ويعود قبل النشر بدلاً من النشر. setseq_dxsm_128_64 هو الامتداد الطبيعي لـ PCG64 الحالي ويغير فقط وظيفة الإخراج.

حسنا أرى ذلك. لا ، لقد استخدمت مولد C ++ مختلفًا عن الذي قمت بتطبيقه في C. لقد قمت بتطبيق ما يعادل cm_setseq_dxsm_128_64 الذي يستخدم "المضاعف الرخيص" في تكرار LCG ، وليس setseq_dxsm_128_64 الذي لا يزال يستخدم المضاعف الكبير في تكرار LCG. يتم إعادة استخدام "المضاعف الرخيص" داخل وظيفة إخراج DXSM ، ولكن هذا محور تصميم متعامد.

لماذا لا تفضل setseq_dxsm_128_64؟

قالت imneme إنها ستقوم في النهاية بتغيير pcg64 الرسمي في إصدار C ++ للإشارة إلى cm_setseq_dxsm_128_64 ، وليس setseq_dxsm_128_64 . يعوض المضاعف الرخيص بعض التكلفة الإضافية لـ DXSM مقارنة بـ XSL-RR. وأعتقد أنه البديل الذي قضت شهرين في اختباره.

يعد إخراج حالة التكرار المسبق أيضًا جزءًا من عثرة الأداء .

إليك بعض المواعيد:

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)

كل ذلك على Ubuntu-20.04 ، المترجم الافتراضي.

6٪ أبطأ. يبدو أنه اختلاف بسيط بالنسبة لي. جميع الأوقات في NumPy / randomgen بعيدة جدًا عما يمكنك الحصول عليه في حلقة ضيقة فعلية من الكود الأصلي.

قارن

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)

إلى ما تم نشره من كود C (أبطأ بنسبة 150٪ ؟؟).

منحت ، في سياق numpy ، لا يهم كثيرًا. إنها مهمة أكثر في سياق C ++ ، مما أدى إلى تخصيص أشهر الكتلة للاختبار والترشيح باعتباره الافتراضي المستقبلي pcg64 في كود C ++ الرسمي. هذه هي الدوافع المباشرة لـ numpy ، IMO.

الفرق بين المخزون PCG64 و PCG64DXSM الخاص بي في الفرع الخاص بي ("المضاعف الرخيص" ، دالة إخراج DXSM ، إخراج الحالة المتكرر مسبقًا ، مسار الكود المنفصل):

[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

ما زلت أقول إنه ليس سوى عدد قليل (أكثر مما كان لدي) #ifdefs بين الاثنين ، حتى مع تطبيق متخصص لـ MSVC. بالإضافة إلى أن مستخدمي RSN MS سيكونون قادرين على استخدام clang # 13816 👍.

هل نتجادل حول تكرار الكود؟ أفضل بكثير أن يكون لدي تطبيقات منفصلة بدلاً من القلق بشأن بضعة أسطر من التعليمات البرمجية مشوشة باستخدام #ifdefs :)

كانت في الغالب مجرد مزحة ، على الرغم من أنها سلطت الضوء على الحاجة إلى بيان واضح تمامًا يحدد "PCG 2.0" (ويفضل في مكان ليس به مشكلات GitHub من NumPy).

شكرًا ، rkern et al.

imneme ما يمكنني استخدامه هو منشور مدونة حول DXSM يسهل الارتباط به أكثر من تعليق الإعلان في الإصدار القديم الضخم. لا يجب أن يكون أكثر بكثير مما ورد في هذا التعليق ، ولكن تضمين الحالة الحالية للاختبار الذي ذكرته هنا سيكون جيدًا. إذا أردت تلخيص بعض المناقشات من القضية الكبرى التي أدت إلى هذا التطور ، فسيكون ذلك مفيدًا بالتأكيد ، لكنه ليس ضروريًا تمامًا.

هل لديك إطار زمني في الاعتبار؟ لقد كنت أنوي القيام بذلك لبعض الوقت وتم دفعه من قبل أشياء أخرى ، لذا فإن وجود موعد نهائي مقترح سيكون حافزًا مفيدًا بالنسبة لي. ربما أسبوع؟ اثنان؟

نقلrkern أيضًا عن vigna ، الذي كتب:

لماذا لا تأخذ LCG مع حالة 128 بت ومضاعف جيد (65 بت على الأقل) وتشوش البتات العلوية باستخدام وظيفة المزج من SplitMix ، والتي تم اختبارها بشدة في تطبيقات مختلفة (التجزئة ، PRNG ، إلخ) ، يعطي نتائج ممتازة؟

FWIW ، تمت مناقشة هذا النهج في ورقة PCG الأصلية ، باستخدام _FastHash_ كوظيفة التجزئة الجاهزة ، وهي وظيفة تجزئة متعددة xorshift مشابهة جدًا. في الاختبار الذي أجريته ، لم تكن السرعة مثل التباديل الأخرى ، ولكنها كانت عالية الجودة. ذكر سيباستيانو أيضًا هذه الفكرة في نقده لعام 2018 لـ PCG وأنا ناقشها في هذا القسم من ردي على هذا النقد.

في النسخة الأصلية من نقد PCG الخاص به ، انتهى بكتابة متغير PCG الخاص به ، والذي سأقتبس أدناه:

        #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);
        }

منذ ذلك الحين ، قام بتحديث الكود في نقده إلى إصدار أسرع يستخدم مُضاعِفًا أرخص ويخفض الثابت الإضافي إلى 64 بت فقط ،

        #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);
        }

مشكلتي مع هذين المتغيرين هي أن التقليب قابل للعكس لأن الحالة المقطوعة (النصف العلوي) مقلوبة / مشوشة - يمكنك تشغيلها للخلف وتفكيك التدافع ، مما يتركك مع LCG مجرد اقتطاع مع جميع العيوب الكامنة فيه. أفضل تبديل / خداع الحالة بأكملها ثم إخراج اقتطاع من ذلك. (بالطبع ، سيكون التناوب / الخلط بين عدد أقل من البتات هو الطريقة الأسرع - كالمعتاد هناك مقايضات. يمكن للأشخاص العقلاء أن يختلفوا فيما هو مهم)

لكن عمله في صنع متغير PCG الخاص به قدم إلهامًا مفيدًا للغاية لتقليب DXSM عندما كتبت ذلك العام الماضي.

charris ما هي شهيتك لجعل تنفيذ PCG64DXSM متاحًا (ولكن ليس افتراضيًا بعد) في 1.19.0؟ ما هذا الجدول الزمني؟ أرى أن لدينا بالفعل 1.19.0rc2 تم إصداره ، وهو ليس _ عظيم_ لإدخال ميزة جديدة. مرة أخرى ، أنا لست متشددًا بشأن هذه المشكلة. أميل إلى إصدار 1.19.0 فقط لتوثيق سياستنا حول التغييرات على default_rng() وإدخال أشياء جديدة في 1.20.0.

rkern يجب أن يكون متاحًا لمدة تزيد عن أسبوعين ، لذلك نحن نبحث عن إصدار في وقت ما في النصف الأخير من شهر يونيو. أنا أؤيد وضع PCG64DXSM كخيار اختياري إذا كان يسهل الاختبار ، ولا أعتبره حقًا ميزة جديدة ، مثل ملحق جديد. وأحيانًا يساعد في تحريك الأشياء للحصول على كود عمل حقيقي هناك. NumPy هو محدد الاتجاه :)

تحرير: على افتراض ، بالطبع ، أنه لا توجد مشكلات كبيرة في الكود الجديد ، ولا يبدو أنه يوجد. أنا أيضًا لست قلقًا جدًا بشأن مشاكل PCG64 ، يبدو من غير المحتمل أن يواجه أي شخص مشاكل في استخدام إجراءاتنا الموصى بها.

imneme أسبوع واحد سيكون رائعًا. سيكون أسبوعان على ما يرام. شكر!

هناك سؤال كنت أطرحه على نفسي وهو إلى حد ما خارج الموضوع. نريد أن تنتج مولدات البت الخاصة بنا بتات عشوائية ، لكن AFAICT ، تتضمن معظم الاختبارات أعدادًا صحيحة. ما مدى جودة الاختبارات الحالية في اختبار البتات فعليًا؟ إذا تمكن شخص أكثر دراية بالمنطقة من الإجابة على هذا السؤال ، فسأكون في غاية الامتنان.

ما يتم اختباره هو تدفق البتات. نحن نخبر برنامج الاختبار بالحجم الطبيعي للكلمة PRNG الذي ننتجه ، ولكن فقط حتى يتمكن من القيام بأفضل الطيات للبتات لإثارة أخطاء تميل إلى الظهور في الأجزاء المنخفضة أو العالية من كلمة في PRNGs سيئة. البرنامج الذي نميل إلى استخدامه جميعًا هذه الأيام هو PractRand ، واختباراته موثقة بشكل خفيف هنا . ربما تكون أفضل ورقة يمكن قراءتها هي تلك الخاصة بـ TestU01 ، مجموعة الاختبار القياسية الذهبية السابقة. يحتوي دليل المستخدم الخاص به على مزيد من التفاصيل حول الاختبارات.

أعتذر إذا كان هذا يبدو خادعًا (على الرغم من أنه سيتم الإشارة إليه بالتأكيد) ، ولكنه أيضًا صادق: أتطلع إلى رؤية التنفيذ والتحليل والمعايير ونتائج PractRand على موقع الويب الخاص بك أو على arXiv. نحن (على قدر معقول من المعلومات) ممارسون هنا ، ولسنا باحثين في PRNG ، ولسنا مجهزين بشكل جيد لتنفيذ هذا الاقتراح. أستطيع أن أرى معنى ذلك ، لكن بالنظر إلى القيود الأخرى على وقتي الشخصي ، ليس لدي ميل لبذل الجهد لأخذ هذا من الاقتراح إلى التنفيذ والتحليل. إذا كنت تعالج هذا الاقتراح إلى numpy ، فنحن بحاجة إلى باحثين PRNG للقيام بهذا العمل. إذا كنت تقوم بالفعل بتوجيه هذا الاقتراح إلى شخص آخر ، فاستخدم موقع الويب الخاص بك.

أستطيع أن أفهم تماما وجهة نظرك. كان الرمز والمعيار في أسفل الصفحة يعلقان على مشاكل PCG (http://prng.di.unimi.it/pcg.php) منذ بضع سنوات بالاسم LCG128Mix. يتطلب الأمر 2.16ns على أجهزتي ، وحدة المعالجة المركزية Intel (R) Core (TM) i7-7700 @ 3.60 جيجاهرتز ، مع gcc 9.2.1 و fno-move-loop-invariants -fno-unroll-loops.

الكود بسيط للغاية - فهو يجمع بين LCG القياسي ووظيفة الخلط القياسية (المحسن النهائي لـ MurmurHash3 من ستافورد). لقد قمت بتعديله قليلاً للحصول على ثابت قابل للبرمجة:

    #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);
    }

كما أوضحت من قبل ، فإن ثابت 65 بت أفضل بكثير من أي ثابت 64 بت كمضاعف ، بسبب المشاكل النظرية المتعلقة بالمضاعفات الأصغر من الجذر التربيعي للمعامل.

إذا كنت مهتمًا بتصميم أكثر مبادئًا ، فسأجري اختبارات PractRand. ومع ذلك ، يجب أن تأخذ في الاعتبار أن وظيفة الخلط هذه أسفرت عن مولد ممتاز ، SplitMix ، حتى مع وجود مولد أساسي أضعف بكثير (كان مجرد مادة مضافة) ، وبحالة أصغر (64 بت). لذلك سيكون مجرد "أفضل" من SplitMix ، الذي يمر من PractRand بسرعة 32 تيرابايت.

والمولد الأساسي هو LCG ، لذلك لديك كل الأجراس والصفارات المعتادة من الستينيات: القفزات ، والمسافات ، وما إلى ذلك. حالة.

إذا كنت تفكر في وجود معايير مقارنة ببعض المولدات الأخرى ، أو استخدام المجمعين الآخرين ، فيرجى إبلاغي بذلك.

ولكن ، من فضلك ، بنفس الطريقة المخلصة: فقط إذا كنت مهتمًا حقًا بالتفكير في تصميم "الوقوف على أكتاف العمالقة" باستخدام المكونات القياسية فقط. هناك قيود شخصية على وقتي أيضًا ، وأنا سعيد بالمساهمة ، لكني أرغب في تجنب قضاء الوقت على مولد ليس لديه فرصة للنظر فيه.

راجع للشغل ، لإعطاء مقياس أكثر واقعية لكيفية تحسين جودة المضاعفات المعنية ، قمت بحساب الدرجات الطيفية ، من f₂ إلى f₈ ، لمضاعف 64 بت الحالي المستخدم بواسطة PCG DXS وبعض البدائل.

الدرجات الطيفية هي الطريقة القياسية للحكم على جودة المضاعف. 0 سيئ ، 1 ممتاز. تصف كل درجة كيف يتم توزيع الأزواج ، والثلاثي ، و 4-tuples ، وما إلى ذلك في الإخراج.

يمكن استئناف هذه الأرقام السبعة في المقياس الكلاسيكي ، أو الحد الأدنى ، أو مقياس مرجح (الدرجة الأولى ، بالإضافة إلى الثانية مقسومة على اثنين ، وما إلى ذلك ، طبيعية) ، لجعل الدرجات الأولى أكثر أهمية ، كما اقترح Knuth في TAoCP ، وهذا هو الحد الأدنى والمقياس المرجح للمضاعف الحالي:

0xda942042e4dd58b  0.633  0.778

هناك ثوابت 64 بت أفضل بكثير من ذلك:

0xff37f1f758180525  0.761  0.875

إذا انتقلت إلى 65 بت ، بنفس السرعة بشكل أساسي (على الأقل ، بالنسبة لـ LCG128Mix هي نفس السرعة) ، فستحصل على مقياس مرجح أفضل:

0x1d605bbb58c8abbfd  0.761  0.899

والسبب هو أن مضاعفات 64 بت لها حد جوهري لدرجاتها f≤ (≤0.93) ، كما هو ملاحظ من قبل Knuth هو الأكثر صلة:

0xda942042e4dd58b5  0.795
0xff37f1f758180525  0.928
0x1d605bbb58c8abbfd  0.992

لذا فإن المضاعف الأول له درجة f₂ متوسطة. يقترب المضاعف الثاني جدًا من المستوى الأمثل لمضاعف 64 بت. لا يحتوي المضاعف 65 بت على هذه القيود وله درجة قريبة جدًا من 1 ، وهو أفضل ما يمكن بشكل عام.

للتأكد من اكتمالها ، إليك جميع الدرجات:

 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

يمكنك إعادة حساب هذه النقاط أو البحث عن المضاعف الخاص بك باستخدام الرمز Guy Steele وأنا وزعته: https://github.com/vigna/CPRNG . المضاعفات الأفضل مأخوذة من الورقة المرتبطة.

من المحتمل أن يكون PCG prng افتراضيًا جيدًا لـ numpy ، لكنني لا أعتقد أنه سيصمد أمام اختبار الزمن ، حيث توجد طرق واعدة أكثر ، ولكنها أقل اختبارًا للقيام بذلك. أقترح واحدة في ما يلي.

يعتبر SFC64 نصف الفوضوي أحد أسرع المولدات ذات الصوت الإحصائي مع فترة زمنية كبيرة معقولة. لا يحتوي SFC64 على وظائف قفزة ، ولكن يمكن تمديده بدون زيادة السرعة لدعم 2 ^ 63 تدفقات فريدة مضمونة. ما عليك سوى إضافة تسلسل Weyl مع ثابت مضاف يختاره المستخدم (يجب أن يكون فرديًا) ، بدلاً من مجرد زيادة العداد بمقدار واحد. كل ك فردي ينتج فترة كاملة فريدة. يتطلب الأمر 64 بتًا إضافيًا من الحالة للاحتفاظ بثابت ويل:

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;
}

في بعض الأحيان تكون حالة 320 بت غير مرغوب فيها ، لذلك حاولت الضغط عليها لاستخدام 256 بت مرة أخرى. لاحظ أيضًا وظيفة الإخراج المتغيرة ، والتي تستخدم بشكل أفضل تسلسل Weyl لخلط البتات. يستخدم 128/128 بت حالة فوضوية / منظمة ، والتي يبدو أنها تحقق توازنًا جيدًا:
/ تحرير: تمت إزالة rotl64 () من إخراج func + تنظيف ، 6 أغسطس:

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;
}

لقد اجتاز هذا حاليًا 4 تيرابايت في اختبار PractRand بدون حالات شاذة ، وقد أجريت لفترة وجيزة اختبار وزن هامينج Vigna دون مشاكل حتى الآن (على الرغم من أن اجتياز هذه الاختبارات ليس ضمانًا للإخراج العشوائي الحقيقي تقريبًا ، بل هو اختبار ما إذا كان prng معيبًا أم لا ).

ملاحظة: يُفترض إحصائيًا أن استخدام ثابت Weyl عشوائي (فريد) مع ما يقرب من 50٪ من مجموعة البت هو ميزة إحصائية ، ولكن فقط المزيد من الاختبارات أو التحليل سيكشف مدى أهمية ذلك.

/ عمليات التحرير: عمليات التنظيف.

@ tylo-work SFC64 موجود بالفعل في NumPy ، جنبًا إلى جنب مع Philox ، هذا يتعلق بالمولد الافتراضي.

حسنًا ، لم أكن أعرف بالضبط ما الذي تم تنفيذه ، لذا فإن هذا يتعلق فقط باختيار الأكثر ملاءمة بشكل عام من هؤلاء؟ عادل بما يكفي وشكرا للتوضيح

سأحاول اختبار المولد المقترح على نطاق واسع لمعرفة كيف يتراكم مع الآخرين ، وحتى الآن يبدو جيدًا جدًا فيما يتعلق بالسرعة وجودة الإخراج والبساطة / الحجم / قابلية الاستخدام ، وللاستخدام المتوازي الهائل. لكنني سأكون سعيدًا إذا اختبرها الآخرون أيضًا.

الإصدار في NumPy هو البديل القياسي الذي يحتوي على k=1 .

https://github.com/numpy/numpy/blob/ad30b31af0bb3fbfdc0f11486807edc76cec2680/numpy/random/src/sfc64/sfc64.h#L25 -L33

لا أعتقد أننا نعيد فتح المناقشة حول PRNG الافتراضي من البداية. لدينا مشكلة محددة للغاية مع PRNG الحالي لدينا وننظر في المتغيرات المتاحة وثيقة الصلة التي تعالج هذه المشكلة المحددة. يتمثل أحد مخاوفنا في أن PRNG الافتراضي الحالي يعرض ميزات معينة لـ PRNG ، مثل القابلية للقفز ، والتي لا يزال يتعين على المتغير الذي يحل محله الكشف عنها. لا تحتوي SFC64 (سواء الخاصة بنا أو الخاصة بك) على هذه الميزة.

من المحتمل أن يكون bashtage على استعداد لقبول العلاقات العامة لـ randomgen لإضافة متغيرات Weyl-stream الخاصة بك من SFC64.

@ tylo-work إذا كنت مهتمًا بالتنفيذ المتوازي ، فقد ترغب في إلقاء نظرة على تنفيذ SeedSequence في NumPy.

لا أعتقد أننا نعيد فتح المناقشة حول PRNG الافتراضي من البداية. لدينا مشكلة محددة للغاية مع PRNG الحالي لدينا وننظر في المتغيرات المتاحة وثيقة الصلة التي تعالج هذه المشكلة المحددة.

بافتراض أنك تريد شيئًا يشبه PCG-DXS ، فهناك المزيد من التحسينات التي يمكنك القيام بها فقط باستخدام ثوابت أفضل (وتباطؤ هامشي للغاية). على سبيل المثال ، ستفشل PCG-DXS قريبًا في نوعين متميزين من الاختبارات على اثنين متشابهين ومرتبطين مع نفس الحالة 112 بتة:

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

لاحظ أننا نتحدث عن متواليات مترابطة ≈65536 فقط - ليس هناك ما نخاف منه.

ولكن يمكنك تحسين المولد باختيار مُضاعِف أفضل ، مثل 0x1d605bbb58c8abbfd ، وخلاط أفضل ، مثل 0x9e3779b97f4a7c15. الرقم الأول هو مضاعف 65 بت الذي يحتوي على درجات طيفية أفضل بكثير. الرقم الثاني هو فقط النسبة الذهبية في تمثيل نقطة التثبيت 64 بت ، ومن المعروف أن هذا له خصائص خلط لطيفة (انظر Knuth TAoCP حول التجزئة المضاعفة) ؛ على سبيل المثال ، يتم استخدامه بواسطة مكتبة Eclipse Collections لمزج أكواد التجزئة.

نتيجة لذلك ، تفشل فقط FPF لنفس كمية البيانات:

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

في الواقع ، إذا ذهبنا إلى أبعد من ذلك عند 2 تيرابايت PCG-DXS فشل _ ثلاثة_ نوع من الاختبارات لنفس التتابعات المتشابكة والمترابطة:

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

بينما PCG65-DXSϕ لا يزال يفشل فقط 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

عاجلاً أم آجلاً ، بالطبع ، ستفشل PCG65-DXSϕ أيضًا في Gap و TMFn. لكنك تحتاج إلى رؤية مخرجات أكثر بكثير من PCG-DXS.

هذا هو الكود الكامل لـ PCG65-DXSϕ ، وهو مجرد PCG-DXS بثوابت أفضل:

#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);
}

يرجع التباطؤ الهامشي إلى تعليمات الإضافة (الناتجة عن مضاعف 65 بت) ، وتحميل ثابتين من فئة 64 بت.

أنا لا أؤيد مولدات من هذا النوع بشكل عام ، لكن PCG65-DXSϕ أفضل بشكل ملموس من PCG-DXS في إخفاء الارتباط.

Vigna ، لمعلوماتك ، لقد s[0]=s[1]=s[2]=s[3] = k1 + stream*k2 . ثم يتم تخطي 12 ناتجًا ، وهذا هو أساسًا كيفية تهيئة sfc64.

أدرك أن هذه ليست التهيئة الموصى بها لـ xoshiro ، لكنها لا تزال مثيرة للاهتمام - ومقلقة بعض الشيء - أن الاختبارات بدت جيدة لـ xoshiro مع عدد قليل من تدفقات التشذير ، لكنها فشلت مع الكثير.

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

حاولت أيضًا إضعاف التهيئة لـ SFC64 و TYLO64 لتخطي مخرجات 2 فقط ، لكنهم ما زالوا على ما يرام.
فيما يتعلق بالأداء: يعمل xoshiro256 ** بنسبة 33٪ أبطأ على جهازي من الجهازين الآخرين. TYLO64 يقوم فقط بتحديث 196 بت من vars الحالة. هنا برنامج الاختبار:

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;
}

سأقوم بتضمين بعض رموز الرأس ذات الصلة:

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 أقدر التحليل ، لكني أحتاج حقًا إلى هذه المشكلة لأظل مركزًا. إذا كنت ترغب في مواصلة هذا الخط من المناقشة ، فأنا أشجعك على نشر عملك في Github repo الخاص بك ، وإنشاء منشور آخر هنا لدعوة الأشخاص الموجودين هنا إليه. أي شخص آخر ، يرجى الرد هناك. شكرا لتعاونكم.

وimnemerkern الوقت ينفد للإفراج 1.19.

rkern يبدو أن PCG64DXSM لن يصل إلى 1.19.0 ، سأصدر في نهاية هذا الأسبوع. إذا كان بإمكانك كتابة ملاحظة حول سياسة التغيير / التغييرات القادمة التي ذكرتها أعلاه ، فسأكون ممتنًا لك.

آسف ، لقد كنت أتعامل مع بعض الأمور الأخرى غير ذات الصلة. بناءً على مناقشتنا ، لا أعتقد أن التأخير البسيط يمثل مشكلة كبيرة ، حيث تم التخطيط لـ PCG64DXSM كخيار بديل ، وليس كخيار افتراضي جديد (في الوقت الحالي ، على الأقل).

الآن بعد أن بدأ 1.20 ، هل حان الوقت لإعادة النظر في هذا والانتقال إلى DXSM؟

سيظل لدينا بعض الوقت للقيام بهذه الخطوة قبل التفرع ، ولكن قد يكون من الجيد البدء في ذلك خلال الأسبوع المقبل أو نحو ذلك. bashtage أعتقد أن لديك PCG64DXSM جاهزًا للانطلاق وهذا يحتاج بشكل أساسي إلى قرار قلب التبديل على الدفق الافتراضي؟

من ما تراه ، بدا الأمر كما لو أننا يجب أن نفعل ذلك لـ 1.20 فقط إذا كان متوفرًا بسهولة.

IIRC ، كنا ننتظر مرجعًا يمكن ربطه. ولكن إذا كان الأشخاص ذوو الأرقام العشوائية سعداء بالتغيير ، فيجب علينا استخدامه. هل نحتاج إلى أي كود خاص للنوافذ؟

إنه مجرد ثابت مختلف ووظيفة تخليط مختلفة. لا شيء أكثر روعة من ما كتبهrkern لتطبيق PCG64 الأصلي على Windows. أعتقد أن القرار كان الحصول على PCG64DXSM مستقل تمامًا بدلاً من مشاركة بعض التعليمات البرمجية (للأداء).

ربما يكون من المنطقي البدء من فرع ويب rkern .

قلت إنني سأكتب بعضًا من منشور مدونة حول هذا الموضوع ، والذي أعتقد أن rkern ربما كان يحب يكلفك السرعة أو (إذا قمت بقطع الزوايا لزيادة السرعة) يضيف إمكانية تنبؤية تافهة.

هل كانت هذه الصفحة مفيدة؟
0 / 5 - 0 التقييمات