Numpy: حدد خيار PRNG BitGenerator الافتراضي الجديد

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

13163 سيحضر الاستبدال الذي طال انتظاره للبنية التحتية PRNG الخاصة بـ Numpy. من أجل الحفاظ على إمكانية إدارة العلاقات العامة ، سنقوم بدمجها لإتقانها قبل الانتهاء من جميع القرارات ، مثل أي BitGenerator سيتم ترشيحه ليكون الخيار الافتراضي.

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

من ناحية أخرى، واختيار الافتراضي لايوجد أن العديد من العواقب. نحن لا نتحدث عن الافتراضي BitGenerator الكامن وراء وظائف الراحة numpy.random.* . في 19 NEP ، تظل هذه أسماء مستعارة لـ RandomState ، الذي يبقى MT19937 BitGenerator MT19937 . المكان الوحيد الذي يأتي فيه الإعداد الافتراضي هو عندما يتم إنشاء مثيل Generator() بدون وسيطات ؛ على سبيل المثال ، عندما يطلب المستخدم Generator بحالة عشوائية ، من المفترض أن يستدعي طريقة .seed() عليه. قد يكون هذا نادرًا جدًا ، حيث سيكون من السهل فقط إنشاء مثيل له بشكل صريح باستخدام المصنف BitGenerator الذي يريدونه بالفعل. قد يكون الاختيار الصحيح هنا هو عدم ترشيح BitGenerator .

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

IMO ، هناك بعض الخيارات الرئيسية (مع تعليقي ، لا تتردد في عدم الموافقة ؛ لم أحاول نقل جميع التعليقات ذات الصلة من # 13163):

لا يوجد تقصير

طلب دائمًا Generator(ChosenBitGenerator(maybe_seed)) . هذا غير ودي بعض الشيء ، ولكن نظرًا لأنه طريقة مناسبة جدًا لتهيئة المولد بشكل صحيح للتكاثر ، فقد ينتهي الأمر بالناس للقيام بذلك على أي حال ، حتى لو كان لدينا افتراضيًا.

MT19937

سيكون هذا اختيارًا محافظًا جيدًا. إنه بالتأكيد ليس أسوأ من الوضع الراهن. نظرًا لأن Mersenne Twister لا يزال يُنظر إليه على نطاق واسع باعتباره الخيار "القياسي" ، فقد يساعد المستخدمين الأكاديميين الذين يحتاجون إلى مراجعة أوراقهم من قبل أشخاص قد يشككون في الخيارات "غير القياسية" ، بغض النظر عن الصفات المحددة لـ PRNG. "لم يُطرد أحد على الإطلاق بسبب توظيفه لشركة IBM." تتمثل الجوانب السلبية الرئيسية لـ MT19937 الغالب في أنها أبطأ من بعض البدائل المتاحة ، نظرًا لحالتها الكبيرة جدًا ، وفشل بعض اختبارات الجودة الإحصائية. عند اختيار PRNG آخر ، لدينا _ فرصة_ (ولكن ليس _ التزام_ ، IMO) يجب إبداء رأيها هنا ومحاولة نقل "المعيار" ، إذا أردنا.

PCG64

من المحتمل أن يكون هذا هو الشخص الذي سأستخدمه في أغلب الأحيان شخصيًا. الجانب السلبي الرئيسي هو أنه يستخدم حسابًا صحيحًا من 128 بت ، والذي يتم محاكاته في لغة C إذا لم يوفر المترجم مثل هذا النوع الصحيح. النظامان الأساسيان اللذان ينطبق عليهما هذا هو الحال مع وحدات المعالجة المركزية 32 بت و 64 بت MSVC ، والتي لا تدعم فقط الأعداد الصحيحة 128 بت حتى عندما تدعم وحدة المعالجة المركزية. أنا شخصياً لا أقترح السماح لوحدات المعالجة المركزية 32 بت - نادرة الأداء بشكل متزايد - بإملاء خياراتنا. لكن أداء MSVC مهم ، على الرغم من ذلك ، لأن إصدارات Windows الخاصة بنا تحتاج إلى هذا المجمع وليس برامج تجميع Windows الأخرى. من المحتمل أن تتم معالجتها ببعض جوهرية التجميع / المترجم ، ولكن يجب على شخص ما كتابتها. حقيقة أن MSVC _ فقط_ هو ما يجب علينا القيام به من أجل جعل هذا الأمر أكثر قبولا إلى حد ما من الأوقات الأخرى عندما نواجه التجميع.

Xoshiro256

خيار آخر حديث لـ PRNG صغير وسريع. لديها عدد قليل من المراوغات الإحصائية المعروفة ، ولكن من غير المرجح أن تكون عاملاً رئيسياً لمعظم الاستخدامات. هذه المراوغات تجعلني أخجل منها ، ولكن هذا هو خياري الشخصي للرمز الذي سأكتبه.

15 - Discussion numpy.random

التعليق الأكثر فائدة

مستوحاة جدًا من هذا الموضوع ، لدي بعض الأخبار التي أريد الإبلاغ عنها ...

خلفية

وفقًا للعديد من المقاييس ، فإن pcg64 جيد جدًا ؛ على سبيل المثال ، في ظل المقاييس المعتادة للجودة الإحصائية ، تحصل على شهادة صحية نظيفة. تم اختباره بطرق مختلفة. في الآونة الأخيرة ، قمت بتشغيله حتى نصف بيتابايت باستخدام PractRand. يعمل بشكل جيد في حالات الاستخدام العادي.

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

لذلك ، منذ حوالي 25 يومًا بدأت التفكير في تصميم عضو جديد في عائلة PCG ...

هدف

كان هدفي هو تصميم عضو جديد من عائلة PCG يمكن أن يكون بمثابة انخفاض في بديل للمتغير الحالي pcg64 . كما:

  • يجب أن تقوم وظيفة الإخراج بتشويش البتات أكثر من XSL RR (لأن القيام بذلك سيؤدي إلى تجنب المشكلات التي ظهرت في هذا الموضوع).
  • يجب أن يكون الأداء سريعًا (أو أسرع) من pcg64 .
  • يجب أن يكون التصميم PCG-ish (على سبيل المثال ، لا يمكن التنبؤ به بشكل تافه ، وبالتالي لا تسمح بسهولة التراجع عن أي عمل لوظيفة الإخراج).

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

المفسد

يسعدني الإبلاغ عن النجاح! منذ حوالي 25 يومًا عندما كنت أفكر في هذا الأمر لأول مرة ، كنت في الواقع في إجازة. عندما عدت قبل حوالي عشرة أيام ، جربت الأفكار التي كانت لدي وسعدت أن أجد أنها تعمل بشكل جيد. تم إنفاق الوقت التالي في الغالب على أنواع مختلفة من الاختبارات. بالأمس كنت راضيًا بدرجة كافية لدرجة أنني دفعت الرمز إلى إصدار C ++ من PCG. تشير الاختبارات ذات الأحجام الصغيرة إلى أنها أفضل بكثير من XSL RR ، ومنافسة مع RXS M ، لكنها في الواقع تتألق بأحجام أكبر. إنه يلبي جميع الأهداف الأخرى أيضًا.

تفاصيل

FWIW ، وظيفة الإخراج الجديدة (لحالة إخراج 64 بت):

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

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

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

تغييرات أخرى

كما انها حالة أن 0xda942042e4dd58b5 هو مضاعف LCG لهذا PRNG (وجميع cm_ مسبوقة مولدات PCG 128 بت للدولة). بالمقارنة مع 0x2360ed051fc65da44385df649fccf645 المستخدم بواسطة pcg64 ، فإن هذا الثابت لا يزال جيدًا إلى حد ما من حيث خصائص اختبار الطيف ، ولكنه أرخص للمضاعفة لأن 128 بت × 64 بت أسهل من 128 بت × 128 بت. لقد استخدمت ثابت LCG هذا لعدة سنوات دون مشكلة. عند استخدام متغير المضاعف الرخيص ، أقوم بتشغيل وظيفة الإخراج على الحالة المتكرّرة مسبقًا بدلاً من الحالة اللاحقة التكرارية من أجل توازٍ أكبر على مستوى التعليمات.

اختبارات

لقد اختبرت ذلك جيدًا (PractRand و TestU01) وأنا سعيد به. تضمنت الاختبارات السيناريوهات الموضحة في هذا الموضوع (على سبيل المثال ، أخذ مولدات العصابات إما على بخار متسلسل أو متقدم بمقدار 2 ^ 64 وتشذير مخرجاتها - لقد اختبرت عصابة من أربعة وعصابة من 8192 إلى 8 تيرابايت دون مشاكل ، كذلك كتيار ونظيره في الأرض).

سرعة

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

التوفر

يمكن لمستخدمي رأس C ++ الوصول إلى فرد العائلة الجديد هذا _now_ كـ pcg_engines::cm_setseq_dxsm_128_64 ؛ في مرحلة ما في المستقبل ، سأحول pcg64 من pcg_engines::setseq_xsl_rr_128_64 إلى هذا النظام الجديد. خطتي الحالية هي القيام بذلك هذا الصيف كجزء من نتوء إصدار PCG 2.0.

الإعلانات الرسمية

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

اختياراتك...

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

ال 166 كومينتر

ماذا يفعل مترجم windows من إنتل للأعداد الصحيحة 128 بت؟ ما مقدار أبطأ تجميع PCG64 باستخدام MSVC مقارنةً بـ MT1993 على Windows؟ أظن أنه سيتم استخدام ميزة الانتقال إلى الأمام على نطاق واسع ، لذا قد يكون من الجيد الحصول عليها بشكل افتراضي.

ماذا يفعل مترجم windows من إنتل للأعداد الصحيحة 128 بت؟

لست متأكدًا تمامًا ؛ لا أعرف ما إذا كانت هناك آثار ABI التي تهتم المحكمة الجنائية الدولية بتقييدها. إذا أردنا فقط الحصول على أي فكرة عن التجميع الذي تم إنشاؤه والذي يمكننا استخدامه ، فهذا مورد مفيد: https://godbolt.org/z/kBntXH

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

هل تقصد تيارات قابلة للضبط ، بالأحرى؟ هذه نقطة جيدة ، لكنني أتساءل عما إذا كانت قد لا تؤدي إلى الاتجاه الآخر. إذا كان اختيارنا الافتراضي مهمًا كثيرًا ، فربما إذا اخترنا واحدة من هذه الميزات الأكثر اكتمالا PRNGs ، فسيستخدم الأشخاص هذه الميزات على نطاق واسع في كود المكتبة دون توثيق أنهم يحتاجون إلى تلك الميزات "المتقدمة" ، لأنهم ، بعد كل شيء ، متوفرة "قياسي". ولكن بعد ذلك ، إذا حاول مستخدم آخر استخدام تلك المكتبة BitGenerator الأقل ميزات للسرعة أو لأسباب أخرى ، فسيصطدم بجدار من الطوب. في عالم No default أو MT19937 ، من المرجح أن تفكر المكتبات في الميزات المتقدمة التي تتطلبها وتوثقها.

من ناحية الإمساك ، فإن هذا الاحتمال سيجعل BitGenerator s بدون تدفقات قابلة للتعيين تبدو أقل استحسانًا ، وأنا لا أحب فكرة تقديم ما يعتبر أفضل ممارسة في هذا الاتجاه (شخصيًا بحت ؛ لا أشعر التزام بجعل NumPy-the-project يشترك في هذه الفكرة). قد يساعد في تجنب بعض الانتهاكات التي أراها مع الأشخاص .seed() ing في منتصف التعليمات البرمجية الخاصة بهم. لكن مرة أخرى ، كل هذا يعتمد على فكرة أن وجود تقصير سيغير سلوكيات الناس بشكل كبير ، لذلك من المحتمل أن تكون كل هذه المخاوف ضعيفة للغاية.

ما مقدار أبطأ تجميع PCG64 باستخدام MSVC مقارنةً بـ MT1993 على Windows؟

في المعايير التي نشرها bashtage في # 13163 ، تبلغ سرعة PCG64 ما يقرب من نصف سرعة MT19937 ، وهو أداء مخيب للآمال جدًا من MSVC والأصدقاء. بالمقارنة مع 23٪ أسرع على لينكس.

ماذا يفعل مترجم windows من إنتل للأعداد الصحيحة 128 بت؟

يقوم المترجمون الآخرون مثل Clang و GCC و Intel compiler بتطبيق الأعداد الصحيحة 128 بت على أنظمة 64 بت بنفس الطريقة التي طبقوا بها الأعداد الصحيحة 64 بت على أنظمة 32 بت. كل نفس التقنيات دون الحاجة إلى أفكار جديدة. لم تكلف Microsoft عناء القيام بذلك لـ MSVC لذلك لا توجد أعداد صحيحة 128 بت مدعومة مباشرة من قبل المترجم.

نتيجة لذلك ، بالنسبة لـ MSVC ، فإن التنفيذ الحالي لـ PCG64 في # 13163 يقوم يدويًا بتنفيذ رياضيات 128 بت عن طريق استدعاء عناصر جوهرية من Microsoft مثل _umul128 في x86_64 (ومن المفترض أيضًا أن يستخدم عناصر داخلية مكافئة وأكثر قابلية للنقل مثل

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

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

أنا سعيد لأنك تحب القفز إلى الأمام ، لكن لدي فضول لماذا تعتقد أنه سيتم استخدامه على نطاق واسع.

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

لم تكلف Microsoft عناء القيام بذلك لـ MSVC لذلك لا توجد أعداد صحيحة 128 بت مدعومة مباشرة من قبل المترجم.

سيضر ذلك بعجلاتنا ، OTOH ، يحصل العديد من الأشخاص على Windows على حزمهم من Anaconda أو En Thinkt ، وكلاهما يستخدم Intel ، ومن المحتمل أن يكون الأشخاص الذين يهتمون بالأداء على نظام Linux أو Mac أو ربما AIX.

تحرير: وربما إذا كانت مايكروسوفت مهتمة ، فيمكنهم تقديم مكافأة لإصلاح المشكلة.

FWIW ، هذا هو التجميع الذي سينشئه clang للوظيفة الحرجة ، بما في ذلك البتات اللازمة لفك / إعادة حزم uint128_t في بنية uint64_t s: https: // godbolt.org/z/Gtp3os

رائع جدا ،rkern. هل من الممكن أن تفعل الشيء نفسه لترى ما تفعله MSVC باستخدام كود 128 بت المكتوب بخط اليد؟

رائع جدا ،rkern. هل من الممكن أن تفعل الشيء نفسه لترى ما تفعله MSVC باستخدام كود 128 بت المكتوب بخط اليد؟

إنها ، آه ، ليست جميلة. ~ https://godbolt.org/z/a5L5Gz~

عفوًا ، نسيت إضافة -O3 ، لكنها لا تزال قبيحة: https://godbolt.org/z/yiQRhd

إنه ليس بهذا السوء. لم يتم تشغيل التحسين ، لذلك لم يتم تضمين أي شيء. لقد أضفت /Ox (ربما يوجد خيار أفضل؟). لقد أصلحت الكود أيضًا لاستخدام جوهر الدوران المدمج ( _rotr64 ) نظرًا لأن MSVC على ما يبدو غير قادر على اكتشاف لغة C rotate.

لا يزال نوعًا من حطام القطار. لكنني أعتقد أنه من العدل أن نقول أنه مع قليل من الاهتمام ، يمكن تعديل كود PCG64 لتجميعه على MSVC إلى شيء لا يمثل إحراجًا مطلقًا للجميع.

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

معظم مستخدمينا ليسوا خبراء أرقام عشوائية ، يجب أن نقدم الإعدادات الافتراضية لهم.

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

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

تحرير: توضيح المطورين الذين يجب أن يعرفوا ما يفعلونه

معظم مستخدمينا ليسوا خبراء أرقام عشوائية ، يجب أن نقدم الإعدادات الافتراضية لهم.

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

بعيدًا عن المألوف "يحتاجون الآن إلى كتابة المزيد من التعليمات البرمجية" ، ماذا يحدث عندما نغير شيئًا ما؟

ما "الشيء" الذي تفكر فيه؟ لا أستطيع متابعة حجتك.

بعيدًا عن المألوف "يحتاجون الآن إلى كتابة المزيد من التعليمات البرمجية" ، ماذا يحدث عندما نغير شيئًا ما؟

ما "الشيء" الذي تفكر فيه؟ لا أستطيع متابعة حجتك.

mattip يشير إلى تغيير منشئ البت الافتراضي.

هذا woudl يجعل المستخدمين الذين تبنوه مجانين ، ويتطلب coudl بعض التغيير في الكود.

على سبيل المثال ، إذا كنت تستخدم

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

وتم تغيير منشئ البت الأساسي ، فسيكون هذا خطأ.

إذا فعلت الشيء الأكثر عقلانية واستخدمت

Generator(BitGenerator(1234))

ثم لن تراها.

IMO ، عند التفكير في اختيار الافتراضي ، يجب أن نعتقد أنه تم إصلاحه حتى يتم العثور على خطأ فادح في منشئ البت الأساسي أو تضيف Intel QUANTUM_NI إلى شرائحها ، مما ينتج عنه تحسينات كثيرة في OOM في الأداء العشوائي.

أدرك أنني غريب قليلاً هنا ، لكنني لا أعتقد أنه من المعقول أن نتوقع أن خيار PRNG هو الخيار الافتراضي ثابتًا إلى الأبد ولا يتغير أبدًا. (في C ++ ، على سبيل المثال ، يخضع std::default_random_engine لتقدير التنفيذ ويمكن أن يتغير من إصدار إلى إصدار.)

بدلاً من ذلك ، يجب أن تكون هناك آلية لإعادة إنتاج النتائج السابقة. وبالتالي بمجرد وجود تطبيق معين ، من غير الجيد تغييره (على سبيل المثال ، MT19937 _is_ MT19937 ، لا يمكنك تعديله لإعطاء مخرجات مختلفة). [ومن غير الجيد أيضًا إزالة تطبيق موجود بالفعل.]

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

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

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

(FWIW ، هذا ما فعلته في PCG. إن PCG الافتراضي 32 بت PRNG هو حاليًا متغير XSH-RR [تم الوصول إليه كـ pcg_setseq_64_xsh_rr_32_random_r في مكتبة C و pcg_engines::setseq_xsh_rr_64_32 فئة في C ++ مكتبة] ، ولكن من حيث المبدأ ، إذا كنت تريد حقًا إمكانية التكاثر في المستقبل ، فيجب عليك تحديد XSH-RR بشكل صريح ، بدلاً من استخدام pcg32_random_r أو pcg32 وهي أسماء مستعارة ومن حيث المبدأ يمكن ترقيتها إلى شيء آخر .)

إنه ليس إلى الأبد حقًا (هذا المشروع بأكمله 90 ٪ مدفوعًا بوعد حقيقي وحقيقي ومحترم إلى الأبد تم تقديمه منذ حوالي 14 عامًا) ، ولكن كما تقول ، فإن تبديل الاحتياجات (أ) سبب مقنع للتغيير و (ب) يستغرق ما لا يقل عن بضع سنوات لإعطاء دورة الاستهلاك.

من الأفضل كثيرًا أن تحاول جاهدًا اليوم لتقريبها من اليمين قدر الإمكان.

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

على سبيل المثال ، إذا كنت تستخدم

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

وتم تغيير منشئ البت الأساسي ، فسيكون هذا خطأ.

حسنًا ، يبدو أن هذا يجادل ، مع @ eric-wieser ، للخيار "بلا افتراضي" ، والذي لا يمكنني مواءمته مع العبارة الأولية "معظم مستخدمينا ليسوا خبراء أرقام عشوائية ، يجب أن نقدم لهم الإعدادات الافتراضية ".

بين عدم التقصير والودية ، على افتراض كامل ، سأختار دائمًا الخيار الأخير:

الآن:

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

_أفضله:

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

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

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

نعم لدينا ذلك. يمكن للمستخدمين الحصول على BitGenerator s بالاسم (على سبيل المثال ، MT19937 ، PCG64 ، إلخ.) وتكوينهم بالبذور. BitGenerator الكائنات [0..1) float64 s والأعداد الصحيحة (بالإضافة إلى أي إمكانيات القفز / الدفق الممتعة لديهم) . فئة Generator التي نتحدث عنها تأخذ عنصر BitGenerator مقدمًا وتلتف حوله لتوفير جميع التوزيعات غير المنتظمة ، Gaussians ، gammas ، ذات الحدين ، إلخ. يضمن توافق البث الصارم لـ BitGenerator s. لن نتخلص من أي (تجعله ينطلق) ولن نغيره.

السؤال المركزي حول الإعداد الافتراضي هو "ماذا يفعل الكود g = Generator() ، بدون وسيطات؟" في الوقت الحالي ، في العلاقات العامة ، يقوم بإنشاء Xoshiro256 BitGenerator بحالة تعسفية (أي مأخوذ من مصدر إنتروبيا جيد مثل /dev/urandom ). سيكون خيار "عدم التقصير" هو ارتكاب هذا الخطأ ؛ سيضطر المستخدمون إلى تسمية BitGenerator التي يريدونها بشكل صريح. نقطة @ eric-wieser هي أن "لا يوجد افتراضي" هو خيار _safe_ بشكل قاطع للإصدار الأول. لن يتسبب الإصدار اللاحق الذي يوفر افتراضيًا في حدوث مشكلات بنفس الطريقة التي يؤدي بها تغيير الإعداد الافتراضي الحالي.

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

في المقابل ، يبدو أن bashtage يهتم بالمولد الافتراضي

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

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

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

هذا ممل إلى حد ما ، وهذا هو السبب في أنني اقترحت في الأعلى أنه ربما يختار معظم الناس عادةً Generator(PCG64(<seed>)) على أي حال ، نظرًا لأنه مناسب تمامًا للكتابة. ومع ذلك ، يشيرbashtage بشكل صحيح إلى بعض المقاومة عند اتخاذ قرار إضافي.

لذلك أعتقد أننا _ أيضًا_ لدينا سؤال أوسع أمامنا: "ما هي جميع الطرق التي نريد من المستخدمين إنشاء مثيل لها؟ وإذا كانت هذه الطرق بها إعدادات افتراضية ، فماذا يجب أن تكون هذه الإعدادات الافتراضية؟" لدينا مساحة تصميم مفتوحة وما زال اقتراح Generator(<seed>) أو Generator(DefaultBitGenerator(<seed>)) من الاحتمالات.

bashtage إلى أي مدى تعتقد أن التوثيق سيساعد؟ هذا هو ، إذا قلنا في الجزء العلوي " PCG64 هو الخيار الافتراضي المفضل لدينا BitGenerator " واستخدمنا Generator(PCG64(seed)) باستمرار في جميع الأمثلة (عندما لا نعرض خوارزميات أخرى على وجه التحديد)؟

قد أكون أكثر اقتناعًا بأن لدي وظيفة default_generator(<seed>) _ تزيد عن Generator(<seed>) أو g=Generator();g.seed(<seed>) . ثم إذا احتجنا حقًا إلى تغييرها ولم نرغب في كسر الأشياء ، فيمكننا فقط إضافة وظيفة جديدة وإضافة تحذيرات إلى الوظيفة القديمة. قد أوصي بوضع علامة عليه experimental للإصدار الأول ، مما يمنحنا بعض الوقت لمشاهدة هذه البنية التحتية في البرية قبل تقديم التزام ثابت.

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

أتفق مع bashtage على أنه سيكون من الأفضل دعم بذور الأعداد الصحيحة بشكل مباشر Generator ، على سبيل المثال ، np.random.Generator(1234) . هذا ، بالطبع ، سيستفيد من DefaultBitGenerator .

في التوثيق لـ Generator ، يمكننا إعطاء تاريخ كامل لمولد البت الافتراضي في كل إصدار سابق من NumPy. هذا في الأساس اقتراحimneme ، وأعتقد أنه سيكون كافياً لأغراض التكاثر.

(رأيت للتو هذا التعديل على تعليق سابق)

عفوًا ، نسيت إضافة -O3 ، لكنها لا تزال قبيحة: https://godbolt.org/z/yiQRhd

بالنسبة لـ MSVC ، ليس -O3 ، إنه /O2 أو /Ox (لكن ليس /O3 !).

في التوثيق لـ Generator ، يمكننا إعطاء تاريخ كامل لمولد البت الافتراضي في كل إصدار سابق من NumPy. هذا في الأساس اقتراحimneme ، وأعتقد أنه سيكون كافياً لأغراض التكاثر.

في الواقع ، من الأفضل تضمين وسيطة صريحة version ، مثل وسيطة pickle protocol ، في Generator / DefaultBitGenerator . ثم يمكنك كتابة شيء مثل np.random.Generator(123, version=1) للإشارة إلى أنك تريد أرقامًا عشوائية من "الإصدار 1" (أيًا كان ذلك) أو np.random.Generator(123, version=np.random.HIGHEST_VERSION) (السلوك الافتراضي) للإشارة إلى أنك تريد أحدث / أكبر مُنشئ بت (أيا كان ذلك).

من المفترض أن يكون version=0 هو MT19937 الذي استخدمه NumPy حتى الآن ، و version=1 يمكن أن يكون أيًا كان الافتراضي الجديد الذي نختاره.

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

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

في الواقع ، من الأفضل تضمين وسيطة صريحة version ، مثل pickle ، في Generator / DefaultBitGenerator .

أنا أقل معجبًا بهذا. على عكس حالة pickle ، فإن هذه الأشياء لها أسماء ذات مغزى يمكننا استخدامها ، ولدينا بالفعل الآلية التي تم تنفيذها.

أنا أقل معجبًا بهذا. على عكس حالة pickle ، فإن هذه الأشياء لها أسماء ذات مغزى يمكننا استخدامها ، ولدينا بالفعل الآلية التي تم تنفيذها.

ضع في اعتبارك ما يلي من منظور مستخدم NumPy النموذجي:

  • np.random.Generator(seed, version=0) مقابل np.random.Generator(seed, version=1)
  • np.random.Generator(MT19937(seed)) مقابل np.random.Generator(PCG64(seed))

أعتقد أنه من الآمن افتراض أن معظم مستخدمينا يعرفون القليل جدًا عن المزايا النسبية لخوارزميات RNG. ولكن حتى بدون قراءة أي مستندات ، يمكنهم تخمين أن version=1 (الإصدار الافتراضي الأحدث) يجب أن يكون أفضل في معظم الحالات من version=0 . بالنسبة لمعظم المستخدمين ، هذا كل ما يحتاجون إلى معرفته حقًا.

في المقابل ، أسماء مثل MT19937 و PCG64 هي في الحقيقة ذات معنى فقط للخبراء ، أو الأشخاص الذين قرأوا وثائقنا بالفعل :).

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

