这是我原始问题的更新,其中包含工作代码和运行时。
我有一个简单的代码,通过多个步骤与多个步行者进行2D随机游走。我试图仅在内循环上使用openMP将walker并行化为每个线程上的组。
这是代码。它输出步数与均方根位移(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
带OMP_NUM_THREADS=1
的OpenMP版本:
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
带OMP_NUM_THREADS=4
的OpenMP版本:
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
我不是C的专家,所以请随意扔石头,但是这个OpenMP实现有什么问题可以解释为什么它比串行版本慢?我的猜测是因为与外循环的多次迭代相比,内循环的工作量很小。