openMP仅在内循环不起作用

时间:2016-06-03 19:48:51

标签: c openmp

这是我原始问题的更新,其中包含工作代码和运行时。

我有一个简单的代码,通过多个步骤与多个步行者进行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实现有什么问题可以解释为什么它比串行版本慢?我的猜测是因为与外循环的多次迭代相比,内循环的工作量很小。

0 个答案:

没有答案