2017-07-17 12 views
0

私はopenmpワークシェアリング構成を使用しようとしています。共有されたコードは、私の大きなopenmpコードで間違っていることの簡単な例です。私は整数行列に値を代入し、行列要素の値を出力し、0に初期化し、 't'ループでそれを繰り返す。私は値の代入(並列のために行われる)が整数 'p'で失敗する回数を数えています。コードが正しければ、pは0であるはずですが、異なる実行に対して私に異なる答えを与えるので、作業構造はどこかで失敗しています。出力の1,2,3などのpの最初の間違った値を得る前に、12回ぐらい実行しなければならなかった。openmpはスケジュールのために並行して実行され、いくつかのプログラムの実行に対して異なる回答を与えます

コード内のバリア指示は本当に必要ではなく、私は別の値を得ていた明白な障壁が助けになると思ったが、私は間違っていた。これはコードです:

#define NRA 10     /* number of rows in matrix A */ 
    #define NCA 10     /* number of columns in matrix A */ 

    int main() 
    { 
     int i, j, ir, p = 0, t; 
     int *a; 
     a = (int*) malloc(sizeof(int)*NRA*NCA); 

     omp_set_num_threads(5); 

     for(t=0;t<100000;t++) 
     { 
      #pragma omp barrier 
      #pragma omp parallel for schedule (static,2) collapse(2) 
      for(i=0;i<NRA;i++) 
      { 
       for(j=0;j<NCA;j++) 
       { 
        ir=j*NRA+i; 
        a[ir] = 1; 
       } 
      } 

      #pragma omp single 
      { 
       for(i=0;i<NRA;i++) 
       { 
        for(j=0;j<NCA;j++) 
        { 
         ir=j*NRA+i; 
         if(a[ir] != 1) 
         { 
          p += 1; 
         } 
        } 
       } 
      } 

      #pragma omp parallel for schedule (static,2) collapse(2) 
      for(i=0;i<NRA;i++) 
      { 
       for(j=0;j<NCA;j++) 
       { 
        ir=j*NRA+i; 
        a[ir] = 0; 
       } 
      } 

      # pragma omp barrier 
     }//end t 

     printf("p is %d\n",p); 
    } 

これは大きなコードであり、そして私は、並列ループ内でローカル共有並列ループおよび他のすべての変数外のすべての変数を宣言したため、競合状態が問題であるとは思いません。どんな提案も役に立つでしょう!

