drand48 не безопасен в потоках?
ОС Linux x64. Код:
Код:
/* compile: cc omp-pi.c -o omp-pi -lm -fopenmp */
#include <stdlib.h>
#include <stdio.h>
#include <omp.h>
#include <math.h>
typedef unsigned long int large;
double getPi(large ndots){
large i = 0;
large goals = 0;
#pragma omp parallel private(i)
#pragma omp for
for(i = 0; i < ndots; i++)
#pragma omp critical
{
if(pow(drand48(), 2.0) + pow(drand48(), 2.0) <= 1)
goals++;
}
printf("%li goalsn", goals);
return (double)((4.0 * goals) / ndots);
}
int main(int argc, char* argv[]){
large throws = 1000000000;
double start = omp_get_wtime();
printf("%.10fn", getPi(throws));
printf("%.4f secn", omp_get_wtime() - start);
return 0;
}
#include <stdlib.h>
#include <stdio.h>
#include <omp.h>
#include <math.h>
typedef unsigned long int large;
double getPi(large ndots){
large i = 0;
large goals = 0;
#pragma omp parallel private(i)
#pragma omp for
for(i = 0; i < ndots; i++)
#pragma omp critical
{
if(pow(drand48(), 2.0) + pow(drand48(), 2.0) <= 1)
goals++;
}
printf("%li goalsn", goals);
return (double)((4.0 * goals) / ndots);
}
int main(int argc, char* argv[]){
large throws = 1000000000;
double start = omp_get_wtime();
printf("%.10fn", getPi(throws));
printf("%.4f secn", omp_get_wtime() - start);
return 0;
}
Код:
#pragma omp critical
{
if(pow(drand48(), 2.0) + pow(drand48(), 2.0) <= 1)
goals++;
}
{
if(pow(drand48(), 2.0) + pow(drand48(), 2.0) <= 1)
goals++;
}
Коротко на тему синхронизации: не безопасен ибо это не (_r) ф-ция, а значит использует переменные общего на весь процесс состояния, доступ к которым никто не обязан синхронизировать.
Развернуто: с drand48, erand48_r и __drand48_iterate. Никаких намеков на синхронизацию мы там не наблюдаем, не так ли?
PS: Никогда не читайте мокрые фантазиии странных авторов, смотрите первоисточники.
PPS: Совсем по хорошему у каждого потока должно быть своё состояние для генератора, можно использовать drand48_r + srand48_r/seed48_r, однако портабельным сей код не будет.