2010-10-28 87 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)); 

?在這個例子中,nx = 389ny = 7,nz = 739。這部分的串行執行時間爲0.23 [s],對於8個線程執行時間爲0.79 [s]。

回答

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 2010-10-29 13:51:11

0

那麼,你也使用雙打和劃分。你可以使分裂成倍增?

浮點單元在內核之間共享,並且分區沒有確定的循環數直到完成(與乘法相反)。所以你最終要訪問fp單元序列化。

我敢肯定,如果你使用積分類型或乘法,你會看到一個加速。

+0

實際上,這段代碼正在設置反向幫助器,以便在代碼的其餘部分避免劃分。我會將分部改爲乘法,看看是否有變化。雖然如果有,那麼我只需要序列化這個for循環。 – Lazer 2010-11-02 12:07:51

+0

如果分度切換到乘法,代碼仍會運行得更慢。隨着更多處理器的速度越來越差(比如2-8)。 – Lazer 2010-11-02 12:31:31