2010-10-28 2 views
2

У меня есть функция, которая передает две структуры по ссылке. Эти структуры состоят из динамически распределенных массивов. Теперь, когда я пытаюсь реализовать OpenMP, я получаю замедление, а не ускорение. Я думаю, что это можно объяснить возможными проблемами обмена. Вот некоторые из кода для прочтения (C):OpenMP и общие структуры и указатели

void leap(MHD *mhd,GRID *grid,short int gchk) 
{ 
    /*-- V A R I A B L E S --*/ 
    // Indexes 
    int i,j,k,tid; 
    double rhoinv[grid->nx][grid->ny][grid->nz]; 
    double rhoiinv[grid->nx][grid->ny][grid->nz]; 
    double rhoeinv[grid->nx][grid->ny][grid->nz]; 
    double rhoninv[grid->nx][grid->ny][grid->nz]; // Rho Inversion 
    #pragma omp parallel shared(mhd->rho,mhd->rhoi,mhd->rhoe,mhd->rhon,grid,rhoinv,rhoiinv,rhoeinv,rhoninv) \ 
         private(i,j,k,tid,stime) 
    { 
    tid=omp_get_thread_num(); 
    printf("----- Thread %d Checking in!\n",tid); 
    #pragma omp barrier 
    if (tid == 0) 
    { 
     stime=clock(); 
     printf("-----1) Calculating leap helpers"); 
    } 
    #pragma omp for 
    for(i=0;i<grid->nx;i++) 
    { 
     for(j=0;j<grid->ny;j++) 
     { 
     for(k=0;k<grid->nz;k++) 
     { 
      //  rho's 
      rhoinv[i][j][k]=1./mhd->rho[i][j][k]; 
      rhoiinv[i][j][k]=1./mhd->rhoi[i][j][k]; 
      rhoeinv[i][j][k]=1./mhd->rhoe[i][j][k]; 
      rhoninv[i][j][k]=1./mhd->rhon[i][j][k]; 
     } 
     } 
    } 
    if (tid == 0) 
    { 
     printf("........%04.2f [s] -----\n",(clock()-stime)/CLOCKS_PER_SEC); 
     stime=clock(); 
    } 
    #pragma omp barrier 
    }/*-- End Parallel Region --*/ 
} 

Теперь я попытался по умолчанию (общий) и общий (MHD), но ни какие-либо признаки улучшения. Может быть, так как массивы выделяются

mhd->rho=(double ***)newarray(nx,ny,nz,sizeof(double)); 

Это объявляя структуру или указатель на элемент структуры, что я на самом деле не обмен память на указатели на него? Oh и nx = 389 ny = 7 и nz = 739 в этом примере. Время выполнения для этого раздела в последовательном порядке составляет 0,23 [с] и 0,79 [с] для 8 потоков.

ответ

1

Моя проблема сводится к реальной простой ошибке .... clock(). В то время как я защитил свой алгоритм времени, только имея определенный поток, подсчитал время, я забыл одну важную вещь о clock() ... он возвращает время настенных часов, которое является общим временем процессора (суммирование по активным потокам). То, что мне нужно было звонить, было omp_get_wtime(). Выполняя это, я внезапно вижу ускорение для многих разделов моего кода. Для записи я изменил мой код, чтобы включить

#ifdef _OPENMP 
    #include <omp.h> 
    #define TIMESCALE 1 
#else 
    #define omp_get_thread_num() 0 
    #define omp_get_num_procs() 0 
    #define omp_get_num_threads() 1 
    #define omp_set_num_threads(bob) 0 
    #define omp_get_wtime() clock() 
    #define TIMESCALE CLOCKS_PER_SEC 
#endif 

И мой алгоритм синхронизации теперь

#pragma omp barrier 
    if (tid == 0) 
    { 
     stime=omp_get_wtime(); 
     printf("-----1) Calculating leap helpers"); 
    } 
    #pragma omp for 
    for(i=0;i<grid->nx;i++) 
    { 
     for(j=0;j<grid->ny;j++) 
     { 
      for(k=0;k<grid->nz;k++) 
      { 
       //  rho's 
       rhoinv[i][j][k]=1./mhd->rho[i][j][k]; 
       rhoiinv[i][j][k]=1./mhd->rhoi[i][j][k]; 
       rhoeinv[i][j][k]=1./mhd->rhoe[i][j][k]; 
       rhoninv[i][j][k]=1./mhd->rhon[i][j][k]; 
       // 1./(gamma-1.) 
       gaminv[i][j][k]=1./(mhd->gamma[i][j][k]-1.); 
       gamiinv[i][j][k]=1./(mhd->gammai[i][j][k]-1.); 
       gameinv[i][j][k]=1./(mhd->gammae[i][j][k]-1.); 
       gamninv[i][j][k]=1./(mhd->gamman[i][j][k]-1.); 
      } 
     } 
    } 
    if (tid == 0) 
    { 
     printf("........%04.2f [s] -----\n",(omp_get_wtime()-stime)/TIMESCALE); 
     stime=omp_get_wtime(); 
     printf("-----2) Calculating leap helpers"); 
    } 
0

Важным моментом здесь может быть ваша верхняя граница ваших циклов. Поскольку вы используете grid->nz и т. Д. OpenMP не может знать, будут ли они изменяться или нет для каждой итерации. Загрузите эти значения в локальные переменные и используйте их для условия цикла.

+0

Я пытался делать просто ... нет кубика же время выполнения. Я также попытался поместить все данные в локальные массивы (rhotemp) и получить доступ к ним вместо значений в структуре. – Lazer

0

Ну, вы также используете парные и деление. Можете ли вы сделать деление на умножение?

Единица с плавающей точкой делится между ядрами, а деления не имеют детерминированного числа циклов до завершения (в отличие от умножения). Таким образом, вы получаете сериализацию для доступа к модулю fp.

Я уверен, что если вы используете интегральные типы или умножение, вы увидите ускорение.

+0

Фактически этот раздел кода настраивает обратные помощники, так что в остальной части кода исключается разделение. Я изменю деление на умножение и посмотрю, есть ли изменения. Хотя, если есть, тогда мне просто придется сериализовать этот цикл for. – Lazer

+0

Код все еще работает медленнее, если деление переключается на умножение. И скорость ухудшается с увеличением количества процессоров (скажем, от 2 до 8). – Lazer

Смежные вопросы