#include <stdio.h> #include "mpi.h" #include "ic_nxtval.h" #define ICTAG 0 int MPE_Counter_create_ic(MPI_Comm oldcomm, MPI_Comm *smaller_comm, MPI_Comm *counter_comm) { int counter = 0, message, done = 0, myid, numprocs, server; int color, remote_leader_rank; MPI_Status status; MPI_Comm oldcommdup, splitcomm; MPI_Comm_dup(oldcomm, &oldcommdup); MPI_Comm_size(oldcommdup, &numprocs); MPI_Comm_rank(oldcommdup, &myid); server = numprocs-1; /* last proc is server */ color = (myid == server); /* split into server and rest */ MPI_Comm_split(oldcomm, color, myid, &splitcomm); /* build intercommunicator using bridge w/ oldcommdup */ if(!color) { /* I am not the server */ /* 1) the non-server leader process is chosen to have rank "0" in the peer comm. oldcommdup != rank of server guaranteed that this leader "0" has rank "0" in both oldcommdup and in this splitcomm too, by virtue of MPI_Comm_split 2) server has rank "server" in oldcommdup */ remote_leader_rank = server; /* server rank, oldcommdup */ *smaller_comm = splitcomm; /* return new, smaller world */ } else { remote_leader_rank = 0; /* non-server leader, oldcommdup */ *smaller_comm = MPI_COMM_NULL; } MPI_Intercomm_create(splitcomm, 0, oldcommdup, remote_leader_rank, ICTAG, counter_comm); MPI_Comm_free(&oldcommdup); /* not needed after Intercomm_create */ if (myid == server) { /* I am the server */ MPI_Comm_free(&splitcomm); while (!done) { MPI_Recv(&message, 1, MPI_INT, MPI_ANY_SOURCE, MPI_ANY_TAG, *counter_comm, &status); if (status.MPI_TAG == REQUEST) { MPI_Send(&counter, 1, MPI_INT, status.MPI_SOURCE, VALUE, *counter_comm); counter++; } else if (status.MPI_TAG == GOAWAY) { done = 1; } else { fprintf(stderr, "bad tag %d sent to MPE counter\n", status.MPI_TAG); MPI_Abort(*counter_comm, 1); } } MPI_Comm_free(counter_comm); } return 0; }