Я использовал функцию rand()
для генерации псевдослучайных чисел между 0,1 для целей моделирования, но когда я решил запустить мой код C ++ параллельно (через OpenMP), я заметил, что rand()
не является потоком-безопасен и тоже не очень равномерный.
Поэтому я перешел к использованию (так называемого) более равномерного генератора, представленного во многих ответах на другие вопросы.Это выглядит так:
double rnd(const double & min, const double & max) {
static thread_local mt19937* generator = nullptr;
if (!generator) generator = new mt19937(clock() + omp_get_thread_num());
uniform_real_distribution<double> distribution(min, max);
return fabs(distribution(*generator));
}
Но я видел много научных ошибок в моей исходной задаче, которую я моделировал.Проблемы, которые были связаны как с результатами rand()
, так и со здравым смыслом.
Поэтому я написал код для генерации 500 000 случайных чисел с помощью этой функции, вычисления их среднего значения и повторения этого 200 раз, и построения результатов.
double SUM=0;
for(r=0; r<=10; r+=0.05){
#pragma omp parallel for ordered schedule(static)
for(w=1; w<=500000; w++){
double a;
a=rnd(0,1);
SUM=SUM+a;
}
SUM=SUM/w_max;
ft<<r<<'\t'<<SUM<<'\n';
SUM=0;
}
Мы знаем, что если бы вместо 500k я мог делать это бесконечное время, это должна быть простая строка со значением 0,5.Но с 500k у нас будут колебания около 0,5.
При запуске кода с одним потоком, результат приемлем:
Но вот результат с 2 потоками:
3 потока:
4 потока:
У меня сейчас нет 8-поточного процессора, но результаты даже стоили того.
Как вы можете видеть, они оба неоднородны и сильно колеблются вокруг своего среднего значения.
Так что этот псевдослучайный генератор также небезопасен?
Или я ошибаюсь?где-нибудь?