#define NRA 10     /* number of rows in matrix A */ 
    #define NCA 10     /* number of columns in matrix A */ 
    #define NCB 10     /* number of columns in matrix B */ 

    void matrixcalc (double *ad, double *bd, double *cd, int chunkd); 
    void printresults (double *cd, int chunkd); 
    void printrep (double *cd, int chunkd); 

    int main() 
    { 
     int nthreads, chunk, p = 0; 
     double *a,*b,*c; 
     a = (double*)malloc(NRA*NCA*sizeof(double)); 
     if(a==NULL) 
      printf("ho\n"); 
     b = (double*)malloc(NCA*NCB*sizeof(double)); 
     c = (double*)malloc(NRA*NCB*sizeof(double)); 

     omp_set_num_threads(5); 

     chunk = 2;     /* set loop iteration chunk size */ 
     int ir3, i1, j1; 

     /*** Spawn a parallel region explicitly scoping all variables ***/ 
     int t, tmax = 100000; 
     for(t=0;t<tmax;t++) 
     { 
      #pragma omp parallel shared(a,b,c,nthreads,chunk,t,tmax) 
      { 
       int tid = omp_get_thread_num(); 
       int i, j, ir; 
       if (tid == 0) 
       { 
        nthreads = omp_get_num_threads(); 
        // printf("Starting matrix multiple example with %d threads\n",nthreads); 
        // printf("Initializing matrices...\n"); 
       } 

       /*** Initialize matrices ***/ 
       #pragma omp for schedule (static, chunk) collapse(2) 
       for (i=0; i<NRA; i++) 
       { 
        for (j=0; j<NCA; j++) 
        { 
         ir =j*NRA+i; 
         a[ir]= 1.0; 
        } 
       } 
       #pragma omp for schedule (static, chunk) collapse(2) 
       for (i=0; i<NCA; i++) 
       { 
        for (j=0; j<NCB; j++) 
        { 
         ir = j*NCA+i; 
         b[ir] = 1.0; 
        } 
       } 
       #pragma omp for schedule (static, chunk) collapse(2) 
       for (i=0; i<NRA; i++) 
       {  
        for (j=0; j<NCB; j++) 
        { 
         ir=j*NRA+i; 
         c[ir]= 0.0; 
        } 
       } 
       /*** Do matrix multiply sharing iterations on outer loop ***/ 
       /*** Display who does which iterations for demonstration purposes ***/ 

       matrixcalc(a,b,c,chunk); 
       if(t!=tmax-1) 
       { 
        #pragma omp for schedule (static, chunk) collapse(2) 
        for(i=0;i<NRA;i++) 
        {  
         for(j=0;j<NCB;j++) 
         { 
          ir=j*NRA+i; 
          c[ir]=0.0; 
         } 
        } 
       } 
      }//end parallel region 

      for(i1=0;i1<NRA;i1++) 
      { 
       for(j1=0;j1<NCB;j1++) 
       { 
        ir3=j1*NRA+i1; 
        if(c[ir3]!=12.20000&&c[ir3]!=0.0) 
        { 
         printf("%lf\n",c[ir3]); 
         p+=1; 
        } 
       } 
      } 

     }//end t 
     printf("finalp\t%d\n",p); 
     for(i1=0;i1<NRA;i1++) 
     { 
      for(j1=0;j1<NCB;j1++) 
      { 
       ir3=j1*NRA+i1; 
       printf("%lf\t",c[ir3]); 
      } 
      printf("\n"); 
     } 
    } 

    void matrixcalc (double *a, double *b, double *c, int chunk) 
    { 
     int i,j,k,ir,ir1,ir2; 

     //printf("Thread %d starting matrix multiply...%d\n",tid,chunk); 
     double r = 1.0; 
     #pragma omp for schedule (static, chunk) collapse(3) 

     for (i=0; i<NRA; i++)  
     { 
      for(j=0; j<NCB; j++) 
      {  
       for (k=0; k<NCA; k++) 
       { 
        ir=j*NRA+i; 
        ir1=k*NRA+i; 
        ir2=j*NCA+k; 
        c[ir] += a[ir1] * b[ir2]; 
       } 
      } 
     } 
     #pragma omp for schedule (static, chunk) collapse(2) 
     for(i=0;i<NRA;i++) 
     { 
      for(j=0;j<NCB;j++) 
      { 
       ir=j*NRA+i; 
       c[ir]+=r*2.0; 
      } 
     } 
     #pragma omp single 
     { 
      double h; 
      h = 0.1; 
      h = 2.0*h; 
      for(i=0;i<NRA;i++) 
      { 
       for(j=0;j<NCB;j++) 
       { 
        ir=j*NRA+i; 
        c[ir]+=h; 
       } 
      } 
     } 
+0

これらのバリアは、パラレルセクションの外にあるため(並列性が作成されていないため)、まったく必要ありません。さらに、 'omp single'と' omp for'はブロックの終わりに暗黙のバリアを生成します。したがって、いずれの場合も重複します。 't'ループの外側にパラレル(唯一の)コンストラクトを使用し、残りのコンストラクトでは' omp for'と 'omp single'を使います。さらに、 'i'ループと' j'ループの順序を変更して、要素を順番にアクセスする(キャッシュの局所性を向上させる)。 –

+0

私は障壁について理解していますが、私は他の提案を書き留めました(私は理由を理解できませんでしたが)。私は並列構造をtループの外側に置こうとしましたが、コードは出力を与えるのにかなり時間がかかりました。私はプログラムを終了しなければなりませんでした。 – PooriR

+0

あなたのエラーについて - 私は実質的に変更された質問などの完全なレビューはしませんが、並列領域内からの 'matrixcalc(a、b、c、chunk); 'の呼び出しは問題を求めています。 – Zulan

答えて

2

問題は競合状態irです。ループの外側で定義されているため、暗黙的にsharedです。これを強制的にprivateにすることもできますが、できるだけローカルに変数を宣言する方が良いでしょう。これは、OpenMPコードについての推論がはるかに容易になります:

#pragma omp parallel for schedule (static,2) collapse(2) 
for(int i=0;i<NRA;i++) 
{ 
    for(int j=0;j<NCA;j++) 
    { 
     int ir = j*NRA+i; 
     a[ir] = 1; 
    } 
} 

ホルヘ・ベロンでコメントしたように、他の問題は、冗長な障壁や効率に関して、あなたのコードです。

+0

ありがとう!同様の大きさのコードでは、私はir、i、jを非公開と宣言したので、ただちに競合状態になることはありませんでしたが、これは私がここに書いたコードで働いていました。 – PooriR

+0

アップデートでは、@ Zulanが指摘したのと同様の問題があります。この場合、 'ir3'変数が発生します。 –

+0

私は 'ir3'は並列領域の外側でのみ使用されると信じています。しかし、私は自分自身を繰り返すことができます。デフォルトでは、可能な限りローカル変数を宣言し**、同じ行に初期化します。あなたは自分自身を大いに救います。 – Zulan

関連する問題