Le problème que j'essaie de résoudre est ce qui suit:
Le code série C++ J'ai calculé sur une grande matrice 2D. Pour optimiser ce processus, je souhaite diviser cette grande matrice 2D et exécuter 4 nœuds (par exemple) en utilisant MPI. La seule communication qui se produit entre les nœuds est le partage des valeurs de bord à la fin de chaque étape de la période. Chaque nœud partage les données de la matrice Edge, [I] [J], avec son voisin.
Basé sur la lecture sur MPI, j'ai le système suivant à mettre en œuvre.
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
}
Je voulais savoir si mon approche est correcte et que j'apprécierais également toutes les directives sur d'autres MPI fonctions aussi sur la mise en œuvre.
Merci, Ashwin.
Juste pour amplifier un peu les points de Joel:
Cela va beaucoup plus facile si vous allouez vos tableaux de manière à ce qu'ils sont contigus (quelque chose "des" tableaux multidimensionnels "ne vous donnent pas automatiquement :)
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<rows; i++)
array[i] = &(data[cols*i]);
return array;
}
/*...*/
int **A;
/*...*/
A = alloc_2d_init(N,M);
Ensuite, vous pouvez faire des envois et des récompenses de l'ensemble de la matrice NXM avec
MPI_Send(&(A[0][0]), N*M, MPI_INT, destination, tag, MPI_COMM_WORLD);
et quand vous avez terminé, libérez la mémoire avec
free(A[0]);
free(A);
Aussi, MPI_Recv
est une recette de blocage et MPI_Send
peut être un envoi de blocage. Une chose qui signifie, selon le point de Joel, est que vous n'avez certainement pas besoin de barrières. En outre, cela signifie que si vous avez un modèle d'envoi/recevez comme ci-dessus, vous pouvez vous mettre dans une situation d'impasse - tout le monde envoie, personne ne reçoit. Plus sûr est:
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);
}
Une autre approche plus générale est d'utiliser 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 des envois non bloquants et/ou reçoivent.
Tout d'abord, vous n'avez pas besoin de beaucoup de barrière secondaire, vous devriez vraiment envoyer vos données sous forme de bloc unique en tant que multiples envoi/réception Bloquant leur chemin entraînera de mauvaises performances.