2011-01-25 89 views
0

在下面的程序中,我得到了不同的結果(serial vs OpenMP),原因是什麼?目前我只能認爲循環對於線程來說可能太「大」,也許我應該用其他方式來寫,但我不確定是否有任何提示?OpenMP嵌套循環中的奇怪行爲

編譯:g++-4.2 -fopenmp main.c functions.c -o main_elec_gcc.exe

#include <stdio.h> 
    #include <string.h> 
    #include <stdlib.h> 
    #include <omp.h> 
    #include <math.h> 

    #define NRACK 64 
    #define NSTARS 1024 

    double mysumallatomic_serial(float rocks[NRACK][3],float moon[NSTARS][3],float qr[NRACK],float ql[NSTARS]) { 
     int j,i; 
     float temp_div=0.,temp_sqrt=0.; 
     float difx,dify,difz; 
     float mod2x, mod2y, mod2z; 
     double S2 = 0.; 
    for(j=0; j<NRACK; j++){ 
     for(i=0; i<NSTARS;i++){  
      difx=rocks[j][0]-moon[i][0]; 
      dify=rocks[j][1]-moon[i][1]; 
      difz=rocks[j][2]-moon[i][2]; 
      mod2x=difx*difx; 
      mod2y=dify*dify; 
      mod2z=difz*difz; 
      temp_sqrt=sqrt(mod2x+mod2y+mod2z); 
      temp_div=1/temp_sqrt; 
      S2 += ql[i]*temp_div*qr[j];  
     } 
    } 
    return S2; 
} 

double mysumallatomic(float rocks[NRACK][3],float moon[NSTARS][3],float qr[NRACK],float ql[NSTARS]) { 
    float temp_div=0.,temp_sqrt=0.; 
    float difx,dify,difz; 
    float mod2x, mod2y, mod2z; 
    double S2 = 0.; 

#pragma omp parallel for shared(S2) 
    for(int j=0; j<NRACK; j++){ 
     for(int i=0; i<NSTARS;i++){ 
      difx=rocks[j][0]-moon[i][0]; 
      dify=rocks[j][1]-moon[i][1]; 
      difz=rocks[j][2]-moon[i][2]; 
      mod2x=difx*difx; 
      mod2y=dify*dify; 
      mod2z=difz*difz; 
      temp_sqrt=sqrt(mod2x+mod2y+mod2z); 
      temp_div=1/temp_sqrt; 
      float myterm=ql[i]*temp_div*qr[j]; 
      #pragma omp atomic 
      S2 += myterm; 
     } 
    } 
    return S2; 

int main(int argc, char *argv[]) { 
float rocks[NRACK][3], moon[NSTARS][3]; 
float qr[NRACK], ql[NSTARS]; 
int i,j; 

for(j=0;j<NRACK;j++){ 
    rocks[j][0]=j; 
    rocks[j][1]=j+1; 
    rocks[j][2]=j+2; 
    qr[j] = j*1e-4+1e-3; 
    //qr[j] = 1; 
} 

for(i=0;i<NSTARS;i++){ 
    moon[i][0]=12000+i; 
    moon[i][1]=12000+i+1; 
    moon[i][2]=12000+i+2; 
    ql[i] = i*1e-3 +1e-2 ; 
    //ql[i] = 1 ; 
} 
printf(" serial: %f\n", mysumallatomic_serial(rocks,moon,qr,ql)); 
printf(" openmp: %f\n", mysumallatomic(rocks,moon,qr,ql)); 
return(0); 

    } 
    } 

回答

0

我認爲你應該使用reduction而不是共享變量和刪除#pragma omp atomic,如:

#pragma omp parallel for reduction(+:S2) 

,它應該工作得更快,因爲沒有必要原子在性能和線程同步方面相當痛苦的操作。

UPDATE

您也可以在因經營業績差一些命令:

\sum_1^100(x[i]) != \sum_1^50(x[i]) + \sum_51^100(x[i])

+0

謝謝,但我仍然遇到同樣的問題 – flow 2011-01-25 17:00:59

+0

嘗試將您的陣列定義爲共享 – Elalfer 2011-01-25 17:05:11

0

您對大多數的臨時變量的數據爭您正在使用的並行region - difx,dify,difz,mod2x,mod2y,mod2z,temp_sqrt和temp_div都應該是私有的。您應該通過在parallel for指令中使用私有子句來使這些變量保持私有。