Я новичок ie в OpenMP. Я пишу код для расчета значения Pi путем вычисления области функции f(x) = 4/(1+x^2)
. Я пытаюсь изучить эффективность с различными потоками. Ниже мой код:
int main() {
long long num_iteration = 100000000;
double pi = 0;
double x_margin = 1.0 / num_iteration;
double start_time, end_time;
int num_threads_main = 0;
int j = NUM_THREAD;
int a;
for(a = 1; a <= j; a++) {
pi = 0.0;
omp_set_num_threads(a);
start_time = omp_get_wtime();
#pragma omp parallel
{
int i;
int ID = omp_get_thread_num();
double sum = 0.0;
int num_threads_local = omp_get_num_threads();
double x_value = 0;
if(ID == 0)
num_threads_main = num_threads_local;
for (i = ID; i < num_iteration; i = i + num_threads_local) {
x_value = x_margin * ( i + 0.5 );
sum = sum + ( 4.0 / (1.0 + x_value * x_value));
}
#pragma critical
pi = pi + sum * x_margin;
}
end_time = omp_get_wtime() - start_time;
printf("pi with 1000000000 steps is %f in %f seconds with threads %d\n", pi, end_time, num_threads_main);
}
return 0;
}
Однако, когда я получил странный результат:
pi with 1000000000 steps is 3.141593 in 0.333257 seconds with threads 1
pi with 1000000000 steps is 3.141593 in 0.175574 seconds with threads 2
pi with 1000000000 steps is 3.141593 in 0.177884 seconds with threads 3
pi with 1000000000 steps is 3.141593 in 0.170591 seconds with threads 4
Почему моя программа не работает быстрее, когда есть больше потоков? Я знаю, что могут быть некоторые издержки для OpenMP. Однако я сравниваю свой код с кодом Тима Маттсона для учебника OpenMP. Я нахожу довольно сходство между ними. Ниже приведен его код:
static long num_steps = 100000000;
double step;
int main ()
{
int i,j;
double pi, full_sum = 0.0;
double start_time, run_time;
double sum[MAX_THREADS];
step = 1.0/(double) num_steps;
for(j=1;j<=MAX_THREADS ;j++){
omp_set_num_threads(j);
full_sum = 0.0;
start_time = omp_get_wtime();
#pragma omp parallel private(i)
{
int id = omp_get_thread_num();
int numthreads = omp_get_num_threads();
double x;
double partial_sum = 0;
#pragma omp single
printf(" num_threads = %d",numthreads);
for (i=id;i< num_steps; i+=numthreads){
x = (i+0.5)*step;
partial_sum += + 4.0/(1.0+x*x);
}
#pragma omp critical
full_sum += partial_sum;
}
pi = step * full_sum;
run_time = omp_get_wtime() - start_time;
printf("\n pi is %f in %f seconds %d threds \n ",pi,run_time,j);
}
}
И вот его результат:
num_threads = 1
pi is 3.141593 in 0.483153 seconds 1 threds
num_threads = 2
pi is 3.141593 in 0.305407 seconds 2 threds
num_threads = 3
pi is 3.141593 in 0.246802 seconds 3 threds
num_threads = 4
pi is 3.141593 in 0.204905 seconds 4 threds
Я выполняю эксперимент на моем MacOS 10.15.3 с двухъядерным процессором Intel Core i5 с частотой 2,3 ГГц. Я что-то пропустил. Спасибо.