Потокобезопасный генератор однородных случайных чисел

StackOverflow https://stackoverflow.com/questions/602311

  •  03-07-2019
  •  | 
  •  

Вопрос

У меня есть некоторый параллельный код Fortran90, в котором каждый поток должен генерировать одну и ту же последовательность случайных чисел.

У меня есть генератор случайных чисел, который кажется потокобезопасным, поскольку для данного начального значения я совершенно не могу повторять одни и те же результаты при каждом запуске программы.

Я безуспешно прошелся (почти) по всему Интернету в поисках какого-нибудь кода потокобезопасного RNG.Может ли кто-нибудь предоставить мне (ссылку на) код одного из них?

Заранее спасибо!

Это было полезно?

Решение

Хороший Генератор псевдослучайных чисел для Fortran90 можно найти в Векторная статистическая библиотека Математического ядра Intel.Они потокобезопасны.Кроме того, почему он должен быть потокобезопасным?Если вы хотите, чтобы каждый поток получал один и тот же список, создайте экземпляр нового PRNG для каждого потока с тем же начальным значением.

Другие советы

Большинству повторяемых генераторов случайных чисел требуется состояние в той или иной форме.Без государства они не смогут сделать то, что будет дальше.Чтобы быть потокобезопасным, вам нужен способ самостоятельно сохранять состояние (т. Е. оно не может быть глобальным).

Когда вы говорите "необходимо сгенерировать одну и ту же последовательность случайных чисел", вы имеете в виду, что

  • Каждый поток должен генерировать поток чисел, идентичный другому потоку? Это подразумевает выбор начального значения перед удалением потоков, а затем создание экземпляра локального PRNG для потока в каждом потоке с тем же начальным значением.

или

  • Вы хотите иметь возможность повторять одну и ту же последовательность чисел между различными запусками программ, но каждый поток генерирует свою собственную независимую последовательность? В этом случае вы по-прежнему не можете совместно использовать один PRNG, поскольку последовательность операций потока недетерминирована.Таким образом, перед запуском потоков создайте один PRNG с известным начальным значением и используйте его для генерации начальных начальных значений для потоков. Тогда вы создаете экземпляры локальных генераторов потоков в каждом потоке...

В каждом из этих случаев вы должны отметить, что Нил Баттеруорт расскажите о статистике:большинство обычных гарантий, на которые хотел бы претендовать PRNG, следующие ненадежный при смешивании потоки генерируются таким образом.


В обоих случаях вам нужен локальный PRNG потока.Я не знаю, что доступно в f90...но вы также можете написать свой собственный (поиск Смерч Мерсенна, и напишите маршрут, который принимает сохраненное состояние в качестве параметра ...).

В fortran 77 это выглядело бы примерно так

      function PRNGthread (state)

      double state(statesize)

c stuff happens here which uses and manipulates the state vector...

      PRNGthread = result
      return 

и каждый из ваших потоков должен поддерживать отдельный вектор состояния, хотя все они будут использовать одно и то же начальное значение.

Я понимаю, вам нужно, чтобы каждый поток создавал один и тот же поток случайных чисел.

Очень хорошим псевдослучайным генератором, который генерирует воспроизводимый поток чисел и работает довольно быстро, является MT19937.Просто убедитесь, что вы сгенерировали начальное значение перед запуском потоков, но сгенерируйте отдельный экземпляр MT в каждом потоке (сделайте экземпляр потока MT локальным).Таким образом, будет гарантировано, что каждый MT будет выдавать один и тот же поток чисел.

Как насчет ПРУЖИНЯЩИЙ?Хотя сам я этого не пробовал.

Я закодировал потокобезопасную версию Mersenne Twister / MT19973 на Fortran 90.Состояние PRNG сохраняется в производном типе (randomNumberSequence), и вы используете процедуры для заполнения генератора или получения следующего элемента в последовательности.

Видишь http://code.google.com/p/i3rc-monte-carlo-model/source/browse/trunk/Code/RandomNumbersForMC.f95

Альтернативы, по-видимому, следующие:

  • Используйте объект синхронизации (например, мьютекс) в начальном значении генератора.К сожалению, это приведет к сериализации вашего кода при доступе к generator
  • Используйте локальное хранилище потоков в генераторе, чтобы каждый поток получал свое собственное начальное значение - это может вызвать статические проблемы для вашего приложения
  • Если ваша платформа поддерживает подходящую атомарную операцию, используйте ее в исходном коде (однако, вероятно, этого не произойдет)

Не очень обнадеживающий список, я знаю.И вдобавок ко всему, я понятия не имею, как реализовать любой из них в FORTRAN!

Эта статья https://www.cmiss.org/openCMISS/wiki/RandomNumberGenerationWithOpenMP не только ссылается на реализацию Fortran, но и упоминает ключевые моменты, необходимые для того, чтобы сделать PRNG пригодным для использования с потоками.Самым важным моментом является:

Версия Ziggurat для Fortran90 содержит несколько переменных и массивов с атрибутом "СОХРАНИТЬ".Таким образом, для распараллеливания унифицированного RNG, похоже, требуются изменения, чтобы сделать эти переменные массивами с отдельным значением для каждого потока (остерегайтесь ложного совместного использования).Затем, когда вызывается функция PRNG, мы должны передать номер потока и использовать соответствующее значение состояния.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top