Я использовал функцию 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 тыс. Случайных чисел с помощью этой функции, вычисления их среднего значения, повторения 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.
При запуске кода с одним потоком результат приемлем:
Но вот результат с двумя потоками:
3 потока:
4 потока:
У меня сейчас нет 8-поточного процессора, но результаты того стоили.
Как видите, они оба неоднородны и сильно колеблются вокруг своего среднего значения.
Так является ли этот псевдослучайный генератор потокобезопасным?
Или я где-то ошибаюсь?
rand()
не должен быть потокобезопасным (ср. POSIXstdlib.h
) - person kvantour   schedule 15.05.2018