MPI Spawn: le processus racine ne communique pas avec les processus enfants

(Question du débutant) J’essaie de générer des processus de manière dynamic à l’aide de MPI_Comm_Spawn, puis de diffuser un message aux processus enfants, mais le programme s’arrête dans la diffusion depuis le processus racine vers les enfants. Je suis la documentation de http://www.mpi-forum.org/docs/docs.html mais je ne peux pas le faire fonctionner. Est-ce que quelqu’un peut m’aider s’il vous plaît?

#include  #include  int main(int argc, char *argv[]) { MPI_Init(&argc, &argv); MPI_Comm parentcomm; MPI_Comm_get_parent( &parentcomm ); if (parentcomm == MPI_COMM_NULL) { MPI_Comm intercomm; MPI_Status status; char msg_rec[1024]; char msg_send[1024]; int size, i; int np = (argc > 0) ? atoi(argv[1]) : 3; printf("Spawner will spawn %d processes\n", np); MPI_Comm_spawn( argv[0], MPI_ARGV_NULL, np, MPI_INFO_NULL, 0, MPI_COMM_SELF, &intercomm, MPI_ERRCODES_IGNORE ); MPI_Comm_size(intercomm, &size); sprintf(msg_send, "Hello!"); printf("Spawner will broadcast '%s'\n", msg_send); MPI_Bcast( (void*)msg_send, 1024, MPI_CHAR, 0, intercomm); printf("Spawner will receive answers\n"); for (i=0; i < size; i++) { MPI_Recv( (void*)msg_rec, 1024, MPI_CHAR, i, MPI_ANY_TAG, intercomm, &status); printf("Spawner received '%s' from rank %d\n", msg_rec, i); }; } else { int rank, size; char msg_rec[1024]; char msg_send[1024]; MPI_Comm_rank(parentcomm, &rank); MPI_Comm_size(parentcomm, &size); printf(" Rank %d ready\n", rank); MPI_Bcast( (void*)msg_rec, 1024, MPI_CHAR, 0, parentcomm); printf(" Rank %d received '%s' from broadcast!\n", rank, msg_rec); sprintf(msg_send, "Hi there from rank %d!\n", rank); MPI_Send( (void*)msg_send, 1024, MPI_CHAR, 0, rank, parentcomm); }; MPI_Finalize(); return 0; }; 

Je ne sais pas si cela compte, mais j’utilise Ubuntu 11.10 et Hidra Process Manager.

Comme @suszterpatt l’a fait remarquer, vous travaillez avec un “intercommunicateur” (et non un “intracommunicateur”). Sachant cela et en regardant MPI_Bcast , nous voyons:

Si comm est un intercommunicateur, l’appel implique tous les processus de l’intercommunicateur, mais avec un groupe (groupe A) définissant le processus racine. Tous les processus de l’autre groupe (groupe B) transmettent la même valeur dans l’argument root, qui correspond au rang de la racine du groupe A. La racine transmet la valeur MPI_ROOT dans root. Tous les autres processus du groupe A transmettent la valeur MPI_PROC_NULL en racine. Les données sont diffusées de la racine à tous les processus du groupe B. Les arguments du tampon de réception des processus du groupe B doivent être cohérents avec l’argument du tampon d’envoi de la racine.

Cela signifie que vous ne devez remplacer l’appel diffusé dans le parent que par:

 MPI_Bcast( (void*)msg_send, 1024, MPI_CHAR, MPI_ROOT, intercomm); 

Quelques autres bugs:

  • La vérification du nombre d’arguments doit être argc > 1 .
  • MPI_Comm_size(intercomm, &size) renverra 1 . Vous voudrez MPI_Comm_remote_size(intercomm, &size) utiliser MPI_Comm_remote_size(intercomm, &size) .

Si vous ne souhaitez pas traiter avec un intercommunicateur après avoir créé vos processus enfants, vous pouvez utiliser MPI_Intercomm_merge pour créer un intracommunicateur à partir de votre intercommunicateur. Essentiellement, cela ressemblerait à ceci:

Géniteur:

 MPI_Comm_spawn( argv[0], MPI_ARGV_NULL, np, MPI_INFO_NULL, 0, MPI_COMM_SELF, &intercomm, MPI_ERRCODES_IGNORE ); MPI_Intercomm_merge(intercomm, 0, &intracomm); 

Spawnee:

 MPI_Intercomm_merge(parentcomm, 1, &intracomm); 

Après cela, vous pouvez continuer à utiliser intracomm (ou ce que vous voulez appeler) comme s’il s’agissait d’un intracommunicateur ordinaire. Dans ce cas, les processus en cours de génération auraient les rangs les moins élevés et les nouveaux processus, les niveaux les plus élevés, mais vous pouvez également le modifier avec le deuxième argument.

Les appels de communication collectifs tels que Bcast() nécessitent un intracommunicateur: vous essayez d’utiliser un intercommunicateur ( intercomm et parentcomm ). Vous devrez utiliser les méthodes de création de groupe pour définir un groupe englobant le processus parent et tous les processus enfants, puis créer un nouvel intracommunicateur sur ce groupe.