Mersenne Twister был разработан специально для исправления большинства недостатков, обнаруженных в старых ГПСЧ.
Наиболее часто используемая версия алгоритма Mersenne Twister основана на простом числе Мерсенна . Стандартная реализация этого, MT19937, использует длину слова 32 бита . Существует еще одна реализация (с пятью вариантами [3] ), в которой используется длина слова 64 бита, MT19937-64; он генерирует другую последовательность.
к-распределение
Псевдослучайная последовательность w - битных целых чисел периода P называется k-распределенной с точностью до v -бита, если выполняется следующее.
Пусть trunc v ( x ) обозначает число , образованное старшими v битами x , и рассмотрим P k v -битных векторов.
.
Тогда каждая из возможных комбинаций битов встречается одинаковое количество раз за период, за исключением комбинации, состоящей из всех нулей, которая встречается один раз реже.
Алгоритмическая деталь
Визуализация генерации псевдослучайных 32-битных целых чисел с использованием Mersenne Twister. В разделе «Извлечение числа» показан пример, где целое число 0 уже выведено, а индекс равен целому числу 1. «Создать числа» запускается, когда все целые числа были выведены.
Для длины слова w -бит Mersenne Twister генерирует целые числа в диапазоне .
Общий алгоритм характеризуется следующими величинами:
w : размер слова (в битах)
n : степень рецидива
m : среднее слово, смещение, используемое в рекуррентном отношении, определяющем серию ,
r : точка разделения одного слова или количество бит младшей битовой маски,
a : коэффициенты матрицы скручивания рациональной нормальной формы
b , c : Битовые маски смягчения TGFSR(R)
s , t : Сдвиг битов отпуска TGFSR(R)
u , d , l : дополнительные смены/маски закалочных долот Mersenne Twister
с ограничением, что это простое число Мерсенна. Этот выбор упрощает тест на примитивность и тест на k -распределение , которые необходимы при поиске параметров.
Серия определяется как серия w -битных величин с рекуррентным соотношением:
где обозначает конкатенацию битовых векторов (со старшими битами слева), побитовое исключающее ИЛИ (XOR), означает верхние биты w - r и означает младшие биты .
Все индексы могут быть смещены на -n.
где теперь LHS, , — это следующее сгенерированное значение в серии с точки зрения значений, сгенерированных в прошлом, которые находятся на RHS.
Твист-преобразование A определяется в рациональной нормальной форме как:
с как единичная матрица. Преимущество рациональной нормальной формы состоит в том, что умножение на A можно эффективно выразить как: (помните, что здесь умножение матрицы выполняется в , и поэтому вместо сложения используется побитовое исключающее ИЛИ) где – бит младшего порядка .
Как и в случае с TGFSR(R), «Твистер Мерсенна» каскадируется с умеренным преобразованием , чтобы компенсировать пониженную размерность равнораспределения (из-за того, что A находится в рациональной нормальной форме). Обратите внимание, что это эквивалентно использованию матрицы A , где для T является обратимая матрица, и поэтому анализ характеристического полинома, упомянутый ниже, все еще остается в силе.
Как и в случае с A , мы выбираем смягчающее преобразование так, чтобы оно было легко вычислимым, и поэтому фактически не конструируем T само по себе. В случае Mersenne Twister этот отпуск определяется как
где — следующее значение из серии, — временное промежуточное значение и — значение, возвращаемое алгоритмом, с и как побитовые сдвиги влево и вправо , а также как побитовое И. Первое и последнее преобразования добавлены для улучшения равнораспределения младших разрядов. Согласно свойству TGFSR, требуется достичь верхней границы равнораспределения для старших битов.
Коэффициенты для MT19937:
Обратите внимание, что 32-битные реализации Mersenne Twister обычно имеют d = FFFFFFFF 16 . В результате d иногда опускается в описании алгоритма, поскольку побитовое и с d в этом случае не имеет никакого эффекта.
Коэффициенты для MT19937-64: [5]
Инициализация
Состояние, необходимое для реализации Mersenne Twister, представляет собой массив из n значений по w бит каждое. Для инициализации массива используется w -битное начальное значение, которое передается путем установки начального значения и последующей установки
для от до .
Первое значение, которое затем генерирует алгоритм, основано на , а не на .
Константа f образует еще один параметр генератора, но не является частью самого алгоритма.
Значение f для MT19937 составляет 1812433253.
Значение f для MT19937-64 составляет 6364136223846793005. [5]
C-код
#include <stdint.h>#define n 624 #define m 397 #define w 32 #define r 31 #define UMASK (0xffffffffUL << r) #define LMASK (0xffffffffUL >> (wr)) #define a 0x9908b0dfUL #define u 11 #define s 7 #define t 15 #define l 18 #define b 0x9d2c5680UL #define c 0xefc60000UL #define f 1812433253ULtypedef struct { uint32_t state_array [ n ]; // массив вектора состояния int state_index ; // индекс в массиве векторов состояния, 0 <= state_index <= n-1 всегда } mt_state ;void Initialize_state ( mt_state * state , uint32_t семя ) { uint32_t * state_array = & ( state -> state_array [ 0 ]); state_array [ 0 ] = семя ; // предлагаемое начальное семя = 19650218UL for ( int i = 1 ; i < n ; i ++ ) { семя = f * ( семя ^ ( семя >> ( w -2 ))) + i ; // Кнут TAOCP Vol2. 3-е изд. P.106 для множителя. state_array [ я ] = семя ; } Состояние -> индекс_состояния = 0 ; }uint32_t random_uint32 ( mt_state * state ) { uint32_t * state_array = & ( state -> state_array [ 0 ]); int k = состояние -> индекс_состояния ; // указать местоположение текущего состояния // 0 <= state_index <= n-1 всегда // int k = k - n; // указать на состояние n итераций до // if (k < 0) k += n; // циклическое индексирование по модулю n // предыдущие 2 строки фактически ничего не делают // только для иллюстрации int j = k - ( n -1 ); // указать на состояние n-1 итераций до if ( j < 0 ) j += n ; // циклическое индексирование по модулю nuint32_t x = ( state_array [ k ] & UMASK ) | ( state_array [ j ] & LMASK ); uint32_t xA = x >> 1 ; если ( x & 0x00000001UL ) xA ^= a ; j знак равно k - ( п - м ); // указать на состояние nm итераций перед if ( j < 0 ) j += n ; // циклическое индексирование по модулю n x = state_array [ j ] ^ xA ; // вычисляем следующее значение в состоянии state_array [ k ++ ] = x ; // обновляем новое значение состояния if ( k >= n ) k = 0 ; // циклическое индексирование по модулю n state -> state_index = k ; uint32_t y = x ^ ( x >> u ); // закалка y = y ^ (( y << s ) & b ); y = y ^ (( y << t ) & c ); uint32_t z = y ^ ( y >> l ); вернуть г ; }
Сравнение с классической GFSR
Чтобы достичь теоретического верхнего предела периода в T GFSR , должен быть примитивный полином , являющийся характеристическим полиномом
Период достигает теоретического верхнего предела (за исключением случаев, когда инициализируется значением 0).
Равнораспределение в n измерениях (например, линейные конгруэнтные генераторы в лучшем случае могут обеспечить разумное распределение в пяти измерениях)
MTGP — это вариант Mersenne Twister, оптимизированный для графических процессоров, опубликованный Муцуо Сайто и Макото Мацумото. [8] Базовые операции линейной рекурсии расширены из MT, а параметры выбраны так, чтобы позволить множеству потоков вычислять рекурсию параллельно, одновременно разделяя свое пространство состояний для уменьшения нагрузки на память. В документе утверждается, что улучшенное равнораспределение по сравнению с MT и производительность на старом графическом процессоре (2008 года) ( Nvidia GTX260 со 192 ядрами) составила 4,7 мс для 5×10 7 случайных 32-битных целых чисел.
SFMT ( SIMD -ориентированный Fast Mersenne Twister) — это вариант Mersenne Twister, представленный в 2006 году [9] , предназначенный для быстрой работы при работе на 128-битном SIMD.
Он примерно в два раза быстрее Mersenne Twister. [10]
Он быстрее восстанавливается из начального состояния с нулевым превышением, чем MT, но медленнее, чем WELL.
Он поддерживает различные периоды от 2 607 - 1 до 2 216 091 - 1.
Intel SSE2 и PowerPC AltiVec поддерживаются SFMT. Он также используется для игр с Cell BE на PlayStation 3 . [11]
TinyMT — это вариант Mersenne Twister, предложенный Сайто и Мацумото в 2011 году. [12] TinyMT использует всего 127 бит пространства состояний, что значительно меньше по сравнению с исходными 2,5 КиБ состояния. Однако его период намного короче, чем у оригинала, поэтому авторы рекомендуют его только в тех случаях, когда память ограничена.
Проходит многочисленные тесты на статистическую случайность, включая тесты Дайхарда и большинство, но не все, тестов TestU01 . [13]
Очень длительный период . Обратите внимание, что длительный период не является гарантией качества генератора случайных чисел. Короткие периоды, например, используемые во многих старых программных пакетах, могут быть проблематичными. [14]
k-распределено с точностью до 32 бит для каждого (определение k -распределено см. ниже)
Реализации обычно создают случайные числа быстрее, чем аппаратно реализованные методы. Исследование показало, что Mersenne Twister создает 64-битные случайные числа с плавающей запятой примерно в двадцать раз быстрее, чем аппаратно реализованный процессорный набор инструкций RDRAND . [15]
Недостатки:
Относительно большой буфер состояния, почти 2,5 КБ , если не используется вариант TinyMT.
Посредственная пропускная способность по современным стандартам, если не используется вариант SFMT (обсуждаемый ниже). [16]
Демонстрирует две явные ошибки (линейная сложность) в Crush и BigCrush в пакете TestU01. Тест, как и «Твистер Мерсенна», основан на -алгебре . [13]
Множественные экземпляры, которые отличаются только начальным значением (но не другими параметрами), обычно не подходят для моделирования Монте-Карло , требующего независимых генераторов случайных чисел, хотя существует метод выбора нескольких наборов значений параметров. [17] [18]
Плохая диффузия: может потребоваться много времени, чтобы начать генерировать выходные данные, которые проходят тесты на случайность , если начальное состояние сильно неслучайно, особенно если начальное состояние имеет много нулей. Следствием этого является то, что два экземпляра генератора, запущенные с почти одинаковыми начальными состояниями, обычно выдают почти одну и ту же последовательность в течение многих итераций, прежде чем в конечном итоге разойдутся. Обновление алгоритма MT от 2002 года улучшило инициализацию, поэтому начало с такого состояния маловероятно. [19] Говорят, что версия с графическим процессором (MTGP) еще лучше. [20]
Содержит подпоследовательности, в которых нулей больше, чем единиц. Это добавляет к плохому свойству диффузии, что затрудняет восстановление из состояний со многими нулями.
Не является криптографически безопасным , если не используется вариант CryptMT (обсуждаемый ниже). Причина в том, что соблюдение достаточного количества итераций (624 в случае MT19937, поскольку это размер вектора состояния, из которого производятся будущие итерации) позволяет предсказать все будущие итерации.
Приложения
Mersenne Twister используется в качестве ГПСЧ по умолчанию в следующем программном обеспечении:
Языки программирования: Dyalog APL , [21] IDL , [22] R , [23] Ruby , [24] Free Pascal , [25] PHP , [26] Python (также доступен в NumPy , однако вместо этого значение по умолчанию было изменено на PCG64) . начиная с версии 1.17 [27] ), [28] [29] [30] CMU Common Lisp , [31] Embeddable Common Lisp , [32] Steel Bank Common Lisp , [33] Julia (до версии Julia 1.6 LTS, все еще доступна позже, но с версии 1.7 по умолчанию используется лучший/более быстрый ГСЧ) [34]
Mersenne Twister — один из двух ГПСЧ в SPSS : другой генератор сохранен только для совместимости со старыми программами, а Mersenne Twister считается «более надежным». [54] Mersenne Twister также является одним из PRNG в SAS : остальные генераторы устарели и устарели. [55] Mersenne Twister — это PRNG по умолчанию в Stata , другой — KISS , для совместимости со старыми версиями Stata. [56]
Альтернативы
Альтернативный генератор WELL («Well Equidistributed Long- period Linear») предлагает более быстрое восстановление, равную случайность и почти равную скорость. [57]
Генераторы xorshift и их варианты от Marsaglia являются самыми быстрыми в классе LFSR. [58]
64-битные MELG («64-битные максимально равнораспределенные линейные генераторы с простым периодом Мерсенна») полностью оптимизированы с точки зрения свойств k -распределения. [59]
Семейство ACORN (опубликовано в 1989 г.) — это еще один PRNG с k -распределением, который демонстрирует скорость вычислений, аналогичную MT, и лучшие статистические свойства, поскольку удовлетворяет всем текущим (2019 г.) критериям TestU01; при использовании с соответствующим выбором параметров ACORN может иметь сколь угодно большой период и точность.
Семейство PCG — это более современный генератор с большим периодом, с лучшей локальностью кэша и менее заметной предвзятостью с помощью современных методов анализа. [60]
^ Например, Марсланд С. (2011) Машинное обучение ( CRC Press ), §4.1.1. См. также раздел «Внедрение в программные системы».
^ Джон Савард. «Твистер Мерсенна». Последующая статья, опубликованная в 2000 году, представила пять дополнительных форм вихря Мерсенна с периодом 2^19937-1. Все пять были разработаны для реализации 64-битной арифметики вместо 32-битной.
^ Мацумото, М.; Курита, Ю. (1992). «Витые генераторы GFSR». ACM-транзакции по моделированию и компьютерному моделированию . 2 (3): 179–194. дои : 10.1145/146382.146383. S2CID 15246234.
^ ab "std::mersenne_twister_engine". Генерация псевдослучайных чисел . Проверено 20 июля 2015 г.
^ ab "CryptMt и Фубуки". ЭКРИПТ . Архивировано из оригинала 1 июля 2012 г. Проверено 12 ноября 2017 г.
^ Примечание: 2 19937 составляет примерно 4,3 × 10 6001 ; это на много порядков больше предполагаемого числа частиц в наблюдаемой Вселенной , которое составляет 10 87 .
↑ Маршрут, Мэтью (10 августа 2017 г.). «Синтез популяции ультрахолодных карликов с радиовспышкой». Астрофизический журнал . 845 (1): 66. arXiv : 1707.02212 . Бибкод : 2017ApJ...845...66R. дои : 10.3847/1538-4357/aa7ede . S2CID 118895524.
^ «Быстрый вихрь Мерсенна (SFMT), ориентированный на SIMD: в два раза быстрее, чем вихрь Мерсенна» . Японское общество содействия науке . Проверено 27 марта 2017 г.
^ Макото Мацумото; Такудзи Нишимура. «Динамическое создание генераторов псевдослучайных чисел» (PDF) . Проверено 19 июля 2015 г.
^ Хироши Харамото; Макото Мацумото; Такудзи Нисимура; Франсуа Паннетон; Пьер Л'Экуайер. «Эффективный скачок вперед для F2-линейных генераторов случайных чисел» (PDF) . Проверено 12 ноября 2015 г.
^ "mt19937ar: Mersenne Twister с улучшенной инициализацией" . Хиросима-u.ac.jp . Проверено 4 октября 2015 г.
↑ Туман, Агнер (1 мая 2015 г.). «Генератор псевдослучайных чисел для векторных и многоядерных процессоров». Журнал современных прикладных статистических методов . 14 (1): 308–334. дои : 10.22237/jmasm/1430454120 .
^ «Случайная ссылка». Справочное руководство по языку Dialog . Проверено 4 июня 2020 г.
^ «СЛУЧАЙНО (ссылка на IDL)» . Центр документации Exelis VIS . Проверено 23 августа 2013 г.
^ «Генератор случайных чисел». Представление задач CRAN: распределения вероятностей . Проверено 29 мая 2012 г.
^ "Документация класса "Случайный"" . Документация Ruby 1.9.3 . Проверено 29 мая 2012 г.
^ «случайный». бесплатная документация по Паскалю . Проверено 28 ноября 2013 г.
^ «mt_rand — Генерация лучшего случайного значения». Руководство по PHP . Проверено 2 марта 2016 г.
^ «Примечания к выпуску NumPy 1.17.0 — Руководство по NumPy v1.21» . numpy.org . Проверено 29 июня 2021 г.
^ «9.6 случайных чисел — генерация псевдослучайных чисел» . Документация Python v2.6.8 . Проверено 29 мая 2012 г.
^ «8.6 случайный — Генерация псевдослучайных чисел» . Документация Python v3.2 . Проверено 29 мая 2012 г.
^ «случайное — Генерация псевдослучайных чисел — Документация Python 3.8.3» . Документация Python 3.8.3 . Проверено 23 июня 2020 г.
^ «Выбор дизайна и расширения» . Руководство пользователя CMUCL . Проверено 3 февраля 2014 г.
^ «Случайные состояния». Руководство по ECL . Проверено 20 сентября 2015 г.
^ «Генерация случайных чисел». Руководство пользователя СБКЛ .
^ «Случайные числа · Язык Джулии» . docs.julialang.org . Проверено 21 июня 2022 г.
^ «Случайные числа: Справочное руководство GLib» .
^ «Алгоритмы случайных чисел». ГНУ МП . Проверено 21 ноября 2013 г.
^ «16.3 Специальные матрицы полезности» . GNU Октава . Встроенная функция: рандом
^ «Переменные среды случайных чисел» . Научная библиотека ГНУ . Проверено 24 ноября 2013 г.
^ Мелар, Г. (2014), «О точности статистических процедур в Microsoft Excel 2010», Вычислительная статистика , 29 (5): 1095–1128, CiteSeerX 10.1.1.455.5508 , doi : 10.1007/s00180-014-0482 -5, S2CID 54032450 .
^ «Справочник по языку GAUSS 14» (PDF) .
^ «Униформа». Справочник по функциям Gretl .
^ «Новый генератор случайных чисел — 64-битный Mersenne Twister».
^ «Распределение вероятностей — Справочное руководство Sage v7.2: Вероятность» .
^ "Гранд - Случайные числа" . Справка по Scilab .
^ «Генератор случайных чисел». Онлайн-справка Maple . Проверено 21 ноября 2013 г.
^ «Алгоритмы генератора случайных чисел» . Центр документации MathWorks .
^ «Генерация данных». Руководство пользователя Apache Commons Math .
^ «Генерация случайных чисел в C++11» (PDF) . Стандартная основа C++ .
^ "std::mersenne_twister_engine". Генерация псевдослучайных чисел . Проверено 25 сентября 2012 г.
^ [1] Документация Mathematica
^ "boost/random/mersenne_twister.hpp". Библиотеки Boost C++ . Проверено 29 мая 2012 г.
^ «Обзор API хоста» . Документация по набору инструментов CUDA . Проверено 2 августа 2016 г.
^ «G05 - Генераторы случайных чисел» . Введение в главу библиотеки NAG . Проверено 29 мая 2012 г.
^ «Генератор случайных чисел». Статистика IBM SPSS . Проверено 21 ноября 2013 г.
^ «Использование функций случайных чисел». Справочник по языку SAS . Проверено 21 ноября 2013 г.
^ Справка по Stata: set rng — укажите, какой генератор случайных чисел (ГСЧ) использовать.
^ «Генераторы xorshift*/xorshift+ и перестрелка PRNG» .
^ Харасе, С.; Кимото, Т. (2018). «Реализация 64-битных максимально равнораспределенных F2-линейных генераторов с простым периодом Мерсенна». Транзакции ACM в математическом программном обеспечении . 44 (3): 30:1–30:11. arXiv : 1505.06582 . дои : 10.1145/3159444. S2CID 14923086.
^ "Бумага PCG". 27 июля 2017 г.
дальнейшее чтение
Харасе, С. (2014), «О -линейных отношениях генераторов псевдослучайных чисел Мерсенна Твистера», Mathematics and Computers in Simulation , 100 : 103–113, arXiv : 1301.5435 , doi : 10.1016/j.matcom.2014.02.002, S2CID 6984431.
Харасе, С. (2019), «Преобразование Мерсенна Твистера в числа с плавающей запятой двойной точности», Mathematics and Computers in Simulation , 161 : 76–83, arXiv : 1708.06018 , doi : 10.1016/j.matcom.2018.08.006 , S2CID 19777310.
Внешние ссылки
Научная статья по MT и связанные с ней статьи Макото Мацумото.
Домашняя страница Mersenne Twister с кодами на C, Fortran, Java, Lisp и некоторых других языках.
Примеры Mersenne Twister — коллекция реализаций Mersenne Twister на нескольких языках программирования — на GitHub.
SFMT в действии: Часть I — Создание DLL, включая поддержку SSE2 — в Code Project