2016-08-23 11 views
0

MPI Scatter/Scattervのルートプロセスで何が起こっているかは、私がまだあまり確信していないことです。MPI Scatterv:ルートプロセスを扱うには?

自分のコードで試したときに配列を分割すると、受信者数にルートプロセスを含める必要があります(したがって、サイズがnprocのsendcountを作成する)か、除外されますか?行列乗算のための私のコード例で

、私はまだ途中でプログラムを終了、異常な行動に実行中のプロセスのいずれかでエラーが発生します:

void readMatrix(); 

double StartTime; 
int rank, nproc, proc; 
//double matrix_A[N_ROWS][N_COLS]; 
double **matrix_A; 
//double matrix_B[N_ROWS][N_COLS]; 
double **matrix_B; 
//double matrix_C[N_ROWS][N_COLS]; 
double **matrix_C; 
int low_bound = 0; //low bound of the number of rows of each process 
int upper_bound = 0; //upper bound of the number of rows of [A] of each process 
int portion = 0; //portion of the number of rows of [A] of each process 


int main (int argc, char *argv[]) { 

    MPI_Init(&argc, &argv); 
    MPI_Comm_size(MPI_COMM_WORLD, &nproc); 
    MPI_Comm_rank(MPI_COMM_WORLD, &rank); 

    matrix_A = (double **)malloc(N_ROWS * sizeof(double*)); 
    for(int i = 0; i < N_ROWS; i++) matrix_A[i] = (double *)malloc(N_COLS * sizeof(double)); 
    matrix_B = (double **)malloc(N_ROWS * sizeof(double*)); 
    for(int i = 0; i < N_ROWS; i++) matrix_B[i] = (double *)malloc(N_COLS * sizeof(double)); 
    matrix_C = (double **)malloc(N_ROWS * sizeof(double*)); 
    for(int i = 0; i < N_ROWS; i++) matrix_C[i] = (double *)malloc(N_COLS * sizeof(double)); 

    int *counts = new int[nproc](); // array to hold number of items to be sent to each process 

    // -------------------> If we have more than one process, we can distribute the work through scatterv 
    if (nproc > 1) { 

     // -------------------> Process 0 initalizes matrices and scatters the portions of the [A] Matrix 
     if (rank==0) { 
      readMatrix(); 
     } 
     StartTime = MPI_Wtime(); 
     int counter = 0; 
     for (int proc = 0; proc < nproc; proc++) { 
      counts[proc] = N_ROWS/nproc ; 
      counter += N_ROWS/nproc ; 
     } 
     counter = N_ROWS - counter; 
     counts[nproc-1] = counter; 
     //set bounds for each process 
     low_bound = rank*(N_ROWS/nproc); 
     portion = counts[rank]; 
     upper_bound = low_bound + portion; 
     printf("I am process %i and my lower bound is %i and my portion is %i and my upper bound is %i \n",rank,low_bound, portion,upper_bound); 
     //scatter the work among the processes 
     int *displs = new int[nproc](); 
     displs[0] = 0; 
     for (int proc = 1; proc < nproc; proc++) displs[proc] = displs[proc-1] + (N_ROWS/nproc); 
     MPI_Scatterv(matrix_A, counts, displs, MPI_DOUBLE, &matrix_A[low_bound][0], portion, MPI_DOUBLE, 0, MPI_COMM_WORLD); 
     //broadcast [B] to all the slaves 
     MPI_Bcast(&matrix_B, N_ROWS*N_COLS, MPI_DOUBLE, 0, MPI_COMM_WORLD); 


     // -------------------> Everybody does their work 
     for (int i = low_bound; i < upper_bound; i++) {//iterate through a given set of rows of [A] 
      for (int j = 0; j < N_COLS; j++) {//iterate through columns of [B] 
       for (int k = 0; k < N_ROWS; k++) {//iterate through rows of [B] 
        matrix_C[i][j] += (matrix_A[i][k] * matrix_B[k][j]); 
       } 
      } 
     } 

     // -------------------> Process 0 gathers the work 
     MPI_Gatherv(&matrix_C[low_bound][0],portion,MPI_DOUBLE,matrix_C,counts,displs,MPI_DOUBLE,0,MPI_COMM_WORLD); 
    } 
... 
+1

あなたの 'matrix_A'は' double ** 'なので、' MPI_Scatterv() 'の最初のパラメータのためのプロファイルには合っていません。 'matrix_A [0]'は持つことができますが、 'malloc()'のループを使ってメモリを割り当てたので、連続して格納されていないため、このように使用することはできません。 – Gilles

答えて

1

ルートプロセスはまた、受信機側で行われます。それに興味がない場合は、sendcounts[root] = 0と設定してください。

正確に渡す必要がある値の具体的な情報については、MPI_Scattervを参照してください。

しかし、あなたがしていることを世話してください。私は強くあなたがこのような単一のmallocを使用して、あなたは一次元配列としてあなたの行列を割り当てる方法を変更することを示唆している:

double* matrix = (double*) malloc(N_ROWS * N_COLS * sizeof(double)); 

あなたはまだ2次元配列を使用したい場合は、あなたがする必要があるかもしれませんタイプをMPI derived datatypeと定義します。

単一のMPI転送で2つ以上の行を送信する場合は、渡すデータ型は無効です。バッファはMPI_DOUBLE値の連続した配列が含まれていることをあなたはMPIを言っているMPI_DOUBLE

malloc複数の呼び出しを使用して2次元配列を割り当てるので、データは連続していません。

関連する問題