وعلى أي حال ، فإن هذا المستوى من إعادة إنتاج النسخ المتقاطع هو شيء تخلينا عنه في

بعض الأفكار حول الافتراضي:

  • لا يهتم 99.9٪ من المستخدمين أو يرغبون في معرفة الخوارزميات الأساسية ، فهم يريدون فقط أرقامًا عشوائية. لذا ، يرجى عدم جعل المستخدمين يختارون إجراء 1+ لاتخاذ قرار بشأن الخيار الافتراضي.
  • يبدو أن dSFMT هو مجرد إصدار أسرع من MT19937 (سيكون من الجيد الإشارة في المستندات إلى مدى سرعة إزالة "SSE2"). نظرًا لأننا لا نضمن إمكانية إعادة إنتاج تدفق البيانات على أي حال ، فإن الاختلافات الداخلية في الحالة ليست شيقة جدًا ويجب تفضيل dSFTM على MT19937 حتى إذا كانت الحجة الفائزة هنا هي "جعل الحياة أسهل أثناء مراجعة المقالة" .
  • الأداء مهم لجزء كبير من قاعدة المستخدمين. الخصائص الإحصائية للمولدات لا تهم سوى جزء صغير جدًا من المستخدمين. جميع المولدات المضمنة جيدة لحالات الاستخدام العادي. لذا +1 لاختيار الأسرع افتراضيًا.

آسف للقول - ولكن لا يزال 32 بت مهمًا على Windows - راجع https://github.com/pypa/manylinux/issues/118#issuecomment -481404761

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

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

لبعض الطب الشرعي والمناقشات ، انظر: https://arxiv.org/pdf/1810.10985.pdf

تعطي الكتب المدرسية طرقًا تفترض ضمنيًا أو صريحًا أن PRNGs يمكن استبدالها بمتغيرات IIDU [0،1) دون إدخال خطأ مادي [20 ، 7 ، 2 ، 16 ، 15]. نوضح هنا أن هذا الافتراض غير صحيح للخوارزميات في العديد من الحزم الإحصائية الشائعة الاستخدام ، بما في ذلك MATLAB ، ووحدة Python العشوائية ، و R ، و SPSS ، و Stata.

kellieotto ، pbstark - هل لديكم رأي حول PRNG الذي يجب أن نختاره هنا ، لإعطاء أفضل أساس ممكن للتبديل والتمهيد ؟

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

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

لبعض الطب الشرعي والمناقشات ، انظر: https://arxiv.org/pdf/1810.10985.pdf

مقال مشوق جدا. يستنتج أن NumPy تدور حول المكتبة الوحيدة التي تحصل عليها بشكل صحيح (أعلى الصفحة 9) ، على عكس R و Python stdlib & co.

سيكون من المفيد جدًا الحصول على أمثلة ملموسة أكثر مما هو موجود في الورقة. إذا تعطل المولد الافتراضي الحالي أيضًا في مرحلة ما ، فمتى يحدث ذلك؟ أمثلة مثل دالة R sample تولد 40٪ من الأرقام الزوجية و 60٪ من الأرقام الفردية عند رسم حوالي 1.7 مليار عينة. ما هو مكافئ التمهيد / إعادة التشكيل هنا؟

أحدث إصدار من R (3.6) يصلح الاقتطاع مقابل أسلوب البتات العشوائية
لتوليد أعداد صحيحة عشوائية. يبقى Mersenne Twister هو الافتراضي
PRNG ، رغم ذلك.

Kellie Ottoboni [email protected] وأعتقد أن
يجب أن تكون حزم اللغات والإحصاءات العلمية مشفرة
آمن (CS-PRNG ، على سبيل المثال ، SHA256 في وضع العداد) ، مع خيار السقوط
العودة إلى شيء أسرع ولكن بجودة أقل (على سبيل المثال ، Mersenne Twister)
إذا كانت السرعة تتطلب ذلك.

كنا نعمل على CS-PRNG لـ Python:
https://github.com/statlab/cryptorandom

الأداء ليس رائعًا (حتى الآن). يبدو أن عنق الزجاجة هو تحويل الكتابة
داخل Python لإلقاء سلاسل ثنائية (إخراج التجزئة) كأعداد صحيحة. كان
العمل على تطبيق ينقل المزيد من العمل إلى C.

في صحتك،
فيليب

يوم الإثنين 27 مايو 2019 الساعة 6:27 صباحًا Ralf Gommers [email protected]
كتب:

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

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

لبعض الأدلة الجنائية والمناقشات ، انظر:
https://arxiv.org/pdf/1810.10985.pdf

مقال مشوق جدا. يخلص إلى أن NumPy هو فقط
مكتبة تحصل عليه بشكل صحيح (أعلى الصفحة 9) ، بخلاف R و Python stdlib & co.

سيكون من المفيد جدًا الحصول على أمثلة ملموسة أكثر من تلك الموجودة في
ورقة. إذا تعطل المولد الافتراضي الحالي أيضًا في مرحلة ما ،
متى ذلك أمثلة مثل دالة عينة R التي تولد 40٪ زوجي
الأرقام و 60٪ من الأرقام الفردية عند رسم ~ 1.7 مليار عينة. ما هو
ما يعادل bootstrapping / إعادة التشكيل هنا؟

-
أنت تتلقى هذا لأنه تم ذكرك.
قم بالرد على هذا البريد الإلكتروني مباشرة ، وقم بعرضه على GitHub
https://github.com/numpy/numpy/issues/13635؟email_source=notifications&email_token=AANFDWJEIA4CTLLHVGZVKBLPXPOUFA5CNFSM4HPX3CHKYY3PNVWWK3TUL52HS4DFVREXG43VMVMiss4DFVREXG43VMV
أو كتم الخيط
https://github.com/notifications/unsubscribe-auth/AANFDWJW445QDPGZDGXMPA3PXPOUFANCNFSM4HPX3CHA
.

-
فيليب بي ستارك | عميد مشارك للعلوم الرياضية والفيزيائية |
أستاذ بقسم الإحصاء |
جامعة كاليفورنيا
بيركلي ، كاليفورنيا 94720-3860 | 510-394-5077 | Statistics.berkeley.edu/~stark |
تضمين التغريدة

الأداء مهم لجزء كبير من قاعدة المستخدمين. الخصائص الإحصائية للمولدات لا تهم سوى جزء صغير جدًا من المستخدمين. جميع المولدات المضمنة جيدة لحالات الاستخدام العادي. لذا +1 لاختيار الأسرع افتراضيًا

أولاً ، لا توجد طريقة لاختيار "الأسرع". أجرىbashtage بعض المعايير على الكود الحالي في # 13163 وكان في جميع أنحاء الخريطة ، مع فوز dSFMT على Windows وتعرضه للضرب بشكل سليم بواسطة PCG-64 و Xoroshiro 256 على Linux. وهذا كله على نفس الجهاز بنفس المعيار. ستحدث بنية الأجهزة المختلفة (حتى المراجعات داخل X86) فرقًا كما هو الحال مع معايير مختلفة. (كما تمت مناقشته بالفعل في هذا الموضوع ، فإن أداء PCG ضعيف في معايير Windows بسبب مشاكل مع MSVC ، والتي من المحتمل أيضًا أن تكون شيئًا عابرًا ، نظرًا لأن MSVC قد يتحسن أو قد يعمل الأشخاص على حل مشكلاته. ربما تشرح مشكلات MSVC المشابهة سبب Xoshiro هزم.)

أتساءل أيضًا عن حجم "الجزء المهم" من المستخدمين المهتمين بالسرعة. بلغ متوسط بايثون نفسها

وبالنسبة لهذا "الكسر الكبير" الذي يهتم بالسرعة ، نظرًا لكل المتغيرات الموضحة أعلاه ، من الذي سيأخذ كلمتك فقط لأن PRNG الافتراضي سيعمل بأسرع ما يمكن لتطبيقه؟ من الأشياء المعقولة التي يجب القيام بها (وهو أمر ممتع للغاية وفي متناول معظم المستخدمين) هو قياس أداء PRNGs المختلفة المتاحة ومعرفة أيها أسرع _ بالنسبة لهم_.

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

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

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

لبعض الطب الشرعي والمناقشات ، انظر: https://arxiv.org/pdf/1810.10985.pdf

تعطي الكتب المدرسية طرقًا تفترض ضمنيًا أو صريحًا أن PRNGs يمكن استبدالها بمتغيرات IIDU [0،1) دون إدخال خطأ مادي [20 ، 7 ، 2 ، 16 ، 15]. نوضح هنا أن هذا الافتراض غير صحيح للخوارزميات في العديد من الحزم الإحصائية الشائعة الاستخدام ، بما في ذلك MATLAB ، ووحدة Python العشوائية ، و R ، و SPSS ، و Stata.

FWIW ، هناك ورقة لطيفة من lemire حول إنشاء رقم بكفاءة في نطاق دون تحيز. لقد استخدمت ذلك كنقطة انطلاق لاستكشاف وتشغيل بعض المعايير أيضًا في مقالتي الخاصة . (عند إنشاء 64 بت ، تستخدم طريقة Lemire مضاعفة 128 بت لتجنب التقسيم البطيء 64 بت ، مع جميع المشكلات المألوفة التي قد تثير مستخدمي MSVC.)

pbstark @ kellieotto لقد قرأت ورقتك باهتمام عندما ظهرت على arXiv. كنت أزور بعض الأصدقاء في BIDS ، وقد ذكروا عملك. يشير قسم المناقشة إلى أنه "حتى الآن ، لم نعثر على إحصائية ذات تحيز ثابت كبير بما يكفي لاكتشافه في تكرارات O (10 ^ 5)" لـ MT19937. هل وجدت واحدة حتى الآن؟ هل وجدت مثالًا ملموسًا لـ PRNG بحالة 128 بت مثل PCG64؟ يبدو لي أن هذا يمثل حدًا معقولًا من الأهمية العملية ، حيث قد يبدأ هذا الاعتبار في التفوق على الآخرين (المنظمة البحرية الدولية) ، على الأقل لغرض اختيار تقصير للأغراض العامة.

الميزة الرائعة لإطار عمل PRNG الجديد رقم 13163 هو أنه يسمح لأي شخص بتقديم BitGenerator والذي يمكن توصيله بالكهرباء. ليس من الضروري حتى أن يكون فارغًا ليستخدمه الأشخاص في مكان الشفرة. أود أن أشجعك على النظر في تنفيذ cryptorandom كـ BitGenerator في C حتى نتمكن من مقارنتها وجهًا لوجه مع الخيارات الأخرى.

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

pbstark ربما ترغب في تنفيذ هذا باعتباره BitGenerator متوافقًا مع numpy / randomgen؟ وهذا هو المرجح أن تكون كل من أسهل طريقة لتسريع العملية وجعلها متاحة للجمهور واسع في شكل أكثر فائدة بكثير. نظرًا لأنه يبدو أنك أنت وكيلي أوتوبوني في بيركلي ، فهل يمكننا أن نلتقي ببعض الوقت لاستكمال ذلك؟ (مجرد عرض ، يجب أن ألقي نظرة فاحصة على الكود بنفسي أولاً).

فيما يتعلق بأوراق العينة العشوائية: الممارسة تجعلها غير كاملة ، إنها قراءة لطيفة ، لكن من الجدير بالذكر أنه إذا كان لدينا 1 تريليون نواة تنتج رقمًا واحدًا لكل نانوثانية لمدة 100 عام ، فسنولد أقل من 2 ^ 102 رقم.

بالنسبة إلى PRNGs التي يمكن التنبؤ بها بشكل تافه (حتى تلك التي تحتوي على مساحات حالة كبيرة مثل Mersenne Twister) ، يمكننا في الواقع معرفة ما إذا كان يمكن إنتاج تسلسل إخراج معين (والعثور على البذور التي ستولدها إذا كانت موجودة أو تشعر بالحزن إذا لم تكن موجودة ) ، ولكن بالنسبة لـ PRNGs الأخرى التي لا يمكن التنبؤ بها بشكل تافه ، لا يمكننا (بسهولة) معرفة تسلسلات الإخراج التي لا يمكن أبدًا إنتاجها وأيها موجودة ولكنها نادرة بما فيه الكفاية بحيث من غير المرجح أن نجدها على الإطلاق في فترة البحث. (كما تعلم ، لدي برنامج PRNG أعلم أنه سيخرج ملفًا مضغوطًا به _Twelth Night_ بداخله ضمن 2 ^ 80 إخراجًا ، ولكن حظًا سعيدًا في العثور عليه.)

إذا كنت تريد حقًا cryptoprng ، فإن الخيار الوحيد على الأجهزة الحديثة هو
AES لأنه يحتوي على تعليمات مخصصة. lemire لديه تطبيق
هنا https://github.com/lemire/testingRNG/blob/master/source/aesctr.h ذلك
هي بنفس سرعة المولدات غير المشفرة. هناك أيضا ChaCha20 التي يمكن أن تذهب
سريع مع SIMD. كلاهما سيكون بطيئًا على الأجهزة القديمة. ثري فراي و
تم تضمين Philox بالفعل وهو prngs عداد cryptolite.

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

