openMP только на внутреннем цикле не работает
Это обновление к моему первоначальному вопросу с рабочим кодом и включенным временем выполнения.
У меня есть простой код, который выполняет двухмерную случайную прогулку с несколькими проходчиками за несколько шагов. Я пытаюсь распараллелить ходоков в группу в каждом потоке с openMP только во внутреннем цикле.
Вот код Он выводит номер шага против среднеквадратичного смещения (RMSD). График Step vs RMSD должен следовать степенному закону с индексом около 0.5 в качестве проверки результатов (что он и делает).
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>
int main(int argc,char **argv){
// define variables
int i,j;
double msd,xij,yij,randm;
// inputs
// ----------------------
// set size
int walkers = 2000;
int steps = 50000;
// ----------------------
// allocate arrays
double *xpos = malloc(walkers*sizeof(double));
double *ypos = malloc(walkers*sizeof(double));
double *thet = malloc(walkers*steps*sizeof(double));
int *step = malloc(steps*sizeof(int));
double *rmsd = malloc(steps*sizeof(double));
// initialize
double dr = 0.2;
double pi = 4.0*atan(1.0);
for(i=0; i<walkers; i++){
xpos[i] = 0.0;
ypos[i] = 0.0;
}
// generate random angles
srand(time(NULL));
for(i=0; i<steps; i++){
for(j=0; j<walkers; j++){
randm = rand();
randm = (randm/RAND_MAX)*2.0*pi;
thet[i*walkers+j] = randm;
}
}
// random walk
#pragma omp parallel private(i,j,xij,yij)
for(i=0; i<steps; i++){
msd = 0.0;
#pragma omp barrier
#pragma omp for reduction(+:msd)
for(j=0; j<walkers; j++){
xpos[j] += dr*cos(thet[i*walkers+j]);
ypos[j] += dr*sin(thet[i*walkers+j]);
xij = xpos[j];
yij = ypos[j];
// get displacement
msd += xij*xij + yij*yij;
}
// store values to array
#pragma omp single
step[i] = i+1;
#pragma omp single
rmsd[i] = sqrt(msd/walkers);
}
// write output to file
FILE *f = fopen("random_walk_c_omp.txt","w");
for(i=0; i<steps; i++){
fprintf(f,"%i %f\n",step[i],rmsd[i]);
}
fclose(f);
// free arrays
free(xpos);
free(ypos);
free(thet);
free(step);
free(rmsd);
}
Вот время выполнения.
Серийная версия, скомпилированная без OpenMP:
gcc-5 random_walk_c_omp.c -o random_walk_c_omp -O3 -Wall
time ./random_walk_c_omp
2.55 real 2.36 user 0.18 sys
OpenMP версия с OMP_NUM_THREADS=1
:
gcc-5 random_walk_c_omp.c -o random_walk_c_omp -O3 -Wall -fopenmp
time ./random_walk_c_omp
2.81 real 2.62 user 0.17 sys
OpenMP версия с OMP_NUM_THREADS=4
:
gcc-5 random_walk_c_omp.c -o random_walk_c_omp -O3 -Wall -fopenmp
time ./random_walk_c_omp
4.36 real 3.42 user 3.80 sys
Я не специалист по Си, поэтому не стесняйтесь бросать камни сюда, но есть ли что-то не так с этой реализацией OpenMP, которая объясняет, почему она медленнее, чем серийная версия? Я предполагаю, что из-за небольшой рабочей нагрузки внутреннего цикла по сравнению со многими итерациями внешнего цикла.