2012-04-02 75 views
8

(Pregunta inicial) Estoy intentando generar procesos dinámicamente usando MPI_Comm_Spawn y luego transmitir un mensaje a los procesos hijos, pero el programa se detiene en la transmisión desde el proceso raíz hasta los niños. Estoy siguiendo la documentación desde http://www.mpi-forum.org/docs/docs.html pero no puedo hacer que funcione. puede alguien ayudarme por favor?MPI Spawn: el proceso raíz no se comunica con procesos secundarios

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

No sé si es importante, pero estoy usando ubuntu 11.10 e Hidra Process Manager.

Respuesta

-1

Las llamadas de comunicación colectiva como Bcast() requieren un intracomunicador: está intentando utilizar un intercomunicador (ambos intercomm y parentcomm). Tendrá que usar los métodos de creación de grupos para definir un grupo que abarque el proceso principal y todos los procesos secundarios, luego cree un nuevo intracomunicador sobre ese grupo.

+0

Eso no es preciso como señala @bfroehle. Puede hacer una llamada colectiva con un intercomunicador. Solo debe tener cuidado al respecto y leer las especificaciones por separado. –

3

Como señaló @suszterpatt, está trabajando con un "Intercomunicador" (no un "Intracomunicador"). Sabiendo esto y mirando a MPI_Bcast, vemos:

Si comm es un intercomunicador, entonces la llamada involucra a todos los procesos en el intercomunicador, pero con un grupo (grupo A) que define el proceso de raíz. Todos los procesos en el otro grupo (grupo B) pasan el mismo valor en el argumento raíz, que es el rango de la raíz en el grupo A. La raíz pasa el valor MPI_ROOT en la raíz. Todos los otros procesos en el grupo A pasan el valor MPI_PROC_NULL en la raíz. Los datos se transmiten desde la raíz a todos los procesos en el grupo B. Los argumentos del búfer de recepción de los procesos en el grupo B deben ser consistentes con el argumento de búfer de envío de la raíz.

Esto significa que sólo se necesita reemplazar la llamada de difusión en la matriz con:

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

Algunos otros insectos:

  • La verificación del número de argumentos debe ser argc > 1.
  • MPI_Comm_size(intercomm, &size) devolverá 1. En su lugar, querrá usar MPI_Comm_remote_size(intercomm, &size).
2

Si no quiere tratar con un intercomunicador después de que haya dado lugar a los procesos secundarios, se puede utilizar para crear un MPI_Intercomm_merge intracommunicator de su intercomunicador. En esencia, se vería así:

análisis reproductor:

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

Después de eso, se puede seguir utilizando intracomm (o lo que usted quiera llamarlo) como si era un intracomunicador regular. En este caso, los procesos de desove tendrían los rangos de orden bajo y los nuevos procesos tendrían los rangos más altos, pero también puede modificar eso con el segundo argumento.

+0

¿Cómo funcionaría esto exactamente? Acabo de publicar una [pregunta] relacionada (http: // stackoverflow.com/questions/20755060/can-a-spawned-process-communicate-with-the-main-mpi-communicator) y esta declaración de combinación podría funcionar, pero estoy confundido acerca de "inter", "intra" en las diferentes partes del código. – user989762

Cuestiones relacionadas