next up previous contents
Next: Intercomm_create Up: Collectives Previous: Comm_dup

Comm_split

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



IMPI Protocol ver 0.0
DRAFT March 22, 1999