2016-10-07 9 views
1

그래서 ... 내 질문은 간단합니다. C - MPI - 배열에 서브 어레이 보내기/받기

의 우리가 6 개 * 6 세포의 master_array와 마스터 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 

그리고 우리는 MPI 3 개 * 3 세포의 worker_array으로 처리 4 직원을 가지고 있습니다.

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 개 과정에서 확인을 작동하는 것 같다 :

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 

이 매트릭스는 프로세스 그리드에 정확히 분해 어떤 상황에서도 작동합니다. 프로세스가 모두 정확히 같은 크기의 부분 행렬을 가지고 있지 않으면 조금 더 복잡해집니다.