Проблема
Я намерен написать приложение С++ 11 для Linux, которое выполняет некоторое численное моделирование (а не криптографию) на основе примерно одного миллиона псевдослучайных 32-битных чисел. Чтобы ускорить работу, я хотел бы выполнить симуляцию в параллельных потоках, используя все ядра настольного процессора. Я бы хотел использовать Mersenne Twister mt19937
, предоставленный boost, как PRNG, и я предполагаю, что по соображениям производительности у меня должен быть такой PRNG на поток. Теперь я не уверен, как их семени, чтобы не генерировать одну и ту же последовательность случайных чисел в нескольких потоках.
Альтернативы
Вот альтернативы, о которых я думал до сих пор:
-
Разделите PRNG для каждого потока независимо от
/dev/urandom
.Меня немного беспокоит случай, когда системный энтропийный пул исчерпан, так как я не знаю, как работает внутренний PRNG системы. Может случиться так, что я случайно получаю последовательные семена, которые точно определяют последовательные состояния Мерсэнн Твистер, из-за того, что
/dev/urandom
использует сам Мерсенн Твистер? Вероятно, сильно связан с моими проблемами для следующего пункта. -
Поместите один PRNG из
/dev/urandom
, а остальные - из первого.В основном такая же проблема: хорошо или плохо использовать один PRNG для посева другого, который использует тот же алгоритм? Или, другими словами, читает ли 625 32-битных целых чисел от
mt19937
непосредственно внутреннее состояние генератораmt19937
в любой точке этого поколения? -
Выделите других людей сначала с информацией, не относящейся к Мерсенне.
Поскольку использование одного и того же алгоритма для генерации случайных чисел и генерации начального семени так или иначе похоже на то, что это может быть плохой идеей, я подумал о введении некоторого элемента, который не зависит от алгоритма Мерсенна Твистера. Например, я мог бы XOR идентификатор потока в каждый элемент исходного вектора семени. Это улучшает ситуацию?
-
Поделитесь одним PRNG между потоками.
Это гарантирует, что существует только одна последовательность, со всеми известными и желательными свойствами Mersenne Twister. Но накладные расходы на блокировку, необходимые для контроля доступа к этому генератору, меня несколько волнуют. Поскольку я не нашел никаких доказательств обратного, я предполагаю, что я как пользователь библиотеки будет нести ответственность за предотвращение одновременного доступа к PRNG.
-
Предварительно сгенерируйте все случайные числа.
Это будет иметь один поток, который генерирует все необходимые 1M случайные числа спереди, которые будут использоваться разными потоками позже. Требование к памяти 4M было бы небольшим по сравнению с объемом всего приложения. Меня больше всего беспокоит такой подход: генерация самих случайных чисел не является параллельной. Весь этот подход также не слишком хорошо масштабируется.
Вопросы
Какой из этих подходов вы бы предложили и почему? Или у вас есть другое предложение?
Знаете ли вы, какие из моих проблем оправданы и которые просто объясняются моим отсутствием понимания того, как все работает?