Забег вперед в параллельных PRNG в C++C++

Программы на C++. Форум разработчиков
Ответить
Anonymous
 Забег вперед в параллельных PRNG в C++

Сообщение Anonymous »

Я реализую симуляцию Монте-Карло, где мне нужно запустить несколько реализаций некоторой динамики, а затем взять среднее значение конечного состояния для всех симуляций. Поскольку количество реализаций велико, я запускаю их параллельно, используя OpenMP. Каждая реализация начинается с одних и тех же начальных условий, а затем на каждом временном шаге происходит процесс с заданной вероятностью, и чтобы определить, какой процесс я беру случайное число из равномерного распределения.
Я хочу чтобы убедиться, что все симуляции статистически независимы и что рисуемые случайные числа не перекрываются.
Я использую OpenMP для распараллеливания циклов for, поэтому скелетный код выглядит следующим образом: это:

Код: Выделить всё

vector data(number_of_sims);
double t;
double r;
#pragma omp parallel for
for(int i = 0; i < number_of_sims; i++){

// run sim
t = 0;
while (t < T) {
r = draw_random_uniform();
if (r < p) do_something();
else do_something_else();
t += 1.0;  // increment time
}

// some calculation
data[i] = calculate();
}

Поэтому каждый раз, когда мне нужно случайное число, я вызываю функцию, которая использует Твистер Мерсенна, засеянный случайным устройством.

Код: Выделить всё

double draw_random_uniform(){
static thread_local auto seed = std::random_device{}();
static thread_local mt19937 mt(seed);
std::uniform_real_distribution distribution(0.0, 1.0);
double r = distribution(mt);
return r;
}
Однако, поскольку в конечном итоге я хочу запустить этот код на высокопроизводительном вычислительном кластере, я хочу избежать использования std::random_device(), поскольку это рискованно для систем с небольшим количеством энтропия.
Поэтому вместо этого я хочу создать начальный генератор случайных чисел, а затем переместить его вперед на большую величину для каждого из потоков. Я пытался сделать это с помощью PRNG Xoroshiro256+ (здесь я нашел хорошую реализацию: https://github.com/Reputeless/Xoshiro-cpp). Например, что-то вроде этого:

Код: Выделить всё

XoshiroCpp::Xoshiro256Plus prng(42);  // properly seeded prng
#pragma omp parallel num_threads()
{
static thread_local XoshiroCpp::Xoshiro256Plus lprng(prng);  // thread local copy
lprng.longJump();  // jump ahead

// code as before, except use lprng to generate random numbers
# pragma omp for
....
}
Однако я не могу заставить такую ​​реализацию работать. Я подозреваю, что это из-за двойных циклов OpenMP for. У меня возникла мысль предварительно сгенерировать все PNRG и сохранить их в контейнере, а затем получить доступ к соответствующему с помощью omp_get_thread_num() внутри параллельного цикла for.
Я Я не уверен, что это лучший способ сделать все это. Любые советы приветствуются.

Подробнее здесь: https://stackoverflow.com/questions/752 ... prngs-in-c
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «C++»