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

Intercomm_merge

int MPI_Intercomm_merge(MPI_Comm comm, int high, MPI_Comm *newcomm)
{
  MPI_Status status;
  MPI_Group g1, g2, newgroup;
  IMPI_Uint8 newcid, maxcid;
  IMPI_Uint8 inmsg[2], outmsg[2];
  int myrank, rgsize;

  /* Create the new context ID. 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) and their "high" setting.
   * 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_rank(comm, &myrank);
  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(inmsg, 1, IMPI_UINT8, i, IMPI_MERGE_TAG, comm, &status);
      if (inmsg[0] > maxcid) maxcid = inmsg[0];
    }

    /* swap context ID and high value with remote leader */
    outmsg[0] = maxcid;
    outmsg[1] = high;

    MPI_Sendrecv(outmsg, 2, IMPI_UINT8, 0, IMPI_MERGE_TAG,
                 inmsg, 2, IMPI_UINT8, 0, IMPI_MERGE_TAG, comm, &status);

    if (inmsg[0] > maxcid) maxcid = inmsg[0];

    rhigh = inmsg[1];

    /* broadcast context ID and local high to remote non-leader processes */
    outmsg[0] = maxcid;
    outmsg[1] = high;

    for (i = 1; i < rgsize; i++) {
      MPI_Send(outmsg, 2, IMPI_UINT8, i, IMPI_MERGE_TAG, comm);
    }
  }
  else {
    /* non-leader */
    MPI_Send(&maxcid, 1, IMPI_UINT8, 0, MPI_MERGE_TAG, comm);
    MPI_Recv(inmsg, 2, IMPI_UINT8, 0, MPI_MERGE_TAG, comm, &status);

    maxcid = inmsg[0];
    rhigh = inmsg[1];
  }

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

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

  /* All procs know the "high" for local and remote groups and 
	 * the context ID. Create the properly ordered union group.  
	 * In case of equal high values, the group that has the leader 
   * with the lowest rank in MPI_COMM_WORLD goes first. 
	 */
  if (high && (!rhigh)) {
    MPI_Comm_remote_group(comm, &g1);
    MPI_Comm_group(comm, &g2);
  } else if ((!high) && rhigh) {
    MPI_Comm_group(comm, &g1);
    MPI_Comm_remote_group(comm, &g2);
  } else if ((rank in MPI_COMM_WORLD of rank 0 in local group)
         < (rank in MPI_COMM_WORLD of rank 0 in remote group)) {
    MPI_Comm_group(comm, &g1);
    MPI_Comm_remote_group(comm, &g2);
  } else {
    MPI_Comm_remote_group(comm, &g1);
    MPI_Comm_group(comm, &g2);
  }

  MPI_Group_union(g1, g2, &newgroup);

  create a new intra-communicator newcomm with context ID newcid and
    group newgroup;

  return(MPI_SUCCESS);
}



IMPI Protocol ver 0.0
DRAFT March 22, 1999