Я должен выполнить Монте-Карло моделирования параллельно на различных машинах. Код находится в C++, но программа настраивается и запускается со сценарием Python, которые устанавливают много вещей, в особенности случайное семя. Функция setseed thake 4-байтовое целое число без знака
Используя простое
import time
setseed(int(time.time()))
не очень хорошо, потому что я отправляю задания очереди на кластере, они остаются ожидать в течение нескольких минут затем, они запускают, но время начала является impredicible, может случиться так, что два задания запускаются одновременно (секунды), таким образом, я переключаюсь на:
setseet(int(time.time()*100))
но я не счастлив. Каково лучшее решение? Возможно, я могу объединить информацию от: время, идентификатор машины, обрабатывает идентификатор. Или возможно лучшее решение состоит в том, чтобы читать из/dev/random (машины Linux)?
Как считать 4 байта из/dev/random?
f = open("/dev/random","rb")
f.read(4)
дайте мне строку, я хочу целое число!
Чтение из /dev/random
- хорошая идея. Просто преобразуйте 4-байтовую строку в Integer:
f = open("/dev/random","rb")
rnd_str = f.read(4)
Либо используя struct:
import struct
rand_int = struct.unpack('I', rnd_string)[0]
Update Необходим верхний регистр I.
Или умножить и сложить:
rand_int = 0
for c in rnd_str:
rand_int <<= 8
rand_int += ord(c)
Вы можете просто скопировать четыре байта в целое число, и это будет наименьшим из ваших беспокойств.
Но параллельная генерация псевдослучайных чисел - довольно сложная тема, и очень часто она выполняется не очень хорошо. Обычно вы генерируете семена на одной машине и распределяете их по другим.
Взгляните на SPRNG, который решает именно вашу проблему.
Если это Linux или аналогичная ОС, вам нужна / dev / urandom
- данные всегда выдаются немедленно.
/ dev / random
может зависнуть, ожидая, пока система соберет случайность. Он действительно производит случайные числа криптографического уровня, но для вашей проблемы это перебор.
В качестве семени можно использовать случайное число, преимущество которого в том, что оно не зависит от операционной системы (не нужен /dev/random) и не требует преобразования строки в int:
Почему бы просто не использовать
random.randrange(-2**31, 2**31)
в качестве семени каждого процесса? Немного разное время запуска даст дико разные семена, таким образом...
Можно также альтернативно использовать метод random.jumpahead
, если вы примерно знаете, сколько случайных чисел будет использовано каждым процессом (полезная документация по random.WichmannHill.jumpahead
).