#include #include #include "mpi.h" #define NUM_SLAVES 2 /* create NUM_SLAVES processes */ int main (int argc, char *argv[]) { MPI_Comm COMM_ALL_PROCESSES, /* intra-communicator */ COMM_CHILD_PROCESSES, /* inter-communicator */ COMM_PARENT_PROCESSES; /* inter-communicator */ int ntasks_world, /* # of tasks in MPI_COMM_WORLD */ ntasks_local, /* COMM_CHILD_PROCESSES local */ ntasks_remote, /* COMM_CHILD_PROCESSES remote */ ntasks_all, /* tasks in COMM_ALL_PROCESSES */ mytid_world, /* my task id in MPI_COMM_WORLD */ mytid_all, /* id in COMM_ALL_PROCESSES */ namelen; /* length of processor name */ char processor_name[MPI_MAX_PROCESSOR_NAME]; MPI_Init (&argc, &argv); MPI_Comm_rank (MPI_COMM_WORLD, &mytid_world); /* At first we must decide if this program is executed from a parent * or child process because only a parent is allowed to spawn child * processes (otherwise the child process with rank 0 would spawn * itself child processes and so on). "MPI_Comm_get_parent ()" * returns the parent inter-communicator for a spawned MPI rank and * MPI_COMM_NULL if the process wasn't spawned, i.e. it was started * statically via "mpiexec" on the command line. */ MPI_Comm_get_parent (&COMM_PARENT_PROCESSES); if (COMM_PARENT_PROCESSES == MPI_COMM_NULL) { /* All parent processes must call "MPI_Comm_spawn ()" but only * the root process (in our case the process with rank 0) will * spawn child processes. All other processes of the * intra-communicator (in our case MPI_COMM_WORLD) will ignore * the values of all arguments before the "root" parameter. */ if (mytid_world == 0) { printf ("Parent process 0: I create %d slave processes\n", NUM_SLAVES); } MPI_Comm_spawn (argv[0], MPI_ARGV_NULL, NUM_SLAVES, MPI_INFO_NULL, 0, MPI_COMM_WORLD, &COMM_CHILD_PROCESSES, MPI_ERRCODES_IGNORE); } /* Merge all processes into one intra-communicator. The "high" flag * determines the order of the processes in the intra-communicator. * If parent and child processes use the same flag the order may * be arbitray otherwise the processes with "high == 0" will have * a lower rank than the processes with "high == 1". */ if (COMM_PARENT_PROCESSES == MPI_COMM_NULL) { /* parent processes */ MPI_Intercomm_merge (COMM_CHILD_PROCESSES, 0, &COMM_ALL_PROCESSES); } else { /* spawned child processes */ MPI_Intercomm_merge (COMM_PARENT_PROCESSES, 1, &COMM_ALL_PROCESSES); } MPI_Comm_size (MPI_COMM_WORLD, &ntasks_world); MPI_Comm_size (COMM_ALL_PROCESSES, &ntasks_all); MPI_Comm_rank (COMM_ALL_PROCESSES, &mytid_all); MPI_Get_processor_name (processor_name, &namelen); /* With the following printf-statement every process executing this * code will print some lines on the display. It may happen that the * lines will get mixed up because the display is a critical section. * In general only one process (mostly the process with rank 0) will * print on the display and all other processes will send their * messages to this process. Nevertheless for debugging purposes * (or to demonstrate that it is possible) it may be useful if every * process prints itself. */ if (COMM_PARENT_PROCESSES == MPI_COMM_NULL) { MPI_Comm_size (COMM_CHILD_PROCESSES, &ntasks_local); MPI_Comm_remote_size (COMM_CHILD_PROCESSES, &ntasks_remote); printf ("\nParent process %d running on %s\n" " MPI_COMM_WORLD ntasks: %d\n" " COMM_CHILD_PROCESSES ntasks_local: %d\n" " COMM_CHILD_PROCESSES ntasks_remote: %d\n" " COMM_ALL_PROCESSES ntasks: %d\n" " mytid in COMM_ALL_PROCESSES: %d\n", mytid_world, processor_name, ntasks_world, ntasks_local, ntasks_remote, ntasks_all, mytid_all); } else { printf ("\nChild process %d running on %s\n" " MPI_COMM_WORLD ntasks: %d\n" " COMM_ALL_PROCESSES ntasks: %d\n" " mytid in COMM_ALL_PROCESSES: %d\n", mytid_world, processor_name, ntasks_world, ntasks_all, mytid_all); } MPI_Finalize (); return EXIT_SUCCESS; }