في الإثنين ، 27 مايو 2019 ، الساعة 19:50 ، كتب Robert Kern [email protected] :

pbstark https://github.com/pbstark kellieotto
https://github.com/kellieotto قرأت ورقتك باهتمام عندما أقرأها
ظهرت في arXiv. كنت أزور بعض الأصدقاء في BIDS ، وكان لديهم
ذكر عملك. يشير قسم المناقشة إلى أنه "لم نفعل ذلك حتى الآن
وجدت إحصائية ذات تحيز ثابت وكبير بما يكفي لاكتشافه
O (10 ^ 5) مكررات "لـ MT19937. هل عثرت على واحد حتى الآن؟
مثال ملموس لـ PRNG ذو الحالة 128 بت مثل PCG64؟ هذا يبدو لي
أن تكون عتبة معقولة ذات صلة عملية ، حيث يكون هذا الاعتبار
قد تبدأ في التفوق على الآخرين (IMO) ، على الأقل لغرض الاختيار
تقصير للأغراض العامة.

الميزة الرائعة لإطار عمل PRNG الجديد رقم 13163
https://github.com/numpy/numpy/pull/13163 هو أنه يسمح لأي شخص
توفير BitGenerator الخاصة بهم والتي يمكن توصيلها فقط
حتى يجب أن تكون في وضع غير محكم حتى يستخدمه الأشخاص في شفراتهم الخفية. أود
نشجعك على النظر إلى تطبيق cryptorandom باعتباره BitGenerator في C.
حتى نتمكن من مقارنتها وجهًا لوجه مع الخيارات الأخرى.

-
أنت تتلقى هذا لأنه تم ذكرك.
قم بالرد على هذا البريد الإلكتروني مباشرة ، وقم بعرضه على GitHub
https://github.com/numpy/numpy/issues/13635؟email_source=notifications&email_token=ABKTSRO5PKW4MRFSBGUFUNTPXQUOLA5CNFSM4HPX3CHKYY3PNVWWK3TUL52HS4DFVREXG43VMVBW1
أو كتم الخيط
https://github.com/notifications/unsubscribe-auth/ABKTSRMRIHC4OYDR52HLTHDPXQUOLANCNFSM4HPX3CHA
.

أتساءل أيضًا عن حجم "الجزء المهم" من المستخدمين المهتمين بالسرعة. بلغ متوسط ​​Python نفسها حوالي 50 × أبطأ من C. البعض ، بالتأكيد ، لكني أظن أنه ليس عددًا كبيرًا جدًا.

أظن أنك لست مستخدمًا عاديًا :) NumPy غالبًا ما يكون C تحت الغطاء ، وهو سريع مثل القيام بأشياءك الخاصة في C (حسنًا ، أسرع غالبًا). أيضًا ، PyPy ليس جاهزًا للإنتاج للتطبيقات العلمية ، وهو أبطأ على أي حال (لأنه يقتصر على استخدام CPython API التي تستخدمها NumPy ، لذلك لا يمكنها الاستفادة من JIT).

في كلتا الحالتين ، هذا خارج الموضوع. التأكيد على أن مسألة السرعة ليست مثيرة للجدل.

imneme نحن نستخدم طريقة lemires للأعداد الصحيحة المحدودة. منذ هذا أ
بداية جديدة بدون إرث أو استهلاك حاولنا جاهدين أن نبدأ به
خوارزميات جيدة.

في الإثنين ، 27 مايو 2019 ، الساعة 19:46 كتب imneme [email protected] :

لبعض الأدلة الجنائية والمناقشات ، انظر:
https://arxiv.org/pdf/1810.10985.pdf

تعطي الكتب المدرسية طرقًا تفترض ضمنيًا أو صريحًا أن PRNGs يمكنها ذلك
يتم استبدالها بمتغيرات IIDU [0،1) الحقيقية دون إدخال مادة
خطأ [20 ، 7 ، 2 ، 16 ، 15]. نظهر هنا أن هذا الافتراض غير صحيح ل
الخوارزميات في العديد من الحزم الإحصائية الشائعة الاستخدام ، بما في ذلك MATLAB ،
وحدة Python العشوائية و R و SPSS و Stata.

FWIW ، هناك ورقة لطيفة https://arxiv.org/abs/1805.10941 بواسطةlemire
https://github.com/lemire على إنشاء رقم في نطاق بكفاءة
بدون تحيز. لقد استخدمت ذلك كنقطة انطلاق لاستكشاف وتشغيل بعضها
المعايير أيضًا في مقالي الخاص
http://www.pcg-random.org/posts/bounded-rands.html . (عند التوليد
64 بت ، طريقة Lemire تستخدم مضاعفة 128 بت لتجنب البطء
تقسيم 64 بت ، مع كل المشكلات المألوفة التي قد تثير لـ MSVC
المستخدمين.)

-
أنت تتلقى هذا لأنه تم ذكرك.
قم بالرد على هذا البريد الإلكتروني مباشرة ، وقم بعرضه على GitHub
https://github.com/numpy/numpy/issues/13635؟email_source=notifications&email_token=ABKTSRKNAQAK4WIXG5SVLO3PXQUA3A5CNFSM4HPX3CHKYY3PNVWWK3TUL52HS4DFVREXG43VMVB1
أو كتم الخيط
https://github.com/notifications/unsubscribe-auth/ABKTSRKV3KYKRLNMBKNU4JLPXQUA3ANCNFSM4HPX3CHA
.

يجب أن نقدم الإعدادات الافتراضية الآمنة ، وأفضل تخميني الحالي هو أن هذا يعني افتراضيات آمنة لجميع الأغراض باستثناء التشفير

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

إحساسي هو أن PCG64 سيكون افتراضيًا جيدًا. لن يكون عيب السرعة على Windows واضحًا للأشخاص الذين يستخدمون Anaconda et. al. ، ومن المحتمل أن يتم إصلاحه في وقت ما. مع كون التنفيذ الموازي هو الشيء الجديد في Python ، أعتقد أيضًا أن وجود تدفقات قابلة للتعيين يعد خاصية مرغوبة.

أنا متشكك للغاية في أن عقوبة سرعة PCG64 بموجب Visual Studio هي شيء لا يمكن محوه.

هل تم تقييم هذا بعناية في مكان ما؟

التأكيد على أن مسألة السرعة ليست مثيرة للجدل.

سؤالي هو - ما هو الآمن؟

تطبيق المنطق باستمرار: "ما هو سريع"؟ ليس لدي فكرة رائعة عن البرامج الصغيرة التي تتمتع بأداء BitGenerator كعقبة كبيرة. إذا استخدمت BitGenerator أسرع مرتين ، فهل سأحصل على تسريع بنسبة 5٪ في حسابي الكامل؟ ربما لا حتى ذلك. Python-not-being-as-fast-C ليست هي المشكلة ؛ إنه فقط حتى البرامج الثقيلة PRNG والمفيدة بالفعل لا تقضي وقتًا طويلاً في BitGenerator . ربما تكون أي من الخيارات المتاحة كافية.

أنا متشكك للغاية في أن عقوبة سرعة PCG64 بموجب Visual Studio هي شيء لا يمكن محوه.

عرض متابعة تفصيلية كيف يقوم clang بتجميع PCG64 في التجميع الذي يمكننا سرقته لـ MSVC 64 بت ، لذلك لا أعتقد أن MSVC على Windows 64 بت يمثل مشكلة لا يمكن التغلب عليها.

ما قد يكون أكثر تعقيدًا هو PCG64 على أنظمة 32 بت ، والتي قد يكون نظام Windows 32 بت منها فقط مهمًا من الناحية العملية بالنسبة لنا. في هذه الحالة ، لا يتعلق الأمر بـ MSVC بقدر ما يتعلق بتقييد أنفسنا بـ 32 بت ISA.

ما أشرت إليه من [email protected] وأنا أشرت إليه
حتى بالنسبة للمشكلات ذات الحجم المتواضع ، فإن مساحة حالة MT صغيرة جدًا لتقريبها
التباديل المنتظم (ن <2100) أو عينات عشوائية منتظمة (ن = 4e8 ، ك = 1000).

هذا يؤثر على كل شيء من التمهيد إلى اختبارات التقليب إلى MCMC.
الفرق بين التوزيع المقصود والفعلي
يمكن أن يكون التوزيع كبيرًا بشكل تعسفي (إجمالي مسافة الاختلاف تقترب
2). إنه كبير وخطير.

لم نبذل أي جهد لكسر الترجمة الآلية على الوظائف "الإحصائية" في a
عدة سنوات. أنا متأكد من أن هناك طريقة منهجية لكسرها
(لأن مسافات التوزيع كبيرة جدًا).

في صحتك،
فيليب

يوم الإثنين 27 مايو 2019 الساعة 12:26 مساءً Robert Kern [email protected]
كتب:

التأكيد على أن مسألة السرعة ليست مثيرة للجدل.

سؤالي هو - ما هو الآمن؟

تطبيق المنطق باستمرار: "ما هو سريع"؟ ليس لدي فكرة رائعة
ما هي البرامج المعقدة التي لها أداء BitGenerator مثل
عنق الزجاجة كبير. إذا استخدمت BitGenerator أسرع مرتين ،
هل سأحصل على تسريع بنسبة 5٪ في حسابي الكامل؟ ربما لا حتى ذلك.
Python-not-being-as-fast-C ليست هي المشكلة ؛ هذا فقط حتى
البرامج الثقيلة PRNG المفيدة في الواقع لا تنفق الكثير من المال
الوقت في BitGenerator. ربما تكون أي من الخيارات المتاحة
كافي.

-
أنت تتلقى هذا لأنه تم ذكرك.
قم بالرد على هذا البريد الإلكتروني مباشرة ، وقم بعرضه على GitHub
https://github.com/numpy/numpy/issues/13635؟email_source=notifications&email_token=AANFDWKSMPAG3GFUCUFRXCDPXQYVRA5CNFSM4HPX3CHKYY3PNVWWK3TUL52HS4DFVREXG43VMVBW42
أو كتم الخيط
https://github.com/notifications/unsubscribe-auth/AANFDWIDCPAJJ6DJ3RO332LPXQYVRANCNFSM4HPX3CHA
.

-
فيليب بي ستارك | عميد مشارك للعلوم الرياضية والفيزيائية |
أستاذ بقسم الإحصاء |
جامعة كاليفورنيا
بيركلي ، كاليفورنيا 94720-3860 | 510-394-5077 | Statistics.berkeley.edu/~stark |
تضمين التغريدة

pbstark ما أرغب في رؤيته هو تنفيذ ملموس للمشكلة (يمكن أن يكون مصطنعًا ، ولكنه ليس مفتعلًا بشكل كبير) حيث يفشل MT أو PRNG 128 بت ويعمل عليه cryptorandom . هل يمكنك الإشارة إلى مجموعة بيانات حيث تعطي طريقة إعادة التشكيل استنتاجات خاطئة باستخدام برنامج PRNG 128 بت واستنتاجات صحيحة باستخدام cryptorandom ؟

الانتقال إلى PCG64 يجعل الحد الأدنى لحجم المشكلة أسوأ ،
نظرًا لأن مساحة دولتها أصغر من مساحة MT. بالطبع ، يمكن
لا يزال ينتج عشوائية "أفضل" من حيث أنه قد يأخذ عينة من مجموعة فرعية من
مجموعة التقليب أكثر توازناً من MT. لكن يجب أن ينهار من قبل
500 اختر 10 وقبل 21 !.

في صحتك،
فيليب

يوم الاثنين 27 مايو 2019 الساعة 12:30 ظهرًا Robert Kern [email protected]
كتب:

أنا متشكك للغاية في أن عقوبة سرعة PCG64 بموجب Visual Studio هي
شيء لا يمكن محوه.

أعرض الخيط العلوي كيف يقوم clang بتجميع PCG64 في تجميع يمكننا سرقته
لـ MSVC 64 بت ، لذلك لا أعتقد أن MSVC على Windows 64 بت هو ملف
مشكلة لا يمكن التغلب عليها.

ما قد يكون أكثر تعقيدًا هو PCG64 على أنظمة 32 بت ، منها 32 بت فقط
قد يظل Windows مهمًا من الناحية العملية بالنسبة لنا. في هذه الحالة يكون أقل
حول MSVC من تقييد أنفسنا بـ 32 بت ISA.

-
أنت تتلقى هذا لأنه تم ذكرك.
قم بالرد على هذا البريد الإلكتروني مباشرة ، وقم بعرضه على GitHub
https://github.com/numpy/numpy/issues/13635؟email_source=notifications&email_token=AANFDWJFCINQCYGFCI7ULI3PXQZGLA5CNFSM4HPX3CHKYY3PNVWWK3TUL52HS4DFVREXG43VMV
أو كتم الخيط
https://github.com/notifications/unsubscribe-auth/AANFDWK6QTB65Z4TJU76XKTPXQZGLANCNFSM4HPX3CHA
.

-
فيليب بي ستارك | عميد مشارك للعلوم الرياضية والفيزيائية |
أستاذ بقسم الإحصاء |
جامعة كاليفورنيا
بيركلي ، كاليفورنيا 94720-3860 | 510-394-5077 | Statistics.berkeley.edu/~stark |
تضمين التغريدة

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

يبدو من غير المحتمل أن يكون هناك العديد من مستخدمي Windows 32 بت يهتمون بأحدث أداء. لا يتطلب الأمر الكثير من الجهد للتبديل إلى 64 بت.

أود رؤيته أيضًا.

نحن نعلم - على أساس الرياضيات - أنه لا بد من وجود العديد من المشكلات الكبيرة ،
لكن لا يمكننا الإشارة إلى مثال حتى الآن.

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

يوم الإثنين 27 مايو 2019 الساعة 12:39 مساءً Robert Kern [email protected]
كتب:

pbstark https://github.com/pbstark ما أود أن أراه هو ملموس
تنفيذ المشكلة (يمكن أن يكون مصطنعًا ، ولكن ليس مفتعلًا بشكل كبير)
الذي فشلت MT أو PRNG 128 بت وسيعمل التشفير العشوائي. هل تستطيع
يشير إلى مجموعة بيانات هناك حيث تعطي طريقة إعادة التشكيل خطأ
الاستنتاجات مع 128 بت PRNG والاستدلالات الصحيحة مع cryptorandom؟

-
أنت تتلقى هذا لأنه تم ذكرك.
قم بالرد على هذا البريد الإلكتروني مباشرة ، وقم بعرضه على GitHub
https://github.com/numpy/numpy/issues/13635؟email_source=notifications&email_token=AANFDWODTUIPNMVOJB6QP3DPXQ2FPA5CNFSM4HPX3CHKYY3PNVWWK3TUL52HS4DFVREXG43VMVB89
أو كتم الخيط
https://github.com/notifications/unsubscribe-auth/AANFDWITAGQFZDQSIFNEHETPXQ2FPANCNFSM4HPX3CHA
.

-
فيليب بي ستارك | عميد مشارك للعلوم الرياضية والفيزيائية |
أستاذ بقسم الإحصاء |
جامعة كاليفورنيا
بيركلي ، كاليفورنيا 94720-3860 | 510-394-5077 | Statistics.berkeley.edu/~stark |
تضمين التغريدة

k-equidistribution هي خاصية تجميع لمخرجات PRNG على الكل
فترة PRNG. إنه أمر جيد ، لكنه لا يقول شيئًا عن الآخرين
أنواع فشل العشوائية ، مثل الارتباط التسلسلي للمخرجات.
إنه شريط منخفض نسبيًا.

يوم الإثنين 27 مايو 2019 الساعة 12:48 مساءً Sebastian Berg [email protected]
كتب:

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

-
أنت تتلقى هذا لأنه تم ذكرك.
قم بالرد على هذا البريد الإلكتروني مباشرة ، وقم بعرضه على GitHub
https://github.com/numpy/numpy/issues/13635؟email_source=notifications&email_token=AANFDWPOBTPYHC3XBINQYA3PXQ3HZA5CNFSM4HPX3CHKYY3PNVWWK3TUL52HS4DFVREXG43VM38
أو كتم الخيط
https://github.com/notifications/unsubscribe-auth/AANFDWOEB7KR2YJZWHRRAHLPXQ3HZANCNFSM4HPX3CHA
.

-
فيليب بي ستارك | عميد مشارك للعلوم الرياضية والفيزيائية |
أستاذ بقسم الإحصاء |
جامعة كاليفورنيا
بيركلي ، كاليفورنيا 94720-3860 | 510-394-5077 | Statistics.berkeley.edu/~stark |
تضمين التغريدة

فشل pbstark MT في عدد من الاختبارات الإحصائية التي يمر بها PCG (والمولدات الأخرى).

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

إذا أراد المرء أن يقوم MSVC بإنشاء تعليمات ror ، أعتقد أنه يحتاج إلى استخدام "_rotr64" جوهري.

قد يفضل المرء أيضًا علامة "/ O2" للتحسين.

عند النظر إليه ، قد يكون من الأفضل بالفعل كتابته في التجميع ، إذا أراد المرء استخدام PCG64.

بالنسبة إلى pbstark ، إليك بعض الإخراج من PCG-64 الذي تمت تهيئته سأخبرك بالدفق ، إنه 0x559107ab8002ccda3b8daf9dbe4ed480 ):

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

الآن ، لنفترض أنك قمت بتهيئة مولد pcg آخر ببذور تم اختيارها عشوائيًا. دعنا نختار ، من أجل الوسيطة 0xb124fedbf31ce435ff0151f8a07496d3 . كم عدد المخرجات التي يجب أن ننتجها قبل أن نكتشف هذه المخرجات المعروفة؟ نظرًا لأنني أعرف البذرة التي استخدمتها أعلاه ، يمكنني الإجابة عن ذلك (عبر وظيفة المسافة في PCG) ، حوالي 2.5 × 10 ^ 38 (أو حوالي 2 ^ 127.5) من المخرجات. كمرجع ، 10 ^ 38 نانوثانية هي 230 مليار ضعف عمر الكون.

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

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

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

بدافع الفضول ، اختتمت مولد بت عداد AES باستخدام aesctr.h ، الوقت بالثانية لكل قيمة عشوائية:

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

عمل جيد ،bashtage.

هناك عدد قليل من الأشياء التي يجب وضعها في الاعتبار ، أحدها هو أن تعليمات AES المحددة قد تختلف باختلاف البنى وليست موجودة في جميع وحدات المعالجة المركزية المستخدمة بنشاط ، وبالتالي يجب أن يكون هناك مسار احتياطي (بطيء).

أيضًا ، إنه نوع من المقارنة بين التفاح والبرتقال. بالإضافة إلى استخدام التعليمات المتخصصة ، يحصل كود AES على جزء كبير من سرعته من خلال فتح الحلقة - إنه في الواقع يولد أرقامًا في كتل ثم يقرأها. يمكن أن يؤدي إلغاء اللف إلى تسريع أي برنامج PRNG. FWIW ، لدى lemire بالفعل نسخة موجهة من PCG تستخدم تعليمات AVX لتوليد مخرجات متعددة في وقت واحد.

اسمحوا لي أن أرى ما إذا كان بإمكاني تلخيص نقطة إجماع واحدة على الأقل: نحن نتفق جميعًا على أنه يجب إبداء رأي numpy حول الخوارزمية BitGenerator يجب استخدامها ، والترويج لواحد BitGenerator على الآخرين.

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

