next up previous contents
Next: Comm_split Up: Collectives Previous: Comm_free

Comm_dup

int MPI_Comm_dup(MPI_Comm comm, MPI_Comm *newcomm)
{
  MPI_Status  status;
  IMPI_Uint8  newcid, maxcid;
  MPI_Group   group;
  MPI_Comm    localcomm, tmpcomm;
  int         myrank, rgsize;

  MPI_Comm_rank(comm, &myrank);

  /* create a new context ID */
  if (comm is an intra-communicator) {
    MPI_Allreduce(&IMPI_max_cid, &maxcid, 1, IMPI_UINT8, MPI_MAX, comm);
  } else {
    /* Rank 0 processes are the leaders of their local group.  
     * Each leader finds the max context ID of all remote group
     * processes (excluding their leader).  The leaders then swap the 
     * information and broadcast to the remote group.
     * Note: this is a criss-cross effect, processes talk to the remote
     * leader. 
     */
    MPI_Comm_remote_size(comm, &rgsize);

    if (myrank == 0) {
      maxcid = IMPI_max_cid;

      /* find max context ID of remote non-leader processes */
      for (i = 1; i < rgsize; i++) {
        MPI_Recv(&newcid, 1, IMPI_UINT8, i, IMPI_DUP_TAG, comm, &status);
        if (newcid > maxcid) maxcid = newcid;
      }

      /* swap context ID with remote leader */
      MPI_Sendrecv(&maxcid, 1, IMPI_UINT8, 0, IMPI_DUP_TAG,
                   &newcid, 1, IMPI_UINT8, 0, IMPI_DUP_TAG, 
                   comm, &status);

      if (newcid > maxcid) maxcid = newcid;

      /* broadcast context ID to remote non-leader processes */
      for (i = 1; i < rgsize; i++) {
        MPI_Send(&maxcid, 1, IMPI_UINT8, i, IMPI_DUP_TAG, comm);
      }
    }
    else {
      /* non-leader */
      MPI_Send(&maxcid, 1, IMPI_UINT8, 0, MPI_DUP_TAG, comm);
      MPI_Recv(&maxcid, 1, IMPI_UINT8, 0, MPI_DUP_TAG, comm, &status);
    }
  }

  if (maxcid == IMPI_UINT8_MAX) {
    error out of contexts;
  }

  newcid = maxcid + 1;
  IMPI_max_cid = maxcid + 1;

  build a new communicator newcomm with the same groups as comm and
    with context newcid;

  return(MPI_SUCCESS);
}



IMPI Protocol ver 0.0
DRAFT March 22, 1999