Потокобезопасный генератор случайных чисел - PullRequest
5 голосов
/ 02 марта 2009

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

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

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

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

Ответы [ 8 ]

6 голосов
/ 02 марта 2009

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

3 голосов
/ 02 марта 2009

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

2 голосов
/ 02 марта 2009

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

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

или

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

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


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

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

      function PRNGthread (state)

      double state(statesize)

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

      PRNGthread = result
      return 

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

1 голос
/ 06 марта 2010

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

См. http://code.google.com/p/i3rc-monte-carlo-model/source/browse/trunk/Code/RandomNumbersForMC.f95

1 голос
/ 02 марта 2009

Как насчет SPRNG ? Я сам не пробовал.

1 голос
/ 02 марта 2009

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

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

0 голосов
/ 18 февраля 2019

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

Версия Ziggurat для Fortran90 имеет несколько переменных и массивов с атрибутом 'SAVE'. Таким образом, для распараллеливания унифицированного ГСЧ необходимо, чтобы необходимые изменения сделали массивы этих переменных с отдельным значением для каждого потока (остерегайтесь ложного совместного использования). Затем, когда вызывается функция PRNG, мы должны передать номер потока и использовать соответствующее значение состояния.

0 голосов
/ 02 марта 2009

Альтернативы кажутся:

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

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

...