Envio e recebimento de array 2D sobre MPI

O problema que estou tentando resolver é o seguinte:

O código serial C ++ que calculei em uma grande matriz 2D. Para otimizar este processo, desejo dividir essa grande matriz 2D e rodar em 4 nós (digamos) usando MPI. A única comunicação que ocorre entre nós é o compartilhamento de valores de borda no final de cada etapa de tempo. Cada nó compartilha os dados da matriz de arestas, A [i] [j], com seu vizinho.

Com base na leitura do MPI, tenho o seguinte esquema a ser implementado.

if (myrank == 0) { for (i= 0 to x) for (y= 0 to y) { C++ CODE IMPLEMENTATION .... MPI_SEND(A[x][0], A[x][1], A[x][2], Destination= 1.....) MPI_RECEIVE(B[0][0], B[0][1]......Sender = 1.....) MPI_BARRIER } if (myrank == 1) { for (i = x+1 to xx) for (y = 0 to y) { C++ CODE IMPLEMENTATION .... MPI_SEND(B[x][0], B[x][1], B[x][2], Destination= 0.....) MPI_RECEIVE(A[0][0], A[0][1]......Sender = 1.....) MPI BARRIER } 

Eu queria saber se a minha abordagem está correta e também apreciaria qualquer orientação sobre outras funções MPI também olhar para a implementação.

Obrigado, Ashwin.

Apenas para ampliar um pouco os pontos de Joel:

Isso é muito mais fácil se você alocar seus arrays de modo que eles sejam contíguos (algo como “arrays multidimensionais” de C não lhe dão automaticamente 🙂

 int **alloc_2d_int(int rows, int cols) { int *data = (int *)malloc(rows*cols*sizeof(int)); int **array= (int **)malloc(rows*sizeof(int*)); for (int i=0; i 

Então, você pode enviar e receber toda a matriz NxM com

 MPI_Send(&(A[0][0]), N*M, MPI_INT, destination, tag, MPI_COMM_WORLD); 

e quando terminar, liberte a memory com

 free(A[0]); free(A); 

Além disso, MPI_Recv é um MPI_Recv bloqueio, e MPI_Send pode ser um envio de bloqueio. Uma coisa que significa, de acordo com o ponto de Joel, é que você definitivamente não precisa de Barreiras. Além disso, significa que se você tiver um padrão de envio / recebimento como acima, você poderá entrar em uma situação de impasse - todos estão enviando, ninguém está recebendo. Mais seguro é:

 if (myrank == 0) { MPI_Send(&(A[0][0]), N*M, MPI_INT, 1, tagA, MPI_COMM_WORLD); MPI_Recv(&(B[0][0]), N*M, MPI_INT, 1, tagB, MPI_COMM_WORLD, &status); } else if (myrank == 1) { MPI_Recv(&(A[0][0]), N*M, MPI_INT, 0, tagA, MPI_COMM_WORLD, &status); MPI_Send(&(B[0][0]), N*M, MPI_INT, 0, tagB, MPI_COMM_WORLD); } 

Outra abordagem mais geral é usar o MPI_Sendrecv :

 int *sendptr, *recvptr; int neigh = MPI_PROC_NULL; if (myrank == 0) { sendptr = &(A[0][0]); recvptr = &(B[0][0]); neigh = 1; } else { sendptr = &(B[0][0]); recvptr = &(A[0][0]); neigh = 0; } MPI_Sendrecv(sendptr, N*M, MPI_INT, neigh, tagA, recvptr, N*M, MPI_INT, neigh, tagB, MPI_COMM_WORLD, &status); 

ou nonblocking envia e / ou recebe.

Primeiro, você não precisa de muita barreira. Em segundo lugar, você deve realmente enviar seus dados como um único bloco, já que vários envios / recebimentos bloqueando seu caminho resultarão em desempenhos ruins.