ما قصدته حقًا بخيار "بلا افتراضي" هو "عدم وجود افتراضي مجهول". لا تزال هناك طرق يمكننا من خلالها تصميم واجهة برمجة التطبيقات (API) بحيث تكون الطريقة الأكثر ملاءمة للحصول على Generator المصنف هي تلك التي تسمي PRNG الذي نرشحه. على سبيل المثال ، لنفترض أننا _ لا_ نقوم بتضمين نطاق كامل من خوارزميات BitGenerator . نحاول الحفاظ على الحد الأدنى من النقود إلى حد ما وترك الإنجاز إلى scipy ومكتبات الطرف الثالث الأخرى ، بشكل عام ، وقد يكون من الجيد القيام بذلك هنا. يكمن جمال التصميم الحالي في أنه يسمح لنا بنقل تلك BitGenerator s إلى مكتبات أخرى. لنفترض أننا نقدم فقط MT19937 لدعم الإرث RandomState و BitGenerator الذي نفضل أن يستخدمه الأشخاص. من أجل الجدل ، لنفترض أن هذا Xoshiro256 . لنجعل المُنشئ Generator.__init__() يتطلب BitGenerator . ولكن أيضًا ، دعنا نحدد دالة np.random.xoshiro256_gen(seed) تُرجع Generator(Xoshiro256(seed)) تحت الأغلفة. نحن توثيق تلك الوظيفة الراحة مثل طريقة للحصول على المصنفة Generator .

الآن تقدم سريعًا بعض الإصدارات. لنفترض أننا دفعنا PCG64 ، ThreeFry ، وما إلى ذلك إلى random-tng أو scipy أو بعض الحزم الأخرى ، وأصبح أحدهم مشهورًا بسبب تم العثور على الميزات الإضافية أو العيوب الإحصائية الجديدة في Xoshiro256 . قررنا أننا نريد تحديث رأي numpy حول أي BitGenerator يجب أن يستخدمه الأشخاص لـ PCG64 . ثم ما نقوم به هو إضافة فئة PCG64 BitGenerator وإضافة وظيفة np.random.pcg64_gen(seed) . أضفنا تحذيرًا بالإيقاف إلى np.random.xoshiro256_gen(seed) لنقول إنها لم تعد الخوارزمية المفضلة: نوصي بأن يستخدم الرمز الجديد np.random.pcg64_gen(seed) ، ولكن للاستمرار في استخدام خوارزمية Xoshiro256 بدون تحذيرات ، يجب عليهم صراحة استخدام Generator(Xoshiro256(seed)) .

أعتقد أن هذا يتجنب بعض المشكلات التي أواجهها مع واجهة برمجة تطبيقات "مجهول" (على سبيل المثال ، Generator(seed) ، Generator(DefaultBitGenerator(seed)) ، np.random.default_gen(seed) ). يمكننا دعم الخوارزميات التي لم تعد مفضلة إلى الأبد. لن نحتاج أبدًا إلى جعل المُنشئ "المفضل" الذي يتمتع بآرائه يفعل شيئًا مختلفًا عندما نغير رأينا. نظرًا لأننا نستخدم الأسماء الحقيقية لتمييز الأشياء بدلاً من أرقام الإصدارات ، فأنت تعرف دائمًا كيفية تحديث الكود لإعادة إنتاج النتائج القديمة (إذا كنت لا تستطيع تحمل التحذيرات غير الضارة لسبب ما). يمكنك حتى التقاط رمز بدون مصدر أو أرقام إصدار غير مسجلة وإجراء ذلك التحديث. في الوقت نفسه ، من خلال الحد من عدد الخوارزميات إلى الحد الأدنى المطلق وجعل أفضل الممارسات _ أسهل طريقة_ للعمل مع المكتبة ، يمكننا التعبير عن رأي Numpy بشكل فعال.

كيف يبدو هذا؟ لا يزال يتعين علينا بذل الكثير من الجهد في اتخاذ خيار قوي لهذا BitGenerator للإصدار الأول. لا يزال يترتب على ذلك.

يبدو من غير المحتمل أن يكون هناك العديد من مستخدمي Windows 32 بت يهتمون بأحدث أداء. لا يتطلب الأمر الكثير من الجهد للتبديل إلى 64 بت.

أنا موافق. نظرًا لأن المشكلة مع PCG64 على Win32 هي مجرد أداء (وهو أمر يمكننا تحسينه ببعض الجهد) ، هل توافق على أنه ليس مانعًا؟

إذا أراد المرء أن يقوم MSVC بإنشاء تعليمات ror ، أعتقد أنه يحتاج إلى استخدام "_rotr64" جوهري.

قد يفضل المرء أيضًا علامة "/ O2" للتحسين.

شكر! أشار imneme إلى كل هذه الأخطاء الفادحة بالنسبة لي. :-)

seberg هل لديك أي استشهادات من k . قد يكون للآخرين آراء مختلفة ، وربما هناك قضايا محددة في مجالك لست على علم بها. إذا كان الأمر كذلك ، فهناك حلول محددة متاحة!

بدافع الفضول ، اختتمت مولد بت عداد AES باستخدام aesctr.h

قد أكون مخطئًا ، لكنني لا أعتقد أن هذا من شأنه أن يساعد في مخاوف pbstark . AES-CTR عبارة عن CS-RNG ، ولكن ليس كل CS-RNGs لديها الفترات الكبيرة التي قد يحتاجها المرء (نظريًا) للوصول إلى جميع التباديل الممكنة k! مقابل k . لا يزال العداد عبارة عن رقم 128 بت وبمجرد مروره ، تكون قد وصلت إلى نهاية الفترة. تدافعpbstark عن PRNGs ذات الفترة الكبيرة جدًا ، ومعظمها مجرد CS-RNGs.

بشكل عام ، وجهة نظري حول التوزيع المتساوي هي أنك تريد عمومًا أن يكون التوزيع المتساوي لـ PRNG قريبًا من الحد الأقصى المسموح به لحجم حالة PRNG.

على الرغم من أن البعض يعتبر التوزيع المتساوي الأقصى خاصية مرغوبة ، إلا أنه يمكن اعتباره أيضًا عيبًا (وهناك أوراق بحثية تقول الكثير). إذا كان لدينا PRNG _k_-bit وكل تسلسل _k_-bit يحدث مرة واحدة بالضبط ، سينتهي هذا الأمر بانتهاك مشكلة عيد الميلاد التي تنص على أننا نتوقع تكرار إخراج بعد حوالي 2 ^ (k / 2) من المخرجات. ( لقد كتبت اختبارًا إحصائيًا لمشكلة عيد الميلاد بناءً على هذه الأفكار . لقد اكتشف بشكل صحيح الغياب غير المعقول إحصائيًا لأي تكرار في SplitMix ، وإخراج 64 بت ، و 64 بت ، و Xoroshiro64 + ، وإخراج 32 بت ، و 64 بت -دولة 2-أبعاد متساوية التوزيع PRNG ، من بين أمور أخرى.)

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

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

أود رؤيته أيضًا. نحن نعلم - على أساس الرياضيات - أنه لا بد من وجود العديد من المشاكل الكبيرة ، لكن لا يمكننا الإشارة إلى مثال حتى الآن. قد يقول المبدأ الوقائي أنه نظرًا لأننا نعلم أن هناك مشكلات كبيرة ونعرف كيفية منعها (CS-PRNGs) ، فقد نقوم بذلك أيضًا بشكل افتراضي ، ونترك المستخدمين أقل حذرًا إذا اختاروا ذلك.

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

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

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

كان أحد خطوط التحليل التي وجدتها مفيدة للغاية من ورقة PCG الخاصة بـ imneme هو اشتقاق إصدارات متعددة ذات حالة أصغر من كل PRNG ومعرفة المكان الذي بدأوا فيه الفشل في TestU01 بالضبط. هذا يعطينا طريقة لمقارنة بنى PRNG بشكل ترتيبي بدلاً من مجرد قول ، كل شيء أو لا شيء ، "X PRNG يمر" أو فشل. كما أنه يتيح لنا تقدير مقدار الارتفاع الذي نمتلكه في أحجام الولاية المستخدمة (والتي تمر TestU01 بعدد كبير من عينات الجيجابايت). هل هناك حسابات ملموسة يمكنك إجراؤها لتوضيح مشكلة في PRNGs 8 بت؟ 16 بت PRNGs؟ ثم يمكننا معرفة ما إذا كان هذا الاختبار الجديد سيخبرنا بمعلومات حول PRNG قبل TestU01 / PractRand حاليًا. وسيكون ذلك مفيدًا للغاية.

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

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

بالنسبة لأولئك الذين يطلبون ذلك عند خلط 32 عنصرًا ، كل 32 عنصرًا! يجب أن تكون المراسلات العشوائية (على سبيل المثال ، 263130836933693530167218012160000000 منها) قابلة للتوليد ، بدلاً من PRNG التي توفر مجرد عينة عشوائية من هؤلاء 32! خلطًا عشوائيًا ، أود في الواقع أن أقول إنه إذا كنت ستطالب بأرقام ضخمة ، فأنت لا تفكر بما يكفي .

لذلك أود أن أدعي (على نحو طريف) أن الترتيب الذي تظهر به تلك المراوغات لا ينبغي تحديده مسبقًا أيضًا! من الواضح أنه يجب عليك المطالبة بإخراج كل 32! المراوغات في جميع الطلبات الممكنة - (32!)! هو ما تحتاجه! بالطبع ، سيتطلب هذا 3.8 × 10 ^ 18 إكسابايت للحالة ومقدارًا مماثلاً من الإنتروبيا للتهيئة ، لكن من المؤكد أن الأمر يستحق معرفة أن كل شيء موجود.

... أضفنا تحذيرًا من الإيقاف إلى np.random.xoshiro256_gen(seed) لنقول إنها لم تعد الخوارزمية المفضلة: نوصي بأن يستخدم الكود الجديد np.random.pcg64_gen(seed) ، ولكن للاستمرار في استخدام خوارزمية Xoshiro256 بدون تحذيرات ، يجب عليهم صراحة استخدام Generator(Xoshiro256(seed))

لا يزال هذا يزعج المستخدمين من خلال كل من الإهمال والأسماء الغريبة التي لا يريدون حقًا معرفتها.

تقول NEP: ثانيًا ، سيتم السماح بحذر كسر توافق البث من أجل إدخال ميزات جديدة أو تحسين الأداء.

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

ما قصدته حقًا بخيار "بلا افتراضي" هو "عدم وجود افتراضي مجهول".

إذن ، هل وجهة نظرك أنك تريد أن يعرف المستخدمون اسم PRNG الذي يستخدمونه؟

انظر إلى هذا من وجهة نظر المستخدمين. من الصعب حملهم على الانتقال من np.random.rand & co إلى np.random.RandomState() ثم استخدام الأساليب. سنقوم الآن بتقديم نظام أفضل ، وما سيشاهدونه هو np.random.xoshiro256_gen() ؟ سيكون ذلك بمثابة تراجع كبير في قابلية الاستخدام.

إذن ، هل وجهة نظرك أنك تريد أن يعرف المستخدمون اسم PRNG الذي يستخدمونه؟

