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, которая объясняет, почему она медленнее, чем серийная версия? Я предполагаю, что из-за небольшой рабочей нагрузки внутреннего цикла по сравнению со многими итерациями внешнего цикла.

0 ответов

Другие вопросы по тегам