Який із двигунів випадкових чисел <випадкових> насправді слід використовувати на практиці? std :: mt19937?


21

Припустимо, ви хочете використовувати засоби C ++ <random>у практичній програмі (для деякого визначення поняття "практичний" - обмеження тут є частиною цього питання). У вас приблизно такий код:

int main(int argc, char **argv) {
    int seed = get_user_provided_seed_value(argc, argv);
    if (seed == 0) seed = std::random_device()();
    ENGINE g(seed);  // TODO: proper seeding?
    go_on_and_use(g);
}

Моє запитання, який тип слід використовувати ENGINE?

  • Я завжди говорив, std::mt19937тому що це було швидко вводити і розпізнавати імена. Але в наші дні здається, що всі говорять про те, що Mersenne Twister дуже важка і не кеш-пам'ять і навіть не здає всіх статистичних тестів, які роблять інші.

  • Я хотів би сказати, std::default_random_engineтому що це очевидний "дефолт". Але я не знаю, чи варіюється вона від платформи до платформи, і я не знаю, чи є це статистично корисним.

  • Оскільки в наші дні всі працюють на 64-бітній платформі, чи варто нам принаймні використовувати std::mt19937_64більше std::mt19937?

  • Я хотів би сказати pcg64або xoroshiro128тому, що вони здаються шанованими і легкими, але їх взагалі немає <random>.

  • Я нічого не знаю minstd_rand, minstd_rand0, ranlux24, knuth_bзвичайно , вони повинні бути добре для чого - то - і т.д.?

Очевидно, що тут є деякі конкуруючі обмеження.

  • Міцність двигуна. ( <random>не має криптографічно сильних PRNG, але все ж деякі стандартизовані "слабкіші", ніж інші, правда?)

  • sizeof двигун.

  • Швидкість його operator().

  • Простота висіву насіння. mt19937сумно важко висівати належним чином, оскільки у нього стільки стану для ініціалізації.

  • Переносимість між постачальниками бібліотек. Якщо один постачальник foo_engineвиробляє різні номери від інших постачальників foo_engine, це не добре для деяких програм. (Сподіваємось, це не виключає нічого, крім можливо default_random_engine.)

Зваживши всі ці обмеження якнайкраще, що ви скажете, це остаточна відповідь "найкраща практика перебування в межах стандартної бібліотеки"? Чи варто просто продовжувати використовувати std::mt19937, чи що?


2
До останнього моменту всі стандартні адаптери двигуна задані для повернення певного значення на певному послідовному виклику сконструйованого за замовчуванням, тому вони повинні бути портативними.
1201ProgramAlarm

Відповіді:


15

Довідник C ++ перераховує всі випадкові двигуни, що надаються C ++. Однак вибір двигунів залишає бажати кращого (наприклад, дивіться мій список високоякісних випадкових генераторів ). Наприклад:

  • default_random_engine визначено реалізацією, тому невідомо, чи має двигун статистичні вади, які можуть турбувати додаток.
  • linear_congruential_engineреалізує лінійні конгрурентні генератори. Однак вони, як правило, мають низьку якість, якщо модуль не є простим і дуже великим (принаймні 64 біт). Крім того, вони не можуть допустити більше насіння, ніж їх модуль.
  • minstd_rand0і minstd_randвизнайте лише близько 2 ^ 31 насіння. knuth_bзагортає minstd_rand0та робить переміщення Байса-Дарема.
  • mt19937і mt19937_64можна було б визначити набагато більше насіння, якби вони були краще ініціалізовані (наприклад, шляхом ініціалізації std::seed_seqз декількома результатами random_device, не лише одним), але вони використовують близько 2500 байт стану.
  • ranlux24і ranlux48використовувати близько 577 бітів стану, але вони повільні (вони працюють, зберігаючи одні і відкидаючи інші псевдовипадкові виходи).

Однак у C ++ також є два двигуни, які обертають інший двигун, щоб потенційно поліпшити його властивості випадковості:

  • discard_block_engine відкидає деякі виходи даного випадкового двигуна.
  • shuffle_order_engine реалізує перемикання Бейса – Дарема заданого випадкового двигуна.

Наприклад, можна, наприклад, мати Відсіки-Durham перетасування mt19937, ranlux24або звичаю linear_congruential_engineз shuffle_order_engine. Можливо, обмотаний двигун кращої якості, ніж оригінальний. Однак важко передбачити статистичну якість нового двигуна, не перевіряючи його .

Таким чином, в очікуванні таких тестів, здається, mt19937це найбільш практичний двигун у стандарті C ++ на даний момент. Однак мені відомо, щонайменше, одна пропозиція додати ще один двигун випадкових чисел до майбутніх версій C ++ (див. Папір C ++ P2075 ).


1

За посиланням C ++ , default_random_engine:

Чи вибраний генератором бібліотеки генератор, який забезпечує принаймні прийнятну поведінку двигуна для відносно випадкового, недосвідченого та / або легкого використання.

Таким чином , для легкого використання ви не повинні турбуватися про що - небудь, насіння default_random_engineз , Epoch Time (time(0))і що було б добре досить;)


Я вважаю, що питання тут полягає в мобільності. Хоча за замовчуванням може бути двигун, який працює добре, він може не відтворюватися на іншій платформі.
bremen_matt

@bremen_matt Хм ... Ну, навіщо нам відтворювати "випадкове" число?
Фарбод Ахмадян

2
Тестування. Для тестування потрібні відтворювані входи. У той же час ви можете хотіти або потребувати цих даних, щоб вони були випадковими. Наприклад, більшість алгоритмів машинного навчання передбачають, що параметри ініціалізуються випадковим чином. Ransac, CNN, DNN, ... багато алгоритмів вимагають випадкових параметрів.
bremen_matt
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.