لا ، إنه لتخفيف مشاكل وجود واجهة برمجة تطبيقات "هدف متحرك محدد" مثل default_generator(seed) التي كان الناس يعملون حولها (مثل shoyer 's version وسيطة)

يعد الحفاظ على توافق التدفق (الذي تنكره NEP 19) ثانويًا لكسر API. مختلف BitGenerator s لها واجهات برمجة تطبيقات فعالة مختلفة ، اعتمادًا على مجموعات الميزات الخاصة بها (التدفقات القابلة للتعيين ، Jumpahead ، بشكل أساسي ، على الرغم من أنه يمكن أن يكون هناك آخرون ، اعتمادًا على كيفية تحديد المعلمات لـ PRNG). لذا فإن بعض التغييرات في تحديد PRNG الافتراضي الخاص بنا ستؤدي في الواقع إلى كسر الكود (أي لم يعد يعمل أو لم يعد يعمل بشكل صحيح) ، وليس فقط تغيير القيم التي تظهر.

على سبيل المثال ، لنفترض أننا اخترنا أولاً PCG64 . لديها حالة 128 بت ، 2 ^ 127 تدفقات قابلة للتعيين ، وتنفذ Jumpahead ؛ جميل وكامل المواصفات. لذلك يبدأ الناس في كتابة default_generator(seed, stream=whatever) . لنفترض الآن أن العمل المستقبلي وجد بعض الخلل الإحصائي الكبير فيه مما يجعلنا نريد التحول إلى شيء آخر. يجب أن يكون PRNG التالي الذي نروج له كإعداد افتراضي> = حالة 128 بت (سهل ؛ لا أوصي بأي شيء أصغر كإعداد افتراضي للأغراض العامة) ، Jumpahead (صعب!) ،> = 2 ^ 127 تدفقات قابلة للتعيين (whoo، boy!) ، من أجل عدم كسر استخدامات default_generator() الموجودة بالفعل في الكود. الآن ربما يمكننا التعايش مع تلك السقاطة.

اقترح shoyer أنه ربما يمكننا جعل القيمة الافتراضية BitGenerator تتأرجح دائمًا عن عمد إلى ميزات المقام الأقل شيوعًا. هذا سيعمل! لكنها ستفقد أيضًا فرصة الترويج للتدفقات charris التي ترغب في

سنقوم الآن بتقديم نظام أفضل ، وما سيشاهدونه هو np.random.xoshiro256_gen() ؟ سيكون ذلك بمثابة تراجع كبير في قابلية الاستخدام.

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

أنا أيضًا بخير إذا قررنا التعايش مع السقاطة وتجنب آلية version .

رأيي في "الافتراضي" هو أنه يمكننا تركها كتفاصيل تنفيذ ، بحيث يعمل Generator() دائمًا. أود أن أتعامل مع هذا مع ملاحظة قوية للحذر بأن الطريقة الوحيدة للحصول على نتائج قابلة للتكرار دائمًا (حتى التغييرات في المولد) هي استخدام بناء الجملة Generator(BitGenerator(kwarg1=1,kwargs2=b,...))

ليس من العملي إخفاء تفاصيل التنفيذ حقًا لأن الوصول إلى الحالة مطلوب.

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

bashtage في # 13650 منعت الوصول إلى Generator().bit_generator بطريقة لا تزال تسمح بالتخليل بدون وصول مباشر إلى state . يمرر test_pickle المعاد كتابته قليلاً بطريقة تسمح باستخدامه عبر python Thread s

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

"Passes PractRand at _N_ GiB" لبعض _N_ (512 ، 1024) هو تعريف مقبول إذا كنت تريد معيارًا واضحًا للنجاح / الفشل. إذا كنت تريد مثالًا ملموسًا ، فسيتم استبعاد الترجمة الآلية ومتغيراتها بناءً على هذا المعيار. لقد أزلنا أيضًا بعض أفراد عائلة Xoroshiro الأكبر سنًا من العلاقات العامة بسبب هذا.

إذا كنت تريد عرضًا أكثر تعقيدًا للجودة الإحصائية يتيح الترتيب الترتيبي للخوارزميات ، فإنني أوصيك بالقسم 3 من ورقة PCG الخاصة بـ imneme ، والذي يستخدم ملفات تعريف لمتغيرات الحالة المختصرة للخوارزميات للحصول على فكرة عن كيفية الكثير من "هامش" كل خوارزمية كاملة. هذا مشابه تمامًا لكيفية تحليل المشفرين لخوارزميات التشفير المختلفة. يجب أن يجتاز أي خيار قابل للتطبيق يتم فحصه معيار خط الأساس "عدم الانهيار" ، لكن هذا لا يساعدك في ترتيب المتنافسين. بدلاً من ذلك ، قاموا ببناء إصدارات مصغرة من الخوارزميات المنافسة ومعرفة مدى التقليل الذي يجب أن تحصل عليه قبل أن يتمكنوا من كسرها. إذا تم كسر خوارزمية كاملة من جولة N في N-1 ، فحينئذٍ يكون هناك قدر ضئيل جدًا من الإرتفاع ، ومن المحتمل أن يتجنبها المشفرون. وبالمثل ، إذا مرت 128 بت BitGenerator PractRand ولكن إصدارها 120 بت فشل ، فمن المحتمل أن تكون مخاطرة كبيرة.

mattip هذا يبدو معقولا. على الرغم من أن شخص ما في مكان ما سوف

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

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

يمرر test_pickle المعاد كتابته قليلاً بطريقة تسمح باستخدامه عبر python Thread s

من الجدير بالذكر أن هذه مشكلة معلقة (# 9650) - من الناحية المثالية يتم إعادة إدخال Generator() في سلاسل العمليات الفرعية. IIRC هذا عملي فقط في Python> = 3.7

رأيي في "الافتراضي" هو أنه يمكننا تركها كتفاصيل تنفيذ ، بحيث يعمل Generator() دائمًا. أود أن أتعامل مع هذا مع ملاحظة قوية للحذر بأن الطريقة الوحيدة للحصول على نتائج قابلة للتكرار دائمًا (حتى التغييرات في المولد) هي استخدام بناء الجملة Generator(BitGenerator(kwarg1=1,kwargs2=b,...))

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

بدون وسيطة Generator() ، على سبيل المثال ، "أعطني PRNG المصنف بشكل تعسفي والذي يوصي به numpy" ليست حالة الاستخدام الأساسية. لا يتطلب الكثير من الدعم. "أعطني PRNG الذي يوصي به numpy باستخدام هذه البذرة" ، وهو ما نناقش الخيارات من أجله. نحتاج إلى طريقة لـ numpy للتعبير عن رأي حول كيفية الحصول على PRNG مصنّف ، وهذه الطريقة يجب أن تكون سهلة ومريحة للمستخدمين (وإلا لن يستخدموها). أنا _ Like_ بتسمية الخوارزمية (وإن كان ذلك من خلال وظيفة أكثر ملاءمة) ، لكن rgommers يعتقد أن هذه خطوة بعيدة جدًا ، وأنا متعاطف مع ذلك.

المولد بدون وسيطة () ، أي "أعطني PRNG المصنف بشكل عشوائي والذي يوصي به numpy" ليس حالة الاستخدام الأساسية. لا يتطلب الكثير من الدعم. "أعطني PRNG الذي يوصي به Numpy مع هذه البذرة" ، وهو ما نناقش الخيارات له. نحتاج إلى طريقة لـ numpy للتعبير عن رأي حول كيفية الحصول على PRNG مصنّف ، وهذه الطريقة يجب أن تكون سهلة ومريحة للمستخدمين (وإلا لن يستخدموها). أحب تسمية الخوارزمية (وإن كان ذلك من خلال وظيفة أكثر ملاءمة) ، لكن rgommers تعتقد أن هذه خطوة بعيدة جدًا ، وأنا متعاطف مع ذلك.

أود أن أزعم أن المستخدمين في الواقع غير مهيئين لتوفير بذور جيدة. على سبيل المثال ، كم عدد المستخدمين الذين يعرفون الطريقة الصحيحة لبذر Mersenne Twister؟ الأمر ليس سهلاً كما تعتقد - إذا لم تقم بتغذية 624 عددًا صحيحًا عشوائيًا 32 بت (لتوفير 19937 بتًا من الحالة) ، فأنت تفعل ذلك بشكل خاطئ.

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

إذا كان النقاش يدور حول الطريقة الصحيحة فقط فأنا أؤيده
Generator(BitGenerator(**kwargs)) لأنه لن يستخدم إلا بواسطة
مستخدمي برامج semiaware المهتمين بإعادة الإنتاج.

أعتقد أن الإعداد الافتراضي المستخدم لـ Generator() مهم لأن هذا سيكون كذلك
فُسرت على أنها خيار مدروس ، لذا اعتبرها
التوصية عند استخدام النموذج المصنف.

فقط لطرح واحد آخر ، طريقة الفصل Generator.seeded(seed[, bit_generator]) where bit generator is a string. This would allow the pattern of switching from one value to None to warn if the default was going to change, like lstsq. I would also only support a limited pallatte of but generators initially (i.e. 1). Doesn't make it easy to expose advanced features I suppose. In a perfect world it would use kwarg only to allow any keyword argument to be used which avoids most depreciation problems. Of course, this doesn't really need to be a class function, just المصنف`.

في الثلاثاء ، 28 مايو 2019 ، الساعة 16:38 كتب روبرت كيرن [email protected] :

رأيي في "الافتراضي" هو أنه يمكننا تركه كتطبيق
التفاصيل ، بحيث يعمل Generator () دائمًا. أود أن أتعامل مع هذا مع
ملاحظة قوية للحذر من أن الطريقة الوحيدة للحصول على نتائج قابلة للتكرار دائمًا
(حتى التغييرات في المولد) هو استخدام بناء الجملة
المولد (BitGenerator (kwarg1 = 1 ، kwargs2 = b ، ...))

هناك نوعان من التكاثر نحتاج إلى التمييز بينهما. واحد هو
أن أدير برنامجي مرتين بنفس البذرة وأحصل على نفس النتائج.
هذا هو الذي نحتاج إلى دعمه. الآخر هو التكاثر عبر
إصدارات numpy ، والتي نبذنا مسؤوليتها ، على الأقل بالمعنى الدقيق للكلمة.

المولد بدون وسيطة () ، أي "أعطني PRNG المصنف بشكل تعسفي
توصي Numpy "ليست حالة الاستخدام الأساسية. فهي لا تتطلب الكثير
الدعم. "أعطني PRNG الذي يوصي به Numpy بهذه البذرة" ،
وهو ما نناقش الخيارات من أجله. نحن بحاجة إلى طريقة ل numpy
إبداء الرأي حول كيفية الحصول على PRNG مصنّف ، وهذه الطريقة يجب أن تكون كذلك
سهل ومريح للمستخدمين (وإلا فلن يستخدموه). أنا أحب
تسمية الخوارزمية (وإن كان ذلك من خلال وظيفة أكثر ملاءمة) ، ولكن
يعتقد rgommers https://github.com/rgommers أن هذه خطوة بعيدة جدًا ، و
أنا متعاطف مع ذلك.

-
أنت تتلقى هذا لأنه تم ذكرك.
قم بالرد على هذا البريد الإلكتروني مباشرة ، وقم بعرضه على GitHub
https://github.com/numpy/numpy/issues/13635؟email_source=notifications&email_token=ABKTSRKA4SSNW6XZEVFUMCDPXVGW5A5CNFSM4HPX3CHKYY3PNVWWK3TUL52HS4DFVREXG43VMV
أو كتم الخيط
https://github.com/notifications/unsubscribe-auth/ABKTSROCMLHG6E6BLWI6TWDPXVGW5ANCNFSM4HPX3CHA
.

في الثلاثاء ، 28 مايو 2019 ، الساعة 16:38 كتب روبرت كيرن [email protected] :

رأيي في "الافتراضي" هو أنه يمكننا تركه كتطبيق
التفاصيل ، بحيث يعمل Generator () دائمًا. أود أن أتعامل مع هذا مع
ملاحظة قوية للحذر من أن الطريقة الوحيدة للحصول على نتائج قابلة للتكرار دائمًا
(حتى التغييرات في المولد) هو استخدام بناء الجملة
المولد (BitGenerator (kwarg1 = 1 ، kwargs2 = b ، ...))

هناك نوعان من التكاثر نحتاج إلى التمييز بينهما. واحد هو
أن أدير برنامجي مرتين بنفس البذرة وأحصل على نفس النتائج.
هذا هو الذي نحتاج إلى دعمه. الآخر هو التكاثر عبر
إصدارات numpy ، والتي نبذنا مسؤوليتها ، على الأقل بالمعنى الدقيق للكلمة.

المولد بدون وسيطة () ، أي "أعطني PRNG المصنف بشكل تعسفي
توصي Numpy "ليست حالة الاستخدام الأساسية. فهي لا تتطلب الكثير
الدعم. "أعطني PRNG الذي يوصي به Numpy بهذه البذرة" ،
وهو ما نناقش الخيارات من أجله. نحن بحاجة إلى طريقة ل numpy
إبداء الرأي حول كيفية الحصول على PRNG مصنّف ، وهذه الطريقة يجب أن تكون كذلك
سهل ومريح للمستخدمين (وإلا فلن يستخدموه). أنا أحب
تسمية الخوارزمية (وإن كان ذلك من خلال وظيفة أكثر ملاءمة) ، ولكن
يعتقد rgommers https://github.com/rgommers أن هذه خطوة بعيدة جدًا ، و
أنا متعاطف مع ذلك.

-
أنت تتلقى هذا لأنه تم ذكرك.
قم بالرد على هذا البريد الإلكتروني مباشرة ، وقم بعرضه على GitHub
https://github.com/numpy/numpy/issues/13635؟email_source=notifications&email_token=ABKTSRKA4SSNW6XZEVFUMCDPXVGW5A5CNFSM4HPX3CHKYY3PNVWWK3TUL52HS4DFVREXG43VMV
أو كتم الخيط
https://github.com/notifications/unsubscribe-auth/ABKTSROCMLHG6E6BLWI6TWDPXVGW5ANCNFSM4HPX3CHA
.

من منظور قابلية الاستخدام ، أعتقد أننا بحاجة فعلاً إلى دعم Generator(seed) . بخلاف ذلك ، في مواجهة اتخاذ خيار ليسوا مستعدين لاتخاذها ، سيلتزم المستخدمون فقط بـ RandomState .

لإصدار إصدار من مُنشئ البت الافتراضي في Generator ، يمكننا استخدام bit_version=1 بدلاً من version=1 ، على الرغم من أنني موافق أيضًا على إسقاط فكرة version . لا أعتقد أن المستخدمين سيحتاجون إلى تعيين مولدات البت بشكل صريح في كثير من الأحيان.

إن تفضيلي لحل حالات الاستخدام المحددة التي تحتاج إلى ميزات خاصة بالمولد سيكون تصميم واجهات برمجة تطبيقات BitGenerator جديدة عامة تخفي تفاصيل التنفيذ. يمكن إضافتها إلى DefaultBitGenerator أو وضعها في فئات جديدة إذا كان استخدامها يتضمن مقايضات ، على سبيل المثال ، ParallelBitGenerator .

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

سيستمر المستخدمون في استخدام RandomState.

هذا جيد ، فهم ليسوا الأوائل المتبنين. أنا أضغط بشدة (ربما صعبًا جدًا؟) للحصول على الحد الأدنى من واجهة برمجة التطبيقات القابلة للتطبيق ، حيث يمكننا دائمًا توسيع واجهة برمجة التطبيقات ولكن من الصعب تقليصها. الفروق الدقيقة بين Generator(Philox()) و Generator(seed(3)) و Generator(bit_version=1) يصعب رؤيتها حتى يصل هذا إلى المستخدمين النهائيين.

دعنا نحصل على الإصدار الأول بدون Generator(seed) ونحصل على بعض التعليقات.

دعنا نحصل على الإصدار الأول بدون Generator(seed) ونحصل على بعض التعليقات.

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

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

أقول نفس الشيء ، لكني لا أحظى بقبول كبير. كما تقول ، "حسنًا ، لمجرد أن شيئًا ما فكرة سيئة لا يعني أن الناس لن يرغبوا في القيام بذلك!"

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

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

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

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

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

رقم 1

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

NumPy 1.20.x

"" بيثون
مولد فئة:
def __init __ (bitgen_or_seed = بلا ، * ، bit_generator = بلا ، inc = لا شيء):
إذا لم يكن bit_generator بلا أو inc ليس بلا:
warn ("الإعداد الافتراضي هو التغيير من PCG64 إلى AESCtr. الكلمة الأساسية inc"
"الحجة مهملة وسترفع في المستقبل" ، FutureWarning)
""

NumPy 1.22

"" بيثون
مولد فئة:
def __init __ (bitgen_or_seed = بلا ، * ، bit_generator = 'aesctr' ، inc = بلا ، العداد = 0):
إذا لم يكن bit_generator == 'pcg64' أو inc لا شيء:
زيادة استثناء ("PCG لم يعد مدعومًا وتمت إزالة المؤتمر")
""

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

كما أشرت أعلاه في https://github.com/numpy/numpy/issues/13635#issuecomment -496589421 ، أعتقد أن هذا سيكون مفاجئًا ومحبطًا لمعظم المستخدمين. أفضل طلب توفير كائن BitGenerator صريح بدلاً من التخطيط لبدء إصدار تحذيرات إذا لم يقم المستخدمون بتعيين جميع الوسائط الاختيارية. يجب أن يكون ذلك الملاذ الأخير حقًا ، في الحالات التي نكتشف فيها أن واجهات برمجة التطبيقات معطلة بطرق لم نتوقعها.

المشكلة هي الفترة الانتقالية. كل شخص يستخدم الإعدادات الافتراضية سيحصل فجأة على تحذيرات بدون طريقة رائعة للتبديل خلال الفترة الانتقالية. أو على الأقل ، يمكنك نقلهم من "حالة الطاقة المنخفضة" Generator(seed) إلى "حالة الطاقة العالية" الأقل ملاءمة Generator(seed, bit_generator='aesctr') . نظرًا لأن الهدف من واجهة برمجة التطبيقات هذه هو توفير "حالة طاقة منخفضة" ملائمة ، فقد فشلنا في هدفنا أثناء هذا الانتقال. لقد فعلنا ذلك مرة واحدة باستخدام إحدى وظائف الرسم البياني لدينا ، IIRC ، وكان ذلك بمثابة كابوس.

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

دعنا نحصل على الإصدار الأول بدون Generator(seed) ونحصل على بعض التعليقات.

بعبارة "الإصدار الأول" ، هل تقصد إصدارًا فارغًا كاملًا؟ أو مجرد دمج العلاقات العامة (وهو ما حدث منذ ذلك الحين)؟

إذا كان إصدارًا فارغًا كاملًا ، فلا يزال لدينا بعض الأشياء التي يجب تحديدها ، مثل عدد BitGenerator s الذي نقوم بتضمينه. إذا قمنا بتضمين المكمل الحالي الكامل ، فقد كشفنا عن بعض الخيارات.

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

+1 موافق

لا ، إنه لتخفيف مشاكل وجود واجهة برمجة تطبيقات "هدف متحرك محدد" مثل default_generator (بذرة) كان الأشخاص يعملون حولها (مثل وسيطة @ shoyer ).

يعد الحفاظ على توافق التدفق (الذي تنكره NEP 19) ثانويًا لكسر API. تحتوي مولدات BitGener المختلفة على واجهات برمجة تطبيقات فعالة مختلفة

آه حسنًا ، الآن أصبح الأمر أكثر منطقية بالنسبة لي.

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

هذا يبدو وكأنه أفضل حل حتى الآن. يجب أن يكون من الممكن اختيار اسم عاقل هنا. وهناك مساحة كبيرة من الأسماء الحكيمة الأخرى - التي ربما لن نحتاجها أبدًا.

شيء مثل np.random.generator أو np.random.default_generator .

كم عدد BitGenerators التي نقوم بتضمينها

هل يمكنك فتح مشكلة منفصلة مع اقتراح لإسقاط تلك التي تعتقد أنه يجب إزالتها من القائمة المضمنة حاليًا (MT19937 ، DSFMT ، PCG32 ، PCG64 ، Philox ، ThreeFry ، Xoshiro256 ، Xoshiro512)؟

ما زلنا لم نحل المشكلة المطروحة هنا: أي BitGenerator يجب أن يكون افتراضيًا (حاليًا Xoshiro256 )

حسنًا ، هذه المشكلة تدور حول "أي شخص يجب أن يروّج numpy باعتباره BitGenerator المميز" ، والذي يغذي اختيار الافتراضي ولكن أيضًا ما يجب تضمينه أو إسقاطه. تضيف الآليات التي نقدم من خلالها الإعدادات الافتراضية (إذا قدمنا ​​الإعدادات الافتراضية) بعض القيود ، لذا فهذه كلها أشياء تحتاج إلى تحديدها معًا بشكل أو بآخر. إنها فوضى كبيرة ، وبعد كل العمل الذي قمت به لرعاية هذه العلاقات العامة ، أنا متأكد من أنك مرهق لرؤية خيط ضخم آخر بدون أي كود يساهم فيه أحد ، لذلك لديك تعاطفي. :-)

بقدر ما تذهب الخوارزميات في حد ذاتها ، لقد قدمت بالفعل توصياتي: يجب أن نحتفظ بـ MT19937 مقابل RandomState ولأغراض المقارنة ، وأنا أحب PCG64 لأغراض التوصية.

لقد عبثت قليلاً في Compiler Explorer ، وأعتقد أنني قمت بتطبيق PCG64 لـ 64 بت MSVC باستخدام عناصر داخلية بطريقة تجبر المترجم على إنشاء تجميع قريب من clang uint128_t math: https: // godbolt .org / z / ZnPd7Z

ليس لدي بيئة تطوير Windows تم إعدادها في الوقت الحالي ، لذلك لا أعرف ما إذا كانت بالفعل _ صحيحة _... @ bashtage هل تمانع في إعطاء هذه اللقطة؟

بدون رقعة:

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

مع التصحيح:

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

يجتاز التصحيح الاختبارات ، بما في ذلك توليد نفس المجموعة من 1000 قيمة uint64 لبذرتين مختلفتين.

للمقارنة مع مواطني دول مجلس التعاون الخليجي وفي وضع المقارنة:

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

واو ، هذا يبدو سيئًا حقًا. ربما يتعين علينا توسيع المعلومات الموجودة في صفحة المقارنات لإثبات أداء msvc2017-on-win {64 ، 32} مقابل gcc7.4-on-linux {64 ، 32} على نفس الجهاز (أفترض أنك تستخدم msvc2017 ، ربما يجب عليك تضمين هذه المعلومات في مكان ما).

Win32 ميؤوس منه هنا. أظن أن Linux 32 بت سيكون أيضًا فظيعًا جدًا ، لكن ليس لديك نظام Linux 32 بت للاختبار بسهولة.

يمكنني بالتأكيد رؤية حالة تقديم توصية للأشخاص الذين يتمسكون بجهاز 32 بت (على الأرجح Windows بسبب سياسات تكنولوجيا المعلومات الخاصة بالشركة). هذا recco واضح: DSFMT لـ 32 بت (أو MT19937 جيد أيضًا). لكن المعايير ستكون جيدة.

لما يستحق ، أنا متشكك في ادعاء PCG المتكرر في العديد من التدفقات العشوائية المستقلة . هل قام أحد بأي تحليل إحصائي جاد لدعم المطالبة بالاستقلال؟ (في الواقع ، أعتقد أن مقالة أونيل تشير فقط إلى التيارات "المتميزة" ، دون أي ادعاء بالاستقلال).

أعتقد أن هناك سببًا وجيهًا للشك: بالنسبة لمضاعف LCG معين ، فإن كل هذه التدفقات المميزة مرتبطة ببساطة عبر القياس [*]. لذلك ، بالنظر إلى أي دفقين LCG لهما نفس المضاعف ، فإن أحدهما سيكون ببساطة مضاعفًا ثابتًا (modulo 2**64 أو 2**32 حسب الاقتضاء) للآخر ، ولكن بنقاط بداية مختلفة. سيساعد جزء التقليب في PCG في إخفاء هذا قليلاً ، لكن لن يكون مفاجئًا حقًا إذا كانت هناك ارتباطات يمكن اكتشافها إحصائيًا.

تيارات متميزة للغاية ، بالتأكيد ، لكنني لن أتقبل ادعاء التدفقات المستقلة في ظاهرها دون بعض الاختبارات الجادة.

[*] مثال: افترض أن x[0], x[1], x[2], ... هو تدفق LCG قياسي 64 بت ، مع x[i+1] := (m*x[i] + a) % 2**64 . تعيين y[i] := 3*x[i] % 2**64 لكل i . ثم y[i] عبارة عن دفق LCG y[i+1] := (m*y[i] + 3*a) % 2**64 ، لذلك ببساطة عن طريق قياس الدفق الأصلي ، أنتجت أحد تدفقات LCG المميزة هذه بنفس المضاعف ولكن ثابت مضاف مختلف. باستخدام المضاعفات الفردية الأخرى بدلاً من 3 ، وبافتراض أننا مهتمون فقط بـ LCGs ذات الفترة الكاملة (وبالتالي فإن a أمر فردي) ، ستحصل على كل ما هو ممكن فترة LCGs مع هذا المضاعف.


تحرير: بيان خاطئ ثابت حول عدد فئات الاقتران.

أعتقد أن التحليل العام الأكثر شمولاً لتدفقات PCG موجود هنا: http://www.pcg-random.org/posts/critiquing-pcg-streams.html

imneme هل يمكنك التوسع في نصيحتك النهائية؟ "تُظهر المراسلات مع David Blackman أنه قد يكون أسهل مما كنت أتخيله إنشاء تدفقات" قريبة "مع عمليات تهيئة مرتبطة مثل بذرة ثابتة وتدفقات 1،2،3،4. إذا كنت ستستخدم تدفقات متعددة في في الوقت نفسه ، في الوقت الحالي ، أوصي بأن يكون معرف الدفق والبذرة متميزين وليس لهما ارتباطات واضحة مع بعضهما البعض ، مما يعني عدم جعلهما 1،2،3،4.

هل هذا يعني أنك تعتقد أنه من الجيد أن يكون لديك بذرة واحدة جيدة (على سبيل المثال مشتقة من مصدر إنتروبيا) ثم معرفات البث 1،2،3،4؟ أو هل يجب اختيار كلٍّ من معرّف البذور والتيار بشكل عشوائي من مصدر إنتروبيا جيد؟

بعض أرقام Linux-32 (Ubuntu 18.04 / GCC 7.4)

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

لذلك فهي أسرع مرتين من Win-32 ولكنها بطيئة. تم إجراء جميع الأوقات الأربعة على نفس الجهاز

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

NumPy هو NumPy 1.16.4. DSFMT هو المولد الوحيد الذي يتمتع بأداء جيد على 32 بت (x86). يجب توثيق ذلك بوضوح لأي مستخدم 32 بت. يعد MT19937 أيضًا اختيارًا جيدًا نسبيًا لمستخدم 32 بت.

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

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

كنت أشعر بالفضول إلى أي مدى يخفف الجزء "P" من PCG المشكلات المحتملة من التدفقات المرتبطة.

إذن هذه (ربما) أسوأ حالة ممكنة لـ LCGs: حيث يكون الثابت الإضافي لتيار LCG هو النفي الدقيق لثابت المادة المضافة للآخر. ثم مع الاختيارات الرهيبة المناسبة للبذور ، ينتهي بنا المطاف بأن يكون أحد تيارات LCG هو النفي الدقيق للآخر.

ولكن الآن إذا كنا نستخدم كلا الدفقين لإنشاء سلسلة من العوامات ، فيجب أن يساعدنا جزء التقليب في PCG والتحويل إلى float64 قليلاً.

إليك مخطط يوضح مدى فائدة التقليب:

streams

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

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

للسجل ، ها هو المصدر:

import matplotlib.pyplot as plt
import numpy as np

from pcgrandom import PCG64

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

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

PCG64 هو المولد الذي يطلق عليه O'Neill PCG-XSL-RR (القسم 6.3.3 من ورق PCG). حزمة pcgrandom من هنا

اعتقدت أن الطريقة القياسية للحصول على تدفقات مستقلة هي استخدام Jumpahead ().
إن إعادة البذر للحصول على تيارات "مستقلة" أمر خطير بشكل عام.

تحتوي مولدات العداد / التجزئة على قفزة تافهة (). هل PCG؟

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

في صحتك،
فيليب

(EDIT by seberg: تمت إزالة اقتباس البريد الإلكتروني)

pbstark : هذا ليس مجرد إعادة زرع:

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

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

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

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

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

mdickinson ، حاولت إعادة إنتاج الرسم البياني بنفسي وفشلت. لقد استخدمت نسخة C ++ المتعارف عليها من الكود مع هذا البرنامج الذي يجب أن يكون مكافئًا أخلاقيًا لك.

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

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

عندما أقوم بتشغيل هذا ، فإنه ينتج (للسماح بإمكانية التكاثر):

RNG1: 47026247687942121848144207491837523525 203756742601991611962280963671468648533 41579532896305845786243518008404876432
RNG2: 47026247687942121848144207491837523525 136525624318946851501093643760299562925 52472962479578397910044896975270170620

ونقاط البيانات التي يمكنها رسم الرسم البياني التالي:

corr1

إذا تمكنت من اكتشاف ما أفعله بشكل مختلف ، فسيكون ذلك مفيدًا.

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

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

لقد كتبت برنامجًا نصيًا صغيرًا سريعًا للمحرك يشتمل على عدة تدفقات PCG32 ، تم إنشاؤها بطرق مختلفة ، لتغذية PractRand. يستخدم master من numpy على Python 3. عندما أقوم بالضرب في الحالات / الزيادات الداخلية العدائية مباشرة ، يفشل PractRand بسرعة. ليس من الواضح بالنسبة لي ما إذا كان بإمكاننا إيجاد طرق معقولة لإيجاد بذور معادية (تمر فعليًا من خلال روتين التهيئة) لتحقيق حالات الخصومة.

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

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

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

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

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

لست خبيرا ولكن من ناحية التشفير فإن ما هو مقترح غير متوفر في:
https://cryptography.io/en/latest/ من هيئة تشفير Python ؟

تذكر صفحتهم الخاصة بتوليد الأرقام العشوائية أيضًا:

بدءًا من Python 3.6 ، تتضمن المكتبة القياسية وحدة الأسرار ، والتي يمكن استخدامها لإنشاء أرقام عشوائية آمنة مشفرة ، مع مساعدين محددين للتنسيقات المستندة إلى النصوص.

أعتقد ربما إضافة مصفوفات للجيل. يجب أن أتساءل عما إذا كان عبء الصيانة المحتمل لربطه بقوة crypotgraphic يستحق حقًا كل هذا العناء ومناسبًا في NumPy مقابل قل التواصل مع pyca وربما التفكير في مولد / مكون إضافي تابع لجهة خارجية لذلك. أعتقد أن ناثانيال ذكر مصدر قلق مماثل سابقًا.

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

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

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

لكن بالنظر إلى الصورة الأكبر ، أعتقد أنه من المنطقي النظر إلى المشكلات التي تواجه المستخدمين في الممارسة العملية. ما هي النصيحة التي نقدمها لهم ، وما إلى ذلك. لا يدرك معظم المستخدمين أن _بالنسبة لجميع PRNGs (الماضي والمستقبل) _ ، تعتبر بذرة 32 بت فكرة سيئة للغاية وتؤدي إلى تحيز يمكن اكتشافه بشكل تافه بغض النظر عن PRNG قيد التشغيل. بالتأكيد ، يمكننا تجاهل ذلك وقضاء وقتنا بدلاً من ذلك في القلق بشأن ما إذا كان شخص ما قد تمكن من تهيئة Mersenne Twister إلى حالة معظمها من الأصفار (أو حالة جميع الأصفار حيث تفشل LFSR في العمل على الإطلاق!) ، أو ما إذا كان شخص ما قد يتمكن من تهيئة قم بتهيئة Xoshiro بالقرب من النقطة التي يكرر فيها نفس الناتج سبع مرات في مساحة أحد عشر مخرجات ، أو اخترع دفقين متشابهين من PCG ، أو أي شيء آخر ، لكن كل هذه الوسائل لها فرصة متناهية الصغر (عمليًا صفر) لتحدث إذا كان المولد مصنفة ببيانات عشوائية. نظرًا لأن هذه التحويلات جذابة من الناحية الفكرية ومثيرة للاهتمام أكاديميًا ، فإن التفكير فيها مع تجاهل حقيقة أن المستخدمين عادة ما يكون لديهم فكرة بسيطة عما يفعلونه عندما يتعلق الأمر بالبذر هو أمر تافه بينما تحترق روما.

إذا كانت inc=1,2,3,4 فكرة سيئة ، ألا يشير ذلك إلى وجوب توثيقها بوضوح شديد ، أو ربما يجب أن يكون لدينا واجهة برمجة تطبيقات مختلفة قليلاً؟ ربما حتى new_generator = (Bit)Generator().independent() ، يمكننا وضع تحذير عليه إذا كان منشئ البت (الأساسي) لا يوفر طريقة رائعة لتحقيق ذلك.

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

بالنسبة لـ PCG ، يمكن فقط البذور -> uint64_t [2] -> splitmix64 (seed_by_array) -> uint128 مما يضمن انتشار البذور المنخفضة والمتتالية.

بالنسبة لـ PCG ، يمكن فقط البذور -> uint64_t [2] -> splitmix64 (seed_by_array) -> uint128 مما يضمن انتشار البذور المنخفضة والمتتالية.

أو مجرد استخدام أي تجزئة عدد صحيح جيد. (يجب أن يكون انحراف). هناك الكثير منها رخيصة وقصيرة. بضع جولات من Multiply – XorShift جيدة.

بالنسبة إلى وجهة نظر mdickinson ، أعتقد أنه لا يزال يريد قدرًا من الإقناع بأن الاعتماد على التدفق يقتصر على مجموعة صغيرة من الإعدادات المصطنعة / العدائية. وإذا كان الأمر كذلك ، فيمكننا حلها من خلال الممارسات المناسبة لمنع مثل هذه الحالات. مع الكود الحالي الذي لدينا ، هناك بعض الحالات السيئة التي قد ينتقل المستخدمون إليها بسهولة مع واجهات برمجة التطبيقات الحالية. أستطيع أن أؤكد اكتشاف David Blackman أن تعيين كل من seed=1 و inc=0,1,2,... يخلق ارتباطات. يمكن استخدام أحدث برنامج تشغيل لي PractRand لتدفقات PCG32 المشذرة لإثبات ذلك.

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

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

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

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

لم أواجه فشلًا بعد مع بذرة عشوائية ولكن بنفس الزيادات المتقاربة. سأتحقق معك غدًا.

ألاحظ أننا لا نستخدم الزيادة الافتراضية الموصى بها عندما لا يتم تحديد أي منها في المنشئ. ربما يجب علينا إصلاح ذلك. ربما يكون هذا رقمًا أساسيًا جيدًا نستمد منه الزيادة الفعلية من معرف البث المحدد بدلاً من 2*inc + 1 .

يمكننا محاولة بناء بعض الأدوات لمساعدة الناس في استخدام بذور الانتروبيا الافتراضية وإنقاذها. أحد الأسئلة التي لدي هو ما إذا كان من الممكن إنشاء الزيادات في التدفقات المتعددة ببساطة أو إذا كنا بحاجة أيضًا إلى أخذ عينات من الانتروبيا وحفظها أيضًا. من الملائم حقًا أن تكون قادرًا على ترميز "الحالة الأولية" للمحاكاة كرقم واحد يمكن نسخه من البريد الإلكتروني للزميل بدلاً من ملف معتم. مع هذه PRNGs الأصغر مع 128 أو 256 بت فقط من الحالة ، يمكنني بسهولة طباعة ذلك في شكل سداسي عشري في ملف السجل الخاص بي ثم نسخه ولصقه في سطر الأوامر عندما أريد إعادة إنتاجه. إنه أكبر من عدد صحيح 32 بت ، لكن يمكن التحكم فيه. إذا اضطررت إلى أخذ عينة من جميع معرّفات البث الخاصة بي أيضًا ، فيجب عليّ التخلي عن ذلك والتأكد من أنني أسجل كل شيء في ملف الحالة في مكان ما. قد يؤدي ذلك إلى منع بعض حالات الاستخدام التي ناقشناها حيث نريد نشر تدفقات جديدة ديناميكيًا. إذا كان بإمكاني فقط زيادة عداد للحصول على معرف تدفق جيد (ربما اشتقاقه من خلال تجزئة العداد ، أو أي شيء آخر) ، فأنا بحاجة فقط لتسجيل المصدر الأولي وليس معرفات البث.

IIRC ، تستدعي وحدة الأسرار مصدر إنتروبيا نظام التشغيل ، والذي يمكن أن يكون تمامًا
سيئة في بعض الأنظمة ، ولا يمكن تكرارها / استنساخها بغض النظر.

يوم الأربعاء ، 29 مايو ، 2019 الساعة 3:19 مساءً Tyler Reddy [email protected]
كتب:

أنا لست خبيرا ، ولكن من ناحية التشفير ، ما هو مقترح
غير متوفر في:
https://cryptography.io/en/latest/ من هيئة تشفير Python
https://github.com/pyca ؟

صفحتهم على توليد عدد عشوائي
https://cryptography.io/en/latest/random-numbers/ يذكر أيضًا:

بدءًا من Python 3.6 ، تتضمن المكتبة القياسية الأسرار
https://docs.python.org/3/library/secrets.html الوحدة النمطية ، والتي يمكن أن تكون
تستخدم لتوليد أرقام عشوائية آمنة مشفرة ، مع محدد
المساعدين للتنسيقات النصية.

أعتقد ربما إضافة مصفوفات للجيل. يجب أن أتساءل عما إذا كان
عبء الصيانة المحتمل لكونه مرتبطًا بالتصوير
المتانة تستحق العناء حقًا وهي مناسبة في NumPy مقابل القول
التواصل مع pyca وربما التفكير في طرف ثالث
مولد / البرنامج المساعد لذلك. أعتقد أن ناثانيال ذكر مصدر قلق مماثل
سابقا.

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

-
أنت تتلقى هذا لأنه تم ذكرك.
قم بالرد على هذا البريد الإلكتروني مباشرة ، وقم بعرضه على GitHub
https://github.com/numpy/numpy/issues/13635؟
أو كتم الخيط
https://github.com/notifications/unsubscribe-auth/AANFDWKGZMUB67VPCMFZYGTPX36O3ANCNFSM4HPX3CHA
.

-
فيليب بي ستارك | عميد مشارك للعلوم الرياضية والفيزيائية |
أستاذ بقسم الإحصاء |
جامعة كاليفورنيا
بيركلي ، كاليفورنيا 94720-3860 | 510-394-5077 | Statistics.berkeley.edu/~stark |
تضمين التغريدة

tylerjereddy هذه مخصصة للحصول على كمية صغيرة من البتات العشوائية من مصدر إنتروبيا مادي لا يمكن للمهاجم (وأنت!) التنبؤ به. يتم استخدامها في التشفير لأشياء مثل متجهات التهيئة ، الرموز غير الرسمية ، المفاتيح ، وكلها قصيرة. بيت القصيد من هذه أنه لا توجد طريقة لإعادة إنتاجها ، وهو ما يتعارض مع أغراض المحاكاة العددية np.random . لا تتحدث هذه الصفحة عن _reproducible_ الآمنة المشفرة PRNGs ، وهي أيضًا أشياء موجودة و _ يمكن_ إنشاؤها من العناصر الأولية المتوفرة في الحزمة cryptography . ومع ذلك ، في _ الممارسة_ ، لدينا تطبيقات أفضل لهذه الخوارزميات متاحة بالفعل لنا في كود C الفعال ، على الأقل تلك التي تمت صياغتها واختبارها لأغراض المحاكاة. قامbashtage بتنفيذ عدد قليل من هذا الإطار.

أريد أيضًا أن أوضح للفريق الخفي أن ما يقترحهpbstark ليس مجرد برنامج

معظم PRNGs المستندة إلى التشفير والتي يتم اعتبارها عمومًا للمحاكاة لا تملك الحالة غير المحدودة التي يريدها pbstark . عادة ما تقوم على تشفير عداد محدود. بمجرد أن يدور هذا العداد ، تكون قد وصلت إلى الفترة المحددة. من الناحية الفنية ، يرتبط cryptorandom أيضًا بشروط أولية فريدة من نوعها لـ 2**(256+64) بسبب حالة الملخص ذات الحجم الثابت 256 بت وعداد الطول ذو الحجم الثابت 64 بت. ربما يشير ذلك إلى طريقة تنفيذ PRNG غير المحدود حقًا من خلال جعل عداد الطول بحجم تعسفي ، لكنني لم أر مثل هذه الخوارزمية منشورة أو مختبرة.

من ناحية أخرى ، إذا كنت تريد فقط خوارزمية PRNG لها حالة ذات حجم تعسفي ، واحدة فقط تم إصلاحها في البداية لشيء فوق ما تحتاجه ، فإن مولدات PCG الموسعة ستعمل بشكل جيد لهذه المهمة. من الواضح أن هذه ليست CS-PRNGs ، لكنها في الواقع ستلبي رغبة

هناك خصائص أخرى تمتلكها CS-PRNGs القياسية والمحدودة والتي قد نريدها ، لكنها ليست افتراضية ، IMO.

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

يوم الأربعاء ، 29 مايو ، 2019 الساعة 7:26 مساءً Robert Kern [email protected]
كتب:

tylerjereddy https://github.com/tylerjereddy هؤلاء هم للحصول على
كمية صغيرة من البتات العشوائية من مصدر إنتروبيا فيزيائي
لا يمكن التنبؤ بها للمهاجم (وأنت!). يتم استخدامها في التشفير ل
أشياء مثل متجهات التهيئة ، الرموز غير الرسمية ، المفاتيح ، وكلها قصيرة. ال
بيت القصيد من هذه أنه لا توجد طريقة لإعادة إنتاجهم ، وهو في
تتعارض مع أغراض المحاكاة العددية لـ np.random. تلك الصفحة
لا أتحدث عن PRNGs آمنة مشفر استنساخه، الذي
هي أيضًا أشياء موجودة ويمكن بناؤها من الأوائل
متوفر في حزمة التشفير. في الممارسة العملية ، ومع ذلك ، لدينا
أفضل تطبيقات تلك الخوارزميات المتاحة لنا بالفعل في
كود C فعال ، على الأقل تلك التي تمت صياغتها واختبارها
لأغراض المحاكاة. تنفيذ bashtage https://github.com/bashtage
قليل https://github.com/numpy/numpy/issues/13635#issuecomment-496287650
لهذا الإطار.

أريد أيضًا أن أوضح للفريق الخفي أنpbstark
https://github.com/pbstark يقترح ليس فقط أي مستند على التشفير
PRNG. بدلا من ذلك ، يريد واحد مع حالة غير محدودة ، والتي من شأنها أن توفر
الخاصية الرياضية التي يبحث عنها.

معظم PRNGs المستندة إلى التشفير والتي تعتبر عادة للمحاكاة
ليس لديك الحالة غير المحدودة التيpbstark
https://github.com/pbstark يريد. عادة ما تقوم على أساس
تشفير عداد محدود. بمجرد أن يدور هذا العداد ، فإنك تضغط على
فترة محدودة. من الناحية الفنية ، فإن عشوائه المشفر
https://statlab.github.io/cryptorandom/ مقيد أيضًا بـ 2 ** (256 + 64)
شروط أولية فريدة بسبب حالة ملخص 256 بت ذات حجم ثابت و
عداد طول 64 بت بحجم ثابت. ربما يشير هذا الطريق إلى
تنفيذ PRNG غير محدود حقًا عن طريق عمل عداد الطول
الحجم التعسفي ، لكنني لم أر مثل هذه الخوارزمية منشورة أو
تم اختباره.

من ناحية أخرى ، إذا كنت تريد فقط خوارزمية PRNG لها امتداد
حالة الحجم التعسفي ، واحدة فقط تم إصلاحها في البداية
شيء فوق كل ما تحتاجه ، ثم مولدات PCG الممتدة
http://www.pcg-random.org/party-tricks.html سيعمل بشكل جيد لذلك
مهمة. من الواضح أن هذه ليست CS-PRNGs ، لكنها سترضي بالفعل
pbstark https://github.com/pbstark رغبة في الحصول على مساحات دولة ضخمة
على الطلب. ومع ذلك ، لا أوصي بإدراجهم في numpy.

هناك خصائص أخرى تمتلكها CS-PRNGs القياسية والمقيدة
قد نرغب ، لكنهم ليسوا تقصيرًا في عدم التفكير ، IMO.

-
أنت تتلقى هذا لأنه تم ذكرك.
قم بالرد على هذا البريد الإلكتروني مباشرة ، وقم بعرضه على GitHub
https://github.com/numpy/numpy/issues/13635؟email_source=notifications&email_token=AANFDWLGAF6YVIWXYZ2LTT3PX43ONA5CNFSM4HPX3CHKYY3PNVWWK3TUL52HS4DFVREXG43VMVMissment
أو كتم الخيط
https://github.com/notifications/unsubscribe-auth/AANFDWLIJD3UCVY3NXCLPKDPX43ONANCNFSM4HPX3CHA
.

-
فيليب بي ستارك | عميد مشارك للعلوم الرياضية والفيزيائية |
أستاذ بقسم الإحصاء |
جامعة كاليفورنيا
بيركلي ، كاليفورنيا 94720-3860 | 510-394-5077 | Statistics.berkeley.edu/~stark |
تضمين التغريدة

أخشى أن هذه ليست الطريقة التي يعمل بها التحديث عبر الإنترنت لـ SHA-256. الحالة التي تحتفظ بها هي فقط ملخص 256 بت وعداد طول 64 بت ذو الحجم الثابت الذي يتم إلحاقه عند حساب التحديث. لا يحتوي على النص بأكمله. ضغط التجزئة. هذه هي الطريقة التي يمكنه بها إجراء التحديث الفعال على كل بايت. بشكل أساسي ، هناك العديد من عمليات التهيئة / التواريخ السابقة التي ترتبط بنفس حالة SHA-256 الداخلية ، وهي حالة محدودة. في حين أن الدورات طويلة بالتأكيد ، وربما أطول من 2**(256+64) ، إلا أنها موجودة بالتأكيد. وعلى أي حال ، لديك فقط شروط أولية محتملة أقل من 2**(256+64) (لكل طول نص من 0 إلى 2**64-1 ، يمكنك الحصول على 2**256 حالات تجزئة داخلية على الأكثر ؛ مرة واحدة يزيد طول النص عن 32 بايت ، يجب أن يكون هناك تصادمات من نوع la pigeonhole). لم يعد هناك أي وحدات بت في بنية البيانات.

شكرا جزيلا؛ يفهم. أود أن أعبر عن ذلك بشكل مختلف: الدولة
الفضاء غير محدود ، ولكن (من خلال الحمام) يجب أن يكون هناك العديد من الحالات الأولية المميزة
إنتاج تسلسلات إخراج لا يمكن تمييزها.

يوم الأربعاء ، 29 مايو ، 2019 الساعة 8:21 مساءً Robert Kern [email protected]
كتب:

أخشى أن هذه ليست الطريقة التي يعمل بها التحديث عبر الإنترنت لـ SHA-256. الولاية
التي تحافظ عليها هي فقط ملخص 256 بت والحجم الثابت 64 بت
عداد الطول الذي يتم إلحاقه عندما يحسب التحديث. لا تصمد
النص بأكمله. ضغط التجزئة. هذه هي الطريقة التي يمكنه بها القيام بالكفاءة
التحديث على كل بايت. في الأساس ، هناك العديد من عمليات التهيئة / الماضي
التواريخ التي ترتبط بنفس حالة SHA-256 الداخلية ، وهي حالة محدودة.
في حين أن الدورات طويلة بالتأكيد ، وربما أطول من 2 (256 + 64) ، إلا أنهاموجودة بالتأكيد.
الشروط الأولية الممكنة (لكل نص طول من 0 إلى 2 64-1 ، يمكنك ذلكتحتوي على 2 256 حالة تجزئة داخلية
بايت ، يجب أن تكون هناك اصطدامات على طراز pigeonhole). ليس هناك أي شيء
المزيد من البتات في بنية البيانات.

-
أنت تتلقى هذا لأنه تم ذكرك.
قم بالرد على هذا البريد الإلكتروني مباشرة ، وقم بعرضه على GitHub
https://github.com/numpy/numpy/issues/13635؟email_source=notifications&email_token=AANFDWO6HRJZHTVBF2TLK3LPX5B3TA5CNFSM4HPX3CHKYY3PNVWWK3TUL52HS4DFVREXG43VM33TUL52HS4DFVREXG43VM
أو كتم الخيط
https://github.com/notifications/unsubscribe-auth/AANFDWM56HCQRZXDO3BAQHDPX5B3TANCNFSM4HPX3CHA
.

-
فيليب بي ستارك | عميد مشارك للعلوم الرياضية والفيزيائية |
أستاذ بقسم الإحصاء |
جامعة كاليفورنيا
بيركلي ، كاليفورنيا 94720-3860 | 510-394-5077 | Statistics.berkeley.edu/~stark |
تضمين التغريدة

كما أنه لا يوجد سوى 2**(256+64) حالات يمكن أن يمر بها. نظرًا لأن التحديث يأخذ نفس الشكل في كل مرة ، فإنك في النهاية تصل إلى حالة رأيتها من قبل وتدخل في حلقة غير معروفة (بالنسبة لي) ولكنها محدودة. سواء كان ذلك العدد المحدود للحالات الأولية أو فترة محددة ، فإن cryptorandom يحتوي على كلاهما ، وأعتقد أنهما أصغر حتى من MT19937 .

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

لم أواجه فشلًا بعد مع بذرة عشوائية ولكن بنفس الزيادات المتقاربة. سأتحقق معك غدًا.

لا يزال قويًا عند 512 جيجا بايت:

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

إذا تمكنت من اكتشاف ما أفعله بشكل مختلف ، فسيكون ذلك مفيدًا.

أعتقد أنك بحاجة إلى استبدال السطر pcg64 rng2(-seed,-stream); في الكود الخاص بك بـ pcg64 rng2(-seed,-1-stream); ، للسماح بتحويل increment = 2 * stream + 1 . يناظر نفي الزيادة النفي على مستوى البت لمؤشر التيار. إذا قمت بإجراء هذا التغيير وقمت بتشغيل الكود الخاص بك ، فإنني أرى شيئًا يشبه إلى حد كبير حبكتي السابقة. (وأؤكد أنني إذا لم أجري هذا التغيير ، فسيبدو كل شيء جيدًا بصريًا.)

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

الطريقة الصحيحة للتفكير في التدفقات هي مجرد حالة عشوائية أكثر تحتاج إلى بذور.

متفق عليه. أعتقد أن هذا يعطي صورة واضحة جدًا لـ LCGs: بالنسبة لـ LCG 64 بت مع مضاعف ثابت مختار جيدًا a ، لدينا مساحة حالة بحجم 2^127 ، تتكون من جميع الأزواج (x, c) للأعداد الصحيحة mod 2 ^ 64 ، حيث c هي الزيادة الفردية. وظيفة تحديث الحالة هي next : (x, c) ↦ (ax+c, c) ، تقسم مساحة الولاية إلى 2^63 دورات منفصلة بطول 2^64 لكل منها. البذر ينطوي فقط على اختيار نقطة البداية في مساحة الولاية هذه.

هناك بعد ذلك إجراء جماعي واضح يجعل التحليل سهلاً ، ويجعل العلاقات بين التدفقات المختلفة واضحة: مجموعة التحويلات الأفقية 1-د العكسية على Z / 2^64Z لديها طلب بالضبط 2^127 ، وتعمل بشكل انتقالي (وكذلك أيضًا بأمانة) في مساحة الولاية: التحويل الأفيني y ↦ ey + f يعين الزوج (x, c) إلى (ex + f, ec + (1-a)f) . ينتقل إجراء المجموعة باستخدام الوظيفة next ، لذا فإن عنصر المجموعة الفريد الذي يحول نقطة واحدة (x, c) في مساحة الولاية إلى أخرى ، (x2, c2) ، يعين أيضًا التسلسل الناتج عن (x, c) للتسلسل الناتج عن (x2, c2) .

tl ؛ dr: بالنسبة لمضاعف ثابت ، يرتبط أي تسلسلين من LCG لهما نفس المضاعف (سواء باستخدام نفس الزيادة ، كما في حالة lookahead أو زيادات مختلفة) بتحويل أفيني. في الحالات المؤسفة التي نريد تجنبها ، يكون هذا التحويل التقريبي أمرًا بسيطًا للغاية ، مثل إضافة 2 أو الضرب في -1 . في الحالة العامة ، نأمل أن يكون التحويل الأفيني معقدًا بدرجة كافية بحيث لا تتمكن الاختبارات الإحصائية القياسية من اكتشاف العلاقة بين التدفقين.

mdickinson يغطي الوضع بشكل جيد. ستغير تباديل PCG الأشياء قليلاً من حالة LCG ، ولكن ليس كثيرًا. بيت القصيد من تباديل PCG هو أنه يمكننا اختيار مقدار التدافع للقيام به. نظرًا لأن LCGs المقتطعة 128 بت قد اجتازت بالفعل BigCrush ، فعندما اخترت تبديلًا لـ pcg64 ، اخترت قدرًا متواضعًا من التدافع لهذا الحجم LCG (XSL RR). في المقابل ، سرعان ما تفشل LCGs ذات 64 بت في العديد من الاختبارات الإحصائية ، لذا فإن pcg32 يستخدم مزيدًا من التدافع ، لكنه لا يزال ليس أقوى تبديل من ورقة PCG. كما ذكرت في مؤشر ترابط طلب سحب الخيط ، لقد بدأت في الميل نحو تبديل أقوى لـ PCG (RXS M) لحالة استخدام pcg32 . إنه ليس الإعداد الافتراضي بعد ، يجب أن تطلب هذا الإصدار صراحة ، ولكن هناك فرصة جيدة لأنني سأغير الإعداد الافتراضي عندما أقوم بإصدار كبير من أجل PCG. (RXS M هو النصف الأعلى من RXS M XS ، والذي اختبرته Vigna على نطاق واسع بهذا الحجم وأيضًا التبديل الذي يحبه David Blackman).

يمكننا تصور الاختلاف ، حيث تستخدم نسخة محدثة من برنامج اختبار التدفقات القريبة كلا المخططين لـ pcg32 (XSH RR و RCS M [و LCG الأساسي الخام أيضًا]):

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

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

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

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

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

قبل أن نبدأ ، دعنا ننظر إلى الرسم البياني الذي رسمهmdickinson ولكن لمجرد LCG بدون تبديل ، فقط اقتطاع:

corr-truncated-lcg

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

corr-truncated-lcg-good

بالانتقال إلى وظائف الإخراج الخاصة بـ PCG ، إذا استخدمنا XSH RR في الحالة المرضية فإنها تبدو هكذا - إنه تحسن كبير على الرسم البياني أعلاه ولكن من الواضح أنه لا يحجب الفظاعة تمامًا:

corr-pcg32-current

وهذا هو RXS M مع نفس زوج LCG الأساسي (المرتبط بشكل سيئ):

corr-pcg32-future

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

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

في الختام ، بالنسبة لـ NumPy ، أعتقد أنه قد يكون من المنطقي أن نفكر فقط في أن PCG64 يريد 256 بت من الحالة (تقنيًا 255 نظرًا لتجاهل الجزء العالي من الدفق) واستدعائه تم. سيؤدي ذلك إلى تجنب المشكلات المتعلقة بواجهة برمجة التطبيقات أيضًا لأنها ستكون ميزة أقل لدى الأشخاص في BitGenerator وليس في آخر.

(ولكن قد ترغب في تبديل متغير PCG 32 بت إلى RXS M واحد. بالنسبة لمصدر C ، فأنت بحاجة إلى إصدار حديث لأنني لم أكن أزعج عناء تقديم RXS M بشكل صريح في كود C ، وإتاحته فقط في C ++ التجسد.)

[آسف إذا كان هذا أكثر مما كنت تريد أن تعرفه! حسنًا ، لا _that_ آسف. ؛-)]

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

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

لدينا الآن أدوات جيدة في Python لتدوير عمليات N المتوازية ديناميكيًا للقيام ببعض العمل ثم جمع النتائج والمضي قدمًا في العملية الرئيسية (ثم تدوير عمليات M لاحقًا ، إلخ). على عكس المخططات الأقدم والأقل مرونة مثل MPI ، فإننا لا نقوم فقط بتدوير عمليات N ثابتة في البداية. في تلك الحالات ، يمكن أن أرى كل من N PRNGs في الانتروبيا وحفظها في ملف لأن هناك مكانًا واحدًا فقط في البرنامج يقوم بذلك. على الأقل من منظور البرمجة ، هذا ليس بالأمر الصعب. لدينا أدوات أكثر مرونة للتوازي الآن. إن زرع PRNGs هو الآن عنق الزجاجة الذي يمنعنا من استخدام تلك المرونة في البرامج العشوائية. لم تعد هناك نقطة مسؤولية واحدة حيث يمكننا وضع مسك الدفاتر المستند إلى الملفات.

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

ما رأيك في استخدام تجزئة bijective جيدة تزيد عن 2**63 / 2**127 لاشتقاق الزيادات من تسلسل مضاد 0،1،2،3 ، ... مع الحفاظ على الحالة نفسها؟ هل تتوقع مشاكل في ذلك؟ ما رأيك في الجمع بين زيادة التجزئة متبوعة بقفزة كبيرة لنقل الحالة إلى جزء بعيد من الدورة الجديدة؟ ربما يمكننا نقل هذه المناقشة الفرعية إلى البريد الإلكتروني أو مشكلة أخرى والإبلاغ عنها مرة أخرى.

rkern ، قد يكون هناك شيء يشعر

تتفاقم المشكلة عندما يستخدم الجميع ، على سبيل المثال ، نفس PRNG (مثل Mersenne Twister) ويجمع البذور من نفس المجموعة الصغيرة (على سبيل المثال ، الأرقام أقل من 10000) ، لأنه بدلاً من التحيز التعسفي المحدد لكل برنامج ، a _ لكل من يفعل هذا_ التحيز. على سبيل المثال ، لنفترض أنك اخترت بذرة مكونة من أربعة أرقام ثم حصلت على عدد معقول من الأرقام من Mersenne Twister (على سبيل المثال ، أقل من مليون). في هذه الحالة ، يمكنني أن أؤكد لكم أن الرقم غير المحظوظ 13 _ لن يظهر أبدًا _ حيث أن أيًا من المخرجات البالغ عددها 10 مليارات (في الواقع ، حوالي 10٪ من الأعداد الصحيحة ذات 32 بت ستكون غائبة) ، والرقم 123580738 يتم تمثيله بشكل مفرط بعامل من 16. هذا بالضبط ما كنا نتوقعه لعينة عشوائية من عشرة مليارات من الأعداد الصحيحة 32 بت ، لكنها مشكلة حقيقية - إذا كان الجميع يستخدمون نفس العينة_. سيكون لدينا مشكلة مماثلة تمامًا إذا اختار كل شخص بذرة مكونة من تسعة أرقام ورسم 10000 رقم فقط.

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

(هذا هو الكود الذي يجب اللعب به ، لأنه قصير إلى حد ما ...)

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

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

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

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

لنفترض أنه يمكنني حمل الناس على استخدام بذور جيدة بحجم 128 بت للجزء الخاص بالولاية من PCG64 ، بطريقة أو بأخرى. هل لديك أي تعليقات على استخلاص التدفقات من نفس الولاية؟ أنا لا أتطلع إلى رسم المزيد من الأرقام ، بشكل عام ، أكثر مما نفعله من دفق PCG64 . أريد فقط أن أكون قادرًا على رسم هذه الأرقام في عمليات مختلفة دون تنسيق في كل سحب. يبدو أن استخدام تجزئة مضاعفة xorshift ذات 63 بت مخصصة تعمل بشكل جيد حتى الآن (أنا في 32 جيجا بايت الآن) ، من أجل 8192 تدفقات معشق.

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

قد يكون من المفيد تحديد ما نعنيه باختصار.

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

أريد فقط أن أكون قادرًا على رسم هذه الأرقام في عمليات مختلفة دون تنسيق في كل سحب. يبدو أن استخدام تجزئة مضاعفة xorshift ذات 63 بت مخصصة تعمل بشكل جيد حتى الآن (أنا في 32 جيجا بايت الآن) ، من أجل 8192 تدفقات معشق.

هل جربت تشذير تدفقات n باستخدام بذرة واحدة عالية الجودة عن طريق تقديم الحالة بعدد كبير بما يكفي (لنقل 2 ** 64 ، وهو ما يستخدمه PCG64.jumped )؟ يبدو أن هذا هو أبسط طريقة لتنسيق التدفقات الكبيرة n عبر مجموعة باستخدام شيء مثل PCG64(seed).jumped(node_id)

حيث node_id هو 0،1،2 ، ...

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

bashtage ، هذه ليست الطريقة الصحيحة للقيام بذلك. الطريقة الصحيحة هي أن تأخذ بذرة ، إذا كنت ترغب في إضافة عدد صحيح صغير ، فاستخدم دالة التجزئة لتجزئةها. كما ذكرنا سابقًا ، كتبت سابقًا (بشكل مستقل عن PCG) وظيفة خلط جادة [تحرير: رابط الإصلاح إلى الوظيفة الصحيحة] لخلط أنواع مختلفة من الانتروبيا الكبيرة والصغيرة. لست مضطرًا لاستخدام خاصتي ، لكنني أوصيك بعمل شيء على هذا المنوال.

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

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

imneme في الوقت الحالي ، PRNG.jumped() . هل هذا شيء يجب ثنيه؟

بالنسبة إلى البذر ، تستفيد مولدات MT من إجراءات المؤلف الأولية ، وتستخدم PCG إجراءاتك ، والباقي شيء مثل

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

أتخيل أن هذا يمكن تحسينه.

هل هذا شيء يجب ثنيه؟

لم أشاهد jumped . إنه أمر مروع للغاية بالنسبة لـ LCG الأساسي.

افترض أن لدينا مضاعف M 0x96704a6bb5d2c4fb3aa645df0540268d . إذا قمنا بحساب M ^ (2 ^ 64) ، فسنحصل على 0x6147671fb92252440000000000000001 وهو مضاعف LCG رهيب. وبالتالي ، إذا أخذت كل 2 ^ 64 عنصرًا من LCG 128 بت ، فسيكون ذلك فظيعًا (البتات ذات الترتيب المنخفض هي مجرد عداد). تم تصميم وظائف التقليب القياسية لـ PCG لتتبادل الإخراج العادي لـ LCG ، وليس لتخليط العدادات.

يتم اختبار PCG64 حاليًا بما يصل إلى نصف بيتابايت باستخدام Practrand ويظهر التحليل الإضافي أنه يمكنك قراءة العديد من البيتابايت دون مشاكل تتعلق بقدرات اثنين. للأسف ، إذا قفزت إلى الأمام لتخطي قوى دقيقة هائلة من اثنين ، فإن التباديل المعتاد لـ PCG (المتواضع إلى حد ما) لا يمكن أن يعوض بشكل كافٍ عن التسلسل المرضي من تخطي مسافات LCG الأساسية الضخمة مثل هذه. يمكنك زيادة قوة التقليب لإصلاح ذلك ، وفي الواقع قارنت كل من I و Vigna بشكل مستقل التباديل القياسي لـ PCG مقابل وظائف التجزئة الصحيحة الجاهزة التي من المحتمل أن تفعل ذلك (بعد كل شيء ، إنها أساس SplitMix الذي _ هو_ مجرد عداد). عندما نظرت في الأمر في عام 2014 باستخدام Fast Hash ، لم تكن السرعة تبدو رائعة جدًا ، ولكن عندما فعلها Vigna مؤخرًا مع التهام ، ادعى أن الأداء تفوق على PCG القياسي (!).

إذا كنت ترغب حقًا في الحصول على قفزة 2 ^ 64 ، أعتقد أنك بحاجة إلى التبديل إلى تبديل أقوى لوظيفة الإخراج (وهو ما رأيناه قد يتم بتكلفة منخفضة). ولكن إذا شعرت أن هذا يجعله ليس PCG "قياسيًا" حقًا بعد الآن وترغب في الحفاظ على التقليب المعتاد للإخراج ، فمن المحتمل أن jumped() بحاجة للذهاب.

(راجع للشغل ، تنطبق قفزة مرضية للأمام على PRNGs الأخرى أيضًا. من المعروف أن SplitMix لديها بعض الزيادات السيئة ومن المعقول أن نفترض أنه على الرغم من أن الزيادة المعتادة (المعروفة أيضًا باسم "جاما") لـ 0xbd24b73a95fb84d9 جيدة ، إلا أنها تتقدم بمقدار 2 ^ 32 سيمنحك زيادة قدرها 0x95fb84d900000000 ، وهذا ليس جيدًا. بالنسبة إلى LFSR ، ربما لا تكون القفزة السيئة للأمام قوة من اثنين ، لكنني متأكد تمامًا أنه ستكون هناك قفزات حيث تنتهي المصفوفة الأساسية بشكل مرضي متناثر.)

يمكنني التأكيد ، على الأقل مع PCG32 ، 4 تدفقات متداخلة باستخدام .jumped() تفشل بسرعة كبيرة.

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

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

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

حسنًا ، هذا ما نحاول تحديده هنا. :-) كنا راضين بشكل معقول عن مجرد كشف الميزات التي يوفرها كل PRNG ، على افتراض أن الخصائص التي تعرضها كل خوارزمية تمت دراستها جيدًا. نحن أيضًا نكتفي بشكل معقول بقول "هذا هو PRNG الافتراضي الذي نوصي به ؛ يحتوي على مجموعة من الميزات المفيدة ؛ قد لا يمتلكها الآخرون".

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

من ناحية أخرى ، إذا كان الأمر يتعلق فقط بتخصيص عدد كافٍ من دورات وحدة المعالجة المركزية لاختبار التدفقات المتشابكة لكل BitGenerator إلى N GiB على PractRand ، فهذا ليس مرهقًا للغاية.

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

لا أعلم أنه يمكنك تسميتها "مشكلة بحثية" (وبالتالي "مدروسة جيدًا") بالضبط ، ولكن C ++ 11 (الذي كان في الغالب يتعلق باستخدام تقنيات مجربة وحقيقية طويلة الأمد) يوفر مفهوم _SeedSequence_ (و تنفيذ std::seed_seq المحدد) الذي تتمثل مهمته في توفير بيانات البذر إلى PRNGs التعسفية تمامًا.

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

من السهل إلى حد ما التفكير في مجموعة من PRNGs من نفس المخطط المصنفة جميعها مع وحدات البت العشوائية الخاصة بها. يمكنك التفكير في ما نقوم به على أنه نقاط انتقاء (أو فترات زمنية تصل إلى حد أقصى معين للطول يتوافق مع مقدار الأرقام العشوائية التي نتوقع أن نطلبها بشكل معقول ، على سبيل المثال ، 2 ^ 56) على سطر (على سبيل المثال ، خط مع 2 ^ 255 نقطة). يمكننا حساب احتمال أن يتداخل أحدهما مع الآخر إذا طلبنا فترات _n_. إنه احتمال أساسي إلى حد ما - لست متأكدًا من أنه يمكنك نشر ورقة حول هذا الموضوع لأنه (كما أفهمها) لا أحد متحمس أبدًا بشأن الأوراق التي تحتوي على رياضيات أولية. ( lemire قد يختلف!)

[سأجادل بأن ما يجب عليك عمومًا ألا تفعله هو زرع PRNG مع بتات عشوائية تخرج من نفسها. هذا يبدو لي زنا المحارم.]

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

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

بشكل أساسي ، إذا فكرنا في PRNGs كوظائف انتقالية ووظائف مخرجات ، فإن هذا new_state = seed_seq(old_state||streamID) هو مجرد وظيفة انتقال أخرى نقوم بإسقاطها في خطوة واحدة. علينا أن نتأكد من أن العمليات المتضمنة في ذلك seed_seq مختلفة بما فيه الكفاية عن وظائف الانتقال في كل خوارزمية PRNG (أو انعكاساتها) وربما يتعين علينا التأكد من أشياء أخرى. لا أريد استخدام شيء تم إنشاؤه من ، على سبيل المثال ، wyhash لتهيئة wyrand . كما قلت ، لا تريد استخدام PRNG نفسه لتوفير البتات لنفسه. لهذا السبب أعتقد أنه يحتاج إلى بعض الدراسة للتأكد من ذلك بالنسبة لجميع PRNGs (الدراسة التي كنت آمل ألا أضطر إلى القيام بها بنفسي).

من ناحية أخرى ، ربما لا يكون new_state = seed_seq(old_state||streamID) أسوأ من الوضع في هذا الصدد من الاستخدام المقصود لـ _SeedSequence_ لتدفقات متعددة: اسحب حالتين بالتسلسل. إذا كان الأمر كذلك ، فسأكون بخير على تجربة C ++ ، ربما مع التنفيذ الخاص بك ، وإجراء بعض الاختبارات التجريبية مع PractRand لجميع خوارزمياتنا لإظهار أنها ليست أسوأ من نظيراتها ذات التيار الواحد.

سيكون من الجيد حقًا تشغيل قفزة التجزئة لأن ذلك يفتح بعض حالات الاستخدام لتوليد PRNGs بطريقة خالية من التنسيق. يتطلب استخدام معرفات الدفق بعض الاتصالات أو التخصيص المسبق. dask شيئًا كهذا في الماضي.

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

بعد كل ما قيل ، يبدو أن استخدام تجزئة 63 بت لاشتقاق زيادة PCG32 من معرّفات الدفق المتسلسل ( range(N) ) يبدو أنها تعمل. 8192 تيارات مشذرة تمرر PractRand خارج إلى 2 تيرابايت. إذا كشفنا معرّفات الدفق لمولدات PCG ، فقد نرغب في استخدام هذه التقنية لاشتقاق الزيادات ، حتى لو اقترحنا على الأشخاص استخدام وسائل أخرى للحصول على تدفقات مستقلة بشكل متكرر.

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

ربما أعربت عن نفسي بشكل غامض ، لكن لا ،

لكن ، FWIW ، SplitMix تفعل هذا ، هذا ما تفعله العملية split() . وأنا لا أحب أن يفعل ذلك.

قد تكون هذه معلومات كثيرة جدًا ، لكنني سأشاركها قليلاً حول سبب شعوري بالرعب (ربما أكثر رعبًا مما ينبغي) من وظيفة SplitMix split() . كملاحظة تاريخية ، تم تصميم SplitMix و PCG بشكل مستقل في نفس الوقت تقريبًا (تم نشر SplitMix في 20 أكتوبر 2014 ، بينما تم نشر pcg-random.org في أغسطس 2014 وتم ربطه بورقة PCG في 5 سبتمبر 2014 ). هناك بعض أوجه التشابه بين PCG و SplitMix (والعديد من PRNGs الأخرى ، بما في ذلك Vigna xor shift * و xorshift + - تم إصدارهما أيضًا للعالم في 2014). تحتوي جميعها على وظائف انتقال حالة بسيطة إلى حد ما ليست جيدة بدرجة كافية يتم إصلاحها بواسطة وظيفة إخراج التخليط. عندما كنت أكتب ورقة PCG ، كان أحد الأشياء التي كنت أعلم أن بعض الأشخاص سيرغبون فيها هو وظيفة split() لكن لم أستطع إيجاد طريقة جيدة للقيام بذلك ؛ بدلاً من ذلك ، طورت دليلًا سريعًا على أنه إذا كان لديك PRNG _k_ بت حيث يمكنك الذهاب إلى اليسار أو اليمين في كل خطوة ، في غضون _k_ خطوات ، يجب أن تكون قادرًا على الوصول إلى الحالة التي كنت فيها من قبل ، وبالتالي إثبات المفهوم بأكمله كان سيئ التصميم. هذه الملاحظة لم تنشر في الورقة. ولكن كنتيجة لأفكاري التأملية قبل هذا الدليل ، في حاشية في مسودة شبه نهائية للورقة ، اقترحت ، بشكل غريب إلى حد ما ، لأن ناتج PCG كان عبارة عن تجزئة / تدافع / تبديل لحالته ، الشعور بالذنب يمكنك إعادة زرع المولد بإنتاجه الخاص والابتعاد عنه. لقد أخرجته من الإصدار النهائي لأنني اعتقدت أن مثل هذه النزوات ستكون كبيرة جدًا بالنسبة للمراجعين ، نظرًا لأن إعادة زرع PRNG بحالتها الخاصة كان يعتبر على نطاق واسع نوعًا من إساءة استخدام PRNG ، وهذا النوع من الأشياء التي نراها من أشخاص عديمي الخبرة في استخدامها.

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

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

من أجل المتعة ، إليك تفريغ مساحة الحالة لنسخة صغيرة من SplitMix تستكشف فقط ثلاث طرق مختلفة (وثابتة بشكل صارم) للجمع بين next() و split() :

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

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

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

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

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

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

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

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

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

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

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

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

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

إلخ

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

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

بدافع الفضول ، هل هناك أي طريقة (سهلة) لمعرفة مدى تباعد الدولتين في PCG64؟

نعم ، على الرغم من أننا لا نكشفها: http://www.pcg-random.org/useful-features.html#distance

بدافع الفضول ، هل هناك أي طريقة (سهلة) لمعرفة مدى تباعد الدولتين في PCG64؟

نعم ، على الرغم من أننا لا نكشفها: http://www.pcg-random.org/useful-features.html#distance

في مصدر C ++ ، ستخبرك وظيفة المسافة بالمسافة بين التدفقات ، مع إعطاء نقطة الاقتراب الأقرب (حيث يكون الاختلاف الوحيد بين التدفقات ثابتًا إضافيًا).

بالمناسبة ، بالنسبة لـ LCG الأساسي ، يمكننا استخدام المسافة لمعرفة مدى الترابط الذي نتوقع أن تكون عليه المواقف. من الواضح أن المسافة القصيرة سيئة (وهي سيئة لأي PRNG على الإطلاق) ، ولكن المسافة مع مجموعة بت واحد فقط ليست رائعة أيضًا ، وهذا هو السبب في القفز للأمام بمقدار 2 ^ 64 ( 0x10000000000000000 ) باستخدام .jumped فكرة سيئة. في قائمة مهام PCG الخاصة بي ، اكتب وظيفة " independence_score " التي تنظر إلى المسافة بين حالتين وتخبرك بمدى عشوائية المظهر (عبر طرق الوزن ، إلخ - من الناحية المثالية نريد حوالي نصف البِتات تكون أصفارًا وأنصاف آحاد وأن تكون متناثرة بحرية).

تتمثل إحدى طرق _keep_ jumped مع PCG64 في عدم القفز بمقدار n * 0x10000000000000000 ولكن بدلاً من ذلك القفز بمقدار n * 0x9e3779b97f4a7c150000000000000000 (يتم اقتطاعه إلى 128 بت). سيعطيك هذا جميع الخصائص المعتادة التي تريدها ( .jumped(3).jumped(5) == .jumped(8) ) دون أن تكون مرضيًا لـ LCG الأساسي.

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

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

أوصيك بوضعه في خلاط Murmur3 . لا يحتمل أن يقوم أي شخص عن طريق الخطأ بعمل تدفقات مماثلة مع ذلك دون جهد متعمد. (تحرير: أعتقد أنك بحاجة إلى إصدار 128 بت ، ولكن يمكنك فقط مزج النصفين العلوي والسفلي. وسأضيف أيضًا ثابتًا. الجميع يحب 0x9e3779b97f4a7c15f39cc0605cedc835 (جزء كسري من ϕ) ولكن 0xb7e151628aed2a6abf7158809cf4f3c7 (جزء كسري من e) سيكون جيدًا أيضًا ، أو _ أي رقم عشوائي المظهر.)

أوصي بـ wyhash (https://github.com/wangyi-fudan/wyhash) لأنه الأسرع والأبسط الذي اجتاز BigCrush و PractRand. كود c بسيط مثل

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

@ wangyi-fudan ، لا يمكنني إقناع نفسي بأن هذا انحراف.

آسف لمعرفتي المحدودة: لماذا يعتبر الانحراف ضروريًا / مفضلًا لـ PRNG؟
سيكون موضع تقدير لبعض التفسيرات :-)

@ wangyi-fudan ، إذا كانت دالة التجزئة من 64 بت ints إلى 64 بت ints ليست انحرافًا (أي دالة من 1 إلى 1) ، فسيتم إنشاء بعض النتائج أكثر من مرة والبعض الآخر ليس على الإطلاق. هذا نوع من التحيز.

أنا أفهم ماذا تقصد. ومع ذلك ، بالنسبة لمولد الأرقام العشوائية 64 بت ، نتوقع تصادمًا واحدًا بعد 1.2 * 2 ^ 32 رقمًا عشوائيًا (http://mathworld.wolfram.com/BirthdayAttack.html). مع 2 ^ 64 رقمًا عشوائيًا ، من الطبيعي حدوث العديد من التصادمات. التصادمات طبيعية في حين أن الانحراف ليس عشوائيًا بشكل طبيعي. إذا علمت أن جدول المقامرة (على سبيل المثال ، 3 بت PRNG) قد تم تحديده بقيمة 0 في 8 مسارات ، فسأجرؤ على إجراء رهان كبير على الصفر بعد ملاحظة 5 غير صفرية.

@ wangyi-fudan ، في هذا السياق ، كنا نتحدث عن طرق لتبديل معرف الدفق بحيث تصبح التدفقات مثل 1،2،3 شيئًا أكثر عشوائية (ويعرف أيضًا باسم أكثر طبيعية). لا توجد فضيلة في الاصطدامات في هذه العملية.

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

يمكننا حساب احتمال أن يتداخل أحدهما مع الآخر إذا طلبنا فترات _n_. إنه احتمال أساسي إلى حد ما - لست متأكدًا من أنه يمكنك نشر ورقة حول هذا الموضوع لأنه (كما أفهمها) لا أحد متحمس أبدًا بشأن الأوراق التي تحتوي على رياضيات أولية.

أعتقد أنه عليك فقط أن تكون بيير ليكوييه. ؛-) الصفحة 15

نعم ، عندما يشرح الأساسيات يعتبر ذلك جيدًا!

rkernimneme البساطة هي ميزة، سواء في مجال البرمجيات وفي الرياضيات. إن عدم إعجاب البعض بالعمل البسيط لا ينبغي أن يؤخذ على أنه دليل متناقض.

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

الافتراضي BitGenerator هو PCG64 . شكرا لكم جميعا على مساهماتكم المدروسة. والقدرة على التحمل!

مستوحاة جدًا من هذا الموضوع ، لدي بعض الأخبار التي أريد الإبلاغ عنها ...

خلفية

وفقًا للعديد من المقاييس ، فإن pcg64 جيد جدًا ؛ على سبيل المثال ، في ظل المقاييس المعتادة للجودة الإحصائية ، تحصل على شهادة صحية نظيفة. تم اختباره بطرق مختلفة. في الآونة الأخيرة ، قمت بتشغيله حتى نصف بيتابايت باستخدام PractRand. يعمل بشكل جيد في حالات الاستخدام العادي.

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

لذلك ، منذ حوالي 25 يومًا بدأت التفكير في تصميم عضو جديد في عائلة PCG ...

هدف

كان هدفي هو تصميم عضو جديد من عائلة PCG يمكن أن يكون بمثابة انخفاض في بديل للمتغير الحالي pcg64 . كما:

  • يجب أن تقوم وظيفة الإخراج بتشويش البتات أكثر من XSL RR (لأن القيام بذلك سيؤدي إلى تجنب المشكلات التي ظهرت في هذا الموضوع).
  • يجب أن يكون الأداء سريعًا (أو أسرع) من pcg64 .
  • يجب أن يكون التصميم PCG-ish (على سبيل المثال ، لا يمكن التنبؤ به بشكل تافه ، وبالتالي لا تسمح بسهولة التراجع عن أي عمل لوظيفة الإخراج).

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

المفسد

يسعدني الإبلاغ عن النجاح! منذ حوالي 25 يومًا عندما كنت أفكر في هذا الأمر لأول مرة ، كنت في الواقع في إجازة. عندما عدت قبل حوالي عشرة أيام ، جربت الأفكار التي كانت لدي وسعدت أن أجد أنها تعمل بشكل جيد. تم إنفاق الوقت التالي في الغالب على أنواع مختلفة من الاختبارات. بالأمس كنت راضيًا بدرجة كافية لدرجة أنني دفعت الرمز إلى إصدار C ++ من PCG. تشير الاختبارات ذات الأحجام الصغيرة إلى أنها أفضل بكثير من XSL RR ، ومنافسة مع RXS M ، لكنها في الواقع تتألق بأحجام أكبر. إنه يلبي جميع الأهداف الأخرى أيضًا.

تفاصيل

FWIW ، وظيفة الإخراج الجديدة (لحالة إخراج 64 بت):

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

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

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

تغييرات أخرى

كما انها حالة أن 0xda942042e4dd58b5 هو مضاعف LCG لهذا PRNG (وجميع cm_ مسبوقة مولدات PCG 128 بت للدولة). بالمقارنة مع 0x2360ed051fc65da44385df649fccf645 المستخدم بواسطة pcg64 ، فإن هذا الثابت لا يزال جيدًا إلى حد ما من حيث خصائص اختبار الطيف ، ولكنه أرخص للمضاعفة لأن 128 بت × 64 بت أسهل من 128 بت × 128 بت. لقد استخدمت ثابت LCG هذا لعدة سنوات دون مشكلة. عند استخدام متغير المضاعف الرخيص ، أقوم بتشغيل وظيفة الإخراج على الحالة المتكرّرة مسبقًا بدلاً من الحالة اللاحقة التكرارية من أجل توازٍ أكبر على مستوى التعليمات.

اختبارات

لقد اختبرت ذلك جيدًا (PractRand و TestU01) وأنا سعيد به. تضمنت الاختبارات السيناريوهات الموضحة في هذا الموضوع (على سبيل المثال ، أخذ مولدات العصابات إما على بخار متسلسل أو متقدم بمقدار 2 ^ 64 وتشذير مخرجاتها - لقد اختبرت عصابة من أربعة وعصابة من 8192 إلى 8 تيرابايت دون مشاكل ، كذلك كتيار ونظيره في الأرض).

سرعة

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

التوفر

يمكن لمستخدمي رأس C ++ الوصول إلى فرد العائلة الجديد هذا _now_ كـ pcg_engines::cm_setseq_dxsm_128_64 ؛ في مرحلة ما في المستقبل ، سأحول pcg64 من pcg_engines::setseq_xsl_rr_128_64 إلى هذا النظام الجديد. خطتي الحالية هي القيام بذلك هذا الصيف كجزء من نتوء إصدار PCG 2.0.

الإعلانات الرسمية

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

اختياراتك...

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

imneme هل

lemire :

لا يزال من المحتمل أن يكون أفضل من 128 بت × 128 بت. على الرغم من أن مدى أفضل يعتمد على مدى جودة جدولة التعليمات في تلك اللحظة.

أنت محق في أنه في ARM ، نتيجة 64 بت × 64 بت ← 128 بت هي في الواقع تعليمتين.

(من الممكن تمامًا ، بالطبع ، الجمع بين اثنين من LCGs 64 بت وخلطهما. مساحة كل PRNGs التي يمكن أن توجد وستعمل بشكل جيد كبيرة جدًا.)

يشير التنفيذ السريع والقذر في إطار العمل الخاص بنا إلى تحسن معتدل في الأداء ، على الأقل في نظام Linux 64 بت:

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

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

أعتقد أنه ناتج من حالة متكررة مسبقًا هي التي تعطيها النتوء ، على الأقل في هذا السياق. تركت ذلك في البداية وحصلت بشكل أساسي على نفس أداء PCG64 1.0. أعتقد أن الفوز الحقيقي سيكون تحت محاكاة 128 بت ، لكنني لم أتمكن من كتابة ذلك ، وليس لدي طريقة جيدة لاختباره على الأنظمة الأساسية المهمة.

أعتقد أن السؤال الحقيقي بالنسبة لك ، imneme ، ما مدى numpy.random.PCG64 تطبيق الخوارزمية 1.0؟ الإصدار وشيك ومتأخر بالفعل ، لذلك لا أعتقد أننا سنغير الخوارزمية في هذا الوقت. إذا كان الأداء على الأنظمة الأساسية 32 بت جيدًا بشكل خاص ، فأعتقد أننا قد نضيف PCG64DXSM في الإصدار التالي ، وربما نعيد النظر في الإصدار الافتراضي بضعة إصدارات لاحقًا.

إنه اختيارك!

ليس لدي مشكلة في شحن الإصدار 1.0 من PCG64. لقد استخدم الكثير من الأشخاص الآخرين هذا البديل.

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

(ومع ذلك ، إذا كان هذا هو خياري ، على الرغم من الاتهامات المحتملة بالتهور ، فمن المحتمل أن أشحن الجديد ؛ أعتقد أن التأخير في إعداده وتشغيله في Numpy ضئيل للغاية. والمخاطر منخفضة للغاية - إنها بالفعل تم الاختبار بالكامل باستخدام BigCrush ، وتم اختباره باستخدام PractRand حتى 16 تيرابايت (بما في ذلك cm_mcg_dxsm_64_32 وهو ربع الحجم [بدون تدفقات ، إخراج 32 بت]) ، ومن المحتمل أن يصل إلى 32 تيرابايت في أقل من أسبوع .)

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

قصدت المزيد حول استخدام الاسم PCG64 للمتغير 1.0 عندما تستخدم هذا الاسم للإشارة إلى المتغير 2.0.

rkern إذا كانت مجرد مشكلة تسمية ، فإن PCG64DXSM و PCG64 يميزانهما بشكل جيد ، أليس كذلك؟

ل numpy ، بالتأكيد. أنا فقط أتساءل عما إذا كانت imneme تفضل ألا PCG64 عندما تقوم بالترويج لمتغير 2.0 تحت هذا الاسم في إصدار C ++. أنا حساس لحقيقة أن التساهل مع الأسماء يعني أن بعض الأشخاص قد يختبرون Numpy's PCG64 ويقارنون ذلك بالمطالبات التي سيتم تقديمها على pcg-random.org حول الإصدار 2.0. راجع أي محادثة حول PRNGs لبوب جينكين.

في القسم 6.3 من ورقة PCG ، تقول:

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

ويتم تنظيم مكتبات C و C ++ بهذه الطريقة. تقدم المكتبات

  • واجهة منخفضة المستوى تتيح لك اختيار فرد معين من العائلة عبر اسم التبديل وأحجام البت التي تعمل بها وخصائص LCG الأساسي
  • واجهة عالية المستوى توفر أسماء مستعارة مناسبة مثل pcg64 التي تتصل بأحد أفراد الأسرة منخفض المستوى المختار مسبقًا.

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

إذا كنت ستشحن PRNG يسمى PCG64 ، فسأقول إنه يكفي أن أقول في وثائقك أي متغير PCG محدد - بمعنى آخر ، قل أي فرد من أفراد الأسرة يتوافق مع السعر المنخفض واجهة مكتبة ذات مستوى C أو C ++.

يتم تنفيذ المولد الافتراضي كـ np.random.default_gen() في https://github.com/numpy/numpy/pull/13840. ( rkern للرجوع إليه في المستقبل ، ربما يكون من الجيد استدعاء قدمت رابطًا خلفيًا فقط ، نظرًا لعدم وجود إشعارات لذلك).

قاصر واحد: ماذا عن استدعاء هذا np.random.default_generator() بدلاً من ذلك؟ gen قصير جدًا / غير واضح بالنسبة لي. سأكون فضوليًا لما يعتقده الآخرون.

ماذا عن استدعاء np.random.default_generator () بدلاً من ذلك؟

راودتني نفس الفكرة ، ولكن بعد ذلك ، np.random.default_generator() هو شعرة على الجانب الطويل ، لذلك لعبت بـ default_rng .

👍 أحب default_rng أفضل من default_gen أيضًا. سأكون سعيدًا بأي من هذين ، على الرغم من أنني ما زلت أتجه نحو default_generator .

: +1: مقابل default_rng() .

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