2016-10-07 8 views
1

So ...私の質問は簡単です。C - MPI - アレイへのサブアレイの送受信

Master 
----------- 
0 0 0 0 0 0 
0 0 0 0 0 0 
0 0 0 0 0 0 
0 0 0 0 0 0 
0 0 0 0 0 0 
0 0 0 0 0 0 

そして、我々は3つの* 3セルのworker_arrayと4つのワーカーMPIプロセスを持っている:

は、我々は6個の* 6細胞のmaster_arrayとマスターMPIプロセスを持っていると仮定しましょう。

Worker 1 | Worker 2 | Worker 3 | Worker 4 | 
------- | ------- | ------- | ------- | 
1 1 1 | 2 2 2 | 3 3 3 | 4 4 4 | 
1 1 1 | 2 2 2 | 3 3 3 | 4 4 4 | 
1 1 1 | 2 2 2 | 3 3 3 | 4 4 4 | 

は今、私はこのようなマスターアレイに労働者の配列を送信したい:

Master 
----------- 
1 1 1 2 2 2 
1 1 1 2 2 2 
1 1 1 2 2 2 
3 3 3 4 4 4 
3 3 3 4 4 4 
3 3 3 4 4 4 

はどのようにすれば、受信/いくつかの現物・オブ・MPI-お送り使用して、こので終わるんMPI_datatypesまたはMPI_vectorsまたはMPI_subarraysまたはMPI_whatever-does-the-trick?

私はあなたが私の要点を得ることを願っています。

詳しいコードと作業コードの回答には深く感謝します。

+2

ここで探している回答を見つけることができます:http://stackoverflow.com/questions/9269399/sending-blocks-of-2d-array-in-c-using-mpi – Angelos

答えて

1

ここでは、ポイントツーポイントとコレクティブの両方を使用する作業用コードを示します(集合バージョンは以下にコメントアウトされていますが正常に動作します)。マスター側の受信側の非連続データに対応するベクトルタイプを定義する必要があります。コレクティブギャザーを使用するには、このベクトルのサイズを混乱させて、ギャザーバージョンを使用する必要があります。

配列インデックスが乱雑になるのは簡単です。一般的には、6x12マトリックス上に2x3配列のプロセスを使用していますので、故意に正方形ではありません。

私はタブ/スペースの問題を抱えているようですが、私は本当に将来これを整理しなければなりません!

#include <stdio.h> 
#include <stdlib.h> 
#include <mpi.h> 

#define M 6 
#define N 12 

#define MP 2 
#define NP 3 

#define MLOCAL (M/MP) 
#define NLOCAL (N/NP) 

#define TAG 0 

int main(void) 
{ 
    int master[M][N]; 
    int local[MLOCAL][NLOCAL]; 

    MPI_Comm comm = MPI_COMM_WORLD; 
    int rank, size, src; 
    int i, j; 
    int istart, jstart; 
    int displs[MP*NP], counts[MP*NP]; 

    MPI_Status status; 
    MPI_Request request; 
    MPI_Datatype block, blockresized; 

    MPI_Init(NULL, NULL); 

    MPI_Comm_size(comm, &size); 
    MPI_Comm_rank(comm, &rank); 

    if (size != MP*NP) 
    { 
     if (rank == 0) printf("Size %d not equal to MP*NP = %d\n", size, MP*NP); 
     MPI_Finalize(); 
     return 1; 
    } 

    for (i=0; i < M; i++) 
    { 
     for (j=0; j < N; j++) 
    { 
     master[i][j] = rank; 
    } 
    } 

    for (i=0; i < MLOCAL; i++) 
    { 
     for (j=0; j < NLOCAL; j++) 
    { 
     local[i][j] = rank+1; 
    } 
    } 

    // Define vector type appropriate for subsections of master array 

    MPI_Type_vector(MLOCAL, NLOCAL, N, MPI_INT, &block); 
    MPI_Type_commit(&block); 

    // Non-blocking send to avoid deadlock with rank 0 sending to itself 

    MPI_Isend(local, MLOCAL*NLOCAL, MPI_INTEGER, 0, TAG, comm, &request); 

    // Receive from all the workers 

    if (rank == 0) 
    { 
     for (src=0; src < size; src++) 
    { 
     // Find out where this block should go 

     istart = (src/NP) * MLOCAL; 
     jstart = (src%NP) * NLOCAL; 

     // receive a single block 

     MPI_Recv(&master[istart][jstart], 1, block, src, TAG, comm, &status); 
    } 
    } 

    // Wait for send to complete 

    MPI_Wait(&request, &status); 

    /* comment out collective 

    // Using collectives -- currently commented out! 

    MPI_Type_create_resized(block, 0, sizeof(int), &blockresized); 
    MPI_Type_commit(&blockresized); 

    // Work out displacements in master in counts of integers 

    for (src=0; src < size; src++) 
    { 
     istart = (src/NP) * MLOCAL; 
     jstart = (src%NP) * NLOCAL; 

     displs[src] = istart*N + jstart; 
     counts[src] = 1; 
    } 

    // Call collective 

    MPI_Gatherv(local, MLOCAL*NLOCAL, MPI_INT, 
      master, counts, displs, blockresized, 
      0, comm); 

    */ 

    // Print out 

    if (rank == 0) 
    { 
     for (i=0; i < M; i++) 
    { 
     for (j=0; j < N; j++) 
     { 
      printf("%d ", master[i][j]); 
     } 
     printf("\n"); 
    } 
    } 

    MPI_Finalize(); 
} 

6つのプロセスでOK動作するようです:

mpiexec -n 6 ./arraygather 
1 1 1 1 2 2 2 2 3 3 3 3 
1 1 1 1 2 2 2 2 3 3 3 3 
1 1 1 1 2 2 2 2 3 3 3 3 
4 4 4 4 5 5 5 5 6 6 6 6 
4 4 4 4 5 5 5 5 6 6 6 6 
4 4 4 4 5 5 5 5 6 6 6 6 

これは、マトリックスは、プロセスグリッド上に正確に分解するどのような状況で動作するはずです。プロセスがすべてサブ行列のサイズがまったく同じでない場合は、少し複雑になります。

関連する問題