Envío y recepción de matriz 2D en MPI

El problema que bash resolver es el siguiente:

El código de serie C ++ que he calculado en una gran matriz 2D. Para optimizar este proceso, deseo dividir esta gran matriz 2D y ejecutar en 4 nodos (por ejemplo) usando MPI. La única comunicación que se produce entre los nodos es el intercambio de valores de borde al final de cada paso de tiempo. Cada nodo comparte los datos de la matriz de borde, A [i] [j], con su vecino.

Basado en leer sobre MPI, tengo el siguiente esquema para implementar.

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 } 

Quería saber si mi enfoque es correcto y también agradecería que cualquier orientación sobre otras funciones de MPI también busque la implementación.

Gracias, Ashwin.

Solo para amplificar un poco los puntos de Joel:

Esto es mucho más fácil si asigna sus matrices para que sean contiguas (algo que las “matrices multidimensionales” de C no le dan automáticamente 🙂

 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 

Entonces, puede hacer envíos y recibir de toda la matriz NxM con

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

y cuando haya terminado, libere la memoria con

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

Además, MPI_Recv es una MPI_Recv locking, y MPI_Send puede ser un envío de locking. Una cosa que significa, según el punto de Joel, es que definitivamente no necesita Barreras. Además, significa que si tienes un patrón de envío / recepción como el anterior, puedes ponerte en una situación de punto muerto: todos están enviando, nadie está recibiendo. Más seguro es:

 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); } 

Otro enfoque más general es usar 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); 

o no locking envía y / o recibe.

Primero, no necesitas tanta barrera. Segundo, realmente deberías enviar tus datos como un solo bloque ya que el envío / recepción múltiple que bloquea su camino dará como resultado un rendimiento pobre.