2012-04-02 7 views
8

(domanda principiante) Sto provando a generare i processi dinamicamente usando MPI_Comm_Spawn e poi trasmettere un messaggio ai processi figli, ma il programma si ferma nella trasmissione dal processo di root a i bambini. Sto seguendo la documentazione da http://www.mpi-forum.org/docs/docs.html ma non riesco a farlo funzionare. Qualcuno può aiutarmi per favore?MPI Spawn: processo radice non comunica ai processi figlio

#include <stdio.h> 
#include <mpi.h> 

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

Non so se è importante, ma sto usando Ubuntu 11.10 e Hidra Process Manager.

risposta

-1

Le chiamate di comunicazione collettiva come Bcast() richiedono un intracomunicatore: si sta tentando di utilizzare un intercomunicatore (sia intercomm e parentcomm). Dovrai utilizzare i metodi di creazione dei gruppi per definire un gruppo che comprenda il processo principale e tutti i processi figli, quindi creare un nuovo intracomunicatore su quel gruppo.

+0

Questo non è accurato come @bfroehle sottolinea. È possibile effettuare una chiamata collettiva con un intercomunicatore. Devi solo fare attenzione e leggere le specifiche separate. –

3

Come sottolineato da @suszterpatt, si sta lavorando con un "Intercomunicatore" (non un "Intracomunicatore"). Sapendo questo e guardando MPI_Bcast, vediamo:

Se comm è un intercommunicator, poi la chiamata coinvolge tutti i processi nel intercommunicator, ma con un gruppo (gruppo A) che definisce il processo di root. Tutti i processi nell'altro gruppo (gruppo B) passano lo stesso valore nell'argomento root, che è il rango della radice nel gruppo A. La radice passa il valore MPI_ROOT nella radice. Tutti gli altri processi nel gruppo A passano il valore MPI_PROC_NULL nella radice. I dati vengono trasmessi dalla radice a tutti i processi nel gruppo B. Gli argomenti del buffer di ricezione dei processi nel gruppo B devono essere coerenti con l'argomento del buffer di invio della radice.

Questo significa che è necessario sostituire solo la chiamata di trasmissione nel genitore con:

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

Alcuni altri bug:

  • la verifica del numero di argomenti dovrebbe essere argc > 1.
  • MPI_Comm_size(intercomm, &size) restituirà 1. Ti consigliamo di utilizzare MPI_Comm_remote_size(intercomm, &size) invece.
2

Se non si vuole fare con un intercommunicator dopo aver deposto le uova i processi figlio, è possibile utilizzare per creare un MPI_Intercomm_merge intracommunicator dal intercommunicator. In sostanza, sarebbe simile a questa:

Spawner:

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

Dopo di che, si può continuare a utilizzare intracomm (o quello che volete chiamarlo), come se era un normale intracomunicatore. In questo caso, i processi di spawning avranno ranghi di ordine basso e i nuovi processi avranno ranghi più alti, ma è possibile modificarli anche con il secondo argomento.

+0

Come funziona esattamente? Ho appena postato una relativa [domanda] (http: // StackOverflow.it/questions/20755060/can-a-spawned-process-communicate-with-the-main-mpi-communicator) e questa dichiarazione di unione potrebbe funzionare ma sono confuso riguardo a "inter", "intra" nelle diverse parti del codice. – user989762

Problemi correlati