int MPI_Comm_split(MPI_Comm comm, int colour, int key, MPI_Comm *newcomm)
{
int *p, *p2, *procs;
MPI_Group oldgroup, newgroup;
IMPI_Uint8 newcid, maxcid;
/* create a new context ID */
MPI_Allreduce(&IMPI_max_cid, &maxcid, 1, IMPI_UINT8, MPI_MAX, comm);
if (maxcid == IMPI_UINT8_MAX) {
error out of contexts;
}
newcid = maxcid + 1;
IMPI_max_cid = maxcid + 1;
/* create an array of process information for doing the split */
MPI_Comm_size(comm, &nprocs);
procs = (int *) malloc(3 * nprocs * sizeof(int));
/* gather all process information at all processes */
p = &procs[3 * myrank];
p[0] = colour;
p[1] = key;
p[2] = myrank;
MPI_Allgather(p, 3, MPI_INT, procs, 3, MPI_INT, comm);
/* processes with undefined colour can stop here */
if (colour == MPI_UNDEFINED) {
*newcomm = MPI_COMM_NULL;
return(MPI_SUCCESS);
}
sort the array of process information in ascending order by
colour, then by key if colours are the same, then by rank if colour
and key are the same;
/* locate and count the # of processes having my colour */
myprocs = 0;
for (i = 0, p = procs; (i < nprocs) && (*p != colour); ++i, p += 3);
myprocs = p;
mynprocs = 1;
for (++i, p += 3; (i < nprocs) && (*p == colour); ++i, p += 3) {
++mynprocs;
}
/* compact the old ranks of my old group in the array */
p = myprocs;
p2 = myprocs + 2;
for (i = 0; i < mynprocs; ++i, ++p, p2 += 3) *p = *p2;
/* create the new group */
MPI_Comm_group(comm, &oldgroup);
MPI_Group_incl(oldgroup, mynprocs, myprocs, &newgroup);
MPI_Group_free(&oldgroup);
create a new communicator newcomm with context ID newcid
and group newgroup;
return(MPI_SUCCESS);
}