2016-03-30 19 views
0
#include<stdio.h> 
#include<mpi.h> 

int main() 
{ 
     int a_r = 0, a_c = 0, v_s = 0, i = 0, rank = 0, size = 0; 
     int local_row = 0, partial_sum = 0, sum = 0, j = 0; 
     int my_first_ele = 0, my_last_ele = 0; 
     int a[10][10], v[10], partial_mul[10] = {0}, mul[10] = {0}; 

     MPI_Init(NULL, NULL); 
     MPI_Comm_rank(MPI_COMM_WORLD, &rank); 
     MPI_Comm_size(MPI_COMM_WORLD, &size); 

     if(rank == 0) 
     { 
       printf("Enter the row of array A: "); 
       scanf("%d", &a_r); 
       printf("Enter the column of array A: "); 
       scanf("%d", &a_c); 
       printf("Enter the array A: "); 

       for(i = 0; i < a_r; i++) 
       { 
         for(j = 0; j < a_c; j++) 
           scanf("%d", &a[i][j]); 
       } 

       printf("Enter the size of vector array: "); 
       scanf("%d", &v_s); 
       printf("Enter the vector array: "); 
       for(i = 0; i < v_s; i++) 
       { 
         scanf("%d", &v[i]); 
       } 

       MPI_Bcast(&a_r, 1, MPI_INT, 0, MPI_COMM_WORLD); 
       MPI_Bcast(&a_c, 1, MPI_INT, 0, MPI_COMM_WORLD); 
       MPI_Bcast(&v_s, 1, MPI_INT, 0, MPI_COMM_WORLD); 
       MPI_Bcast(a, a_r*a_c, MPI_INT, 0, MPI_COMM_WORLD); 
       MPI_Bcast(v, v_s, MPI_INT, 0, MPI_COMM_WORLD); 

       local_row = a_r/size; 
       my_first_ele = rank * local_row; 
       my_last_ele = (rank+1) * local_row; 

       if(a_c == v_s) 
       {  
         for(i = my_first_ele; i < my_last_ele; i++) 
         { 
           for(j = 0; j < a_c; j++) 
           { 
             partial_mul[i] = partial_mul[i] + (a[i][j]*v[j]); 
           } 
         } 
         printf("\nPartial multiplication in Rank 0: \n"); 
         for(i = my_first_ele; i < my_last_ele; i++) 
           printf("%d \n", partial_mul[i]); 

         MPI_Gather(partial_mul, local_row, MPI_INT, mul, local_row, MPI_INT, 0, MPI_COMM_WORLD); 

         printf("\n \nGlobal Multiplication: \n"); 
         for(i = 0; i < a_r; i++) 
         { 
           printf("%d \n", mul[i]); 
         } 
       } 
       else 
         printf("\nCan't multiply. \n"); 
     } 

     else 
     { 
       MPI_Bcast(&a_r, 1, MPI_INT, 0, MPI_COMM_WORLD); 
       MPI_Bcast(&a_c, 1, MPI_INT, 0, MPI_COMM_WORLD); 
       MPI_Bcast(&v_s, 1, MPI_INT, 0, MPI_COMM_WORLD); 
       MPI_Bcast(a, a_r*a_c, MPI_INT, 0, MPI_COMM_WORLD); 
       MPI_Bcast(v, v_s, MPI_INT, 0, MPI_COMM_WORLD); 

       local_row = a_r/size; 
       my_first_ele = rank * local_row; 
       my_last_ele = (rank+1) * local_row; 
       if(a_c == v_s) 
       {  
         for(i = my_first_ele; i < my_last_ele; i++) 
         { 
           for(j = 0; j < a_c; j++) 
           { 
             partial_mul[i] = partial_mul[i] + (a[i][j]*v[j]); 
           } 
         } 
         printf("\nPartial multiplication in Rank %d: \n", rank); 
         for(i = my_first_ele; i < my_last_ele; i++) 
           printf("%d \n", partial_mul[i]); 

         MPI_Gather(partial_mul, local_row, MPI_INT, mul, local_row, MPI_INT, 0, MPI_COMM_WORLD); 

       } 
       else 
         printf("\nCan't multiply. \n"); 
     } 
     MPI_FINALIZE(); 
} 

私は上記のコードに問題があります。私の部分乗算値は正しいです。しかし私の全体的な乗算では、ランク0の要素しか集めることができず、残りの値は0として出力されています。問題は誰でも説明できます。MPIベクトル乗算

答えて

0

は、あなたのデータレイアウトを見ると、私はあなたがMPIでのデータ構造を誤解だと思う:すべてのデータは各ランクで別々に維持され、何のimplict共有や分布がありません。あなたのベクトルpartial_sumは、それぞれのランクごとに別々のものであり、それぞれが完全な10の要素を持っています。そう内容は次のようになります計算の後、size=2a_r=10ゼロ初期化を想定:

  • ランク0:{x0,x1,x2,x3,x4,0,0,0,0,0}
  • ランク1:{0,0,0,0,0,x5,x6,x7,x8,x9}

xが正しい計算値です。収集すると、最初のlocal_row=5要素が各ランクから収集され、{x0,x1,x2,x3,x4,0,0,0,0,0}となります。

あなたはちょうど正しいオフセットを追加することによってこの問題を解決することができます:

MPI_Gather(&partial_mul[my_first_ele], local_row, MPI_INT, mul, local_row, MPI_INT, 0, MPI_COMM_WORLD); 

しかし、それをしないでください。代わりに、あなたは、実際にデータを分散するために、あなたのデータ構造を見直すベクトル/配列の各部分の正しいサイズを確保しなければなりません。各ランクにデータの部分の周りに送るために、MPI_ScatterMPI_Gatherの反対側)を使用します。最も難しいのは、行列を正しく取得することです。これは、this excellent answerによって詳細に説明されています。