[mpich-commits] [mpich] MPICH primary repository branch, master, updated. v3.2b3-255-g8976a2c

Service Account noreply at mpich.org
Thu Jul 16 13:02:54 CDT 2015


This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "MPICH primary repository".

The branch, master has been updated
       via  8976a2cb117ee3e902399f47a11d0421e37e753c (commit)
       via  b14c5f968ecd132ada7d961eed5406413648f452 (commit)
       via  cb4c8e78f4f4d57624a627d919b084e2a773aea9 (commit)
       via  f8fd3d81ae217b2fbf3d3a2221f7c64d295ceef4 (commit)
      from  92fb8a07f0192a7cfa695518892afa6c2d1a2997 (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
http://git.mpich.org/mpich.git/commitdiff/8976a2cb117ee3e902399f47a11d0421e37e753c

commit 8976a2cb117ee3e902399f47a11d0421e37e753c
Author: Pavan Balaji <balaji at anl.gov>
Date:   Thu Jul 16 12:37:16 2015 -0500

    Move VCR-specific content to the device.
    
    The MPI-layer should be scalable and not rely on O(P) data structures,
    such as VC arrays, except where necessitated by the MPI standard.  The
    device can use such non-scalable data structures if it desires, but
    they should not be forced up on more scalable devices.
    
    Signed-off-by: Charles J Archer <charles.j.archer at intel.com>

diff --git a/src/include/mpiimpl.h b/src/include/mpiimpl.h
index e539ce7..cab4045 100644
--- a/src/include/mpiimpl.h
+++ b/src/include/mpiimpl.h
@@ -1106,7 +1106,6 @@ extern MPID_Group * const MPID_Group_empty;
      do { MPIU_Object_release_ref( _group, _inuse ); } while (0)
 
 void MPIR_Group_setup_lpid_list( MPID_Group * );
-int MPIR_GroupCheckVCRSubset( MPID_Group *group_ptr, int vsize, MPID_VCR *vcr );
 
 /* ------------------------------------------------------------------------- */
 
@@ -1128,6 +1127,45 @@ typedef enum MPID_Comm_hierarchy_kind_t {
 } MPID_Comm_hierarchy_kind_t;
 /* Communicators */
 
+typedef enum {
+    MPIR_COMM_MAP_DUP,
+    MPIR_COMM_MAP_IRREGULAR
+} MPIR_Comm_map_type_t;
+
+/* direction of mapping: local to local, local to remote, remote to
+ * local, remote to remote */
+typedef enum {
+    MPIR_COMM_MAP_DIR_L2L,
+    MPIR_COMM_MAP_DIR_L2R,
+    MPIR_COMM_MAP_DIR_R2L,
+    MPIR_COMM_MAP_DIR_R2R
+} MPIR_Comm_map_dir_t;
+
+typedef struct MPIR_Comm_map {
+    MPIR_Comm_map_type_t type;
+
+    struct MPID_Comm *src_comm;
+
+    /* mapping direction for intercomms, which contain local and
+     * remote groups */
+    MPIR_Comm_map_dir_t dir;
+
+    /* only valid for irregular map type */
+    int src_mapping_size;
+    int *src_mapping;
+    int free_mapping;       /* we allocated the mapping */
+
+    struct MPIR_Comm_map *next;
+} MPIR_Comm_map_t;
+
+int MPIR_Comm_map_irregular(struct MPID_Comm *newcomm, struct MPID_Comm *src_comm,
+                            int *src_mapping, int src_mapping_size,
+                            MPIR_Comm_map_dir_t dir,
+                            MPIR_Comm_map_t **map);
+int MPIR_Comm_map_dup(struct MPID_Comm *newcomm, struct MPID_Comm *src_comm,
+                      MPIR_Comm_map_dir_t dir);
+int MPIR_Comm_map_free(struct MPID_Comm *comm);
+
 /*S
   MPID_Comm - Description of the Communicator data structure
 
@@ -1195,12 +1233,6 @@ typedef struct MPID_Comm {
     MPIR_Context_id_t recvcontext_id; /* Send context id.  See notes */
     int           remote_size;   /* Value of MPI_Comm_(remote)_size */
     int           rank;          /* Value of MPI_Comm_rank */
-    MPID_VCRT     vcrt;          /* virtual connecton reference table */
-    MPID_VCR *    vcr;           /* alias to the array of virtual connections
-				    in vcrt */
-    MPID_VCRT     local_vcrt;    /* local virtual connecton reference table */
-    MPID_VCR *    local_vcr;     /* alias to the array of local virtual
-				    connections in local vcrt */
     MPID_Attribute *attributes;  /* List of attributes */
     int           local_size;    /* Value of MPI_Comm_size for local group */
     MPID_Group   *local_group,   /* Groups in communicator. */
@@ -1258,6 +1290,12 @@ typedef struct MPID_Comm {
     hcoll_comm_priv_t hcoll_priv;
 #endif /* HAVE_LIBHCOLL */
 
+    /* the mapper is temporarily filled out in order to allow the
+     * device to setup its network addresses.  it will be freed after
+     * the device has initialized the comm. */
+    MPIR_Comm_map_t *mapper_head;
+    MPIR_Comm_map_t *mapper_tail;
+
   /* Other, device-specific information */
 #ifdef MPID_DEV_COMM_DECL
     MPID_DEV_COMM_DECL
@@ -1266,7 +1304,7 @@ typedef struct MPID_Comm {
 extern MPIU_Object_alloc_t MPID_Comm_mem;
 
 /* this function should not be called by normal code! */
-int MPIR_Comm_delete_internal(MPID_Comm * comm_ptr, int isDisconnect);
+int MPIR_Comm_delete_internal(MPID_Comm * comm_ptr);
 
 #define MPIR_Comm_add_ref(_comm) \
     do { MPIU_Object_add_ref((_comm)); } while (0)
@@ -1285,7 +1323,7 @@ int MPIR_Comm_delete_internal(MPID_Comm * comm_ptr, int isDisconnect);
 #define FUNCNAME MPIR_Comm_release
 #undef FCNAME
 #define FCNAME MPIU_QUOTE(FUNCNAME)
-static inline int MPIR_Comm_release(MPID_Comm * comm_ptr, int isDisconnect)
+static inline int MPIR_Comm_release(MPID_Comm * comm_ptr)
 {
     int mpi_errno = MPI_SUCCESS;
     int in_use;
@@ -1294,7 +1332,7 @@ static inline int MPIR_Comm_release(MPID_Comm * comm_ptr, int isDisconnect)
     if (unlikely(!in_use)) {
         /* the following routine should only be called by this function and its
          * "_always" variant. */
-        mpi_errno = MPIR_Comm_delete_internal(comm_ptr, isDisconnect);
+        mpi_errno = MPIR_Comm_delete_internal(comm_ptr);
         /* not ERR_POPing here to permit simpler inlining.  Our caller will
          * still report the error from the comm_delete level. */
     }
@@ -1307,7 +1345,7 @@ static inline int MPIR_Comm_release(MPID_Comm * comm_ptr, int isDisconnect)
 /* MPIR_Comm_release_always is the same as MPIR_Comm_release except it uses
    MPIR_Comm_release_ref_always instead.
 */
-int MPIR_Comm_release_always(MPID_Comm *comm_ptr, int isDisconnect);
+int MPIR_Comm_release_always(MPID_Comm *comm_ptr);
 
 /* applies the specified info chain to the specified communicator */
 int MPIR_Comm_apply_hints(MPID_Comm *comm_ptr, MPID_Info *info_ptr);
@@ -3692,45 +3730,9 @@ int MPID_Get_universe_size(int  * universe_size);
 #define MPIR_UNIVERSE_SIZE_NOT_SET -1
 #define MPIR_UNIVERSE_SIZE_NOT_AVAILABLE -2
 
-/*
- * FIXME: VCs should not be exposed to the top layer, which implies that these routines should not be exposed either.  Instead,
- * the creation, duplication and destruction of communicator objects should be communicated to the device, allowing the device to
- * manage the underlying connections in a way that is appropriate (and efficient).
- */
-
-/*@
-  MPID_VCRT_Create - Create a virtual connection reference table
-  @*/
-int MPID_VCRT_Create(int size, MPID_VCRT *vcrt_ptr);
-
-/*@
-  MPID_VCRT_Add_ref - Add a reference to a VCRT
-  @*/
-int MPID_VCRT_Add_ref(MPID_VCRT vcrt);
-
-/*@
-  MPID_VCRT_Release - Release a reference to a VCRT
-  
-  Notes:
-  The 'isDisconnect' argument allows this routine to handle the special
-  case of 'MPI_Comm_disconnect', which needs to take special action
-  if all references to a VC are removed.
-  @*/
-int MPID_VCRT_Release(MPID_VCRT vcrt, int isDisconnect);
-
-/*@
-  MPID_VCRT_Get_ptr - 
-  @*/
-int MPID_VCRT_Get_ptr(MPID_VCRT vcrt, MPID_VCR **vc_pptr);
-
-/*@
-  MPID_VCR_Dup - Create a duplicate reference to a virtual connection
-  @*/
-int MPID_VCR_Dup(MPID_VCR orig_vcr, MPID_VCR * new_vcr);
-
 /*@
-   MPID_VCR_Get_lpid - Get the local process id that corresponds to a 
-   virtual connection reference.
+   MPID_Comm_get_lpid - Get the local process id that corresponds to a
+   comm rank.
 
    Notes:
    The local process ids are described elsewhere.  Basically, they are
@@ -3738,7 +3740,7 @@ int MPID_VCR_Dup(MPID_VCR orig_vcr, MPID_VCR * new_vcr);
    to which it is connected.  These are local process ids because different
    processes may use different ids to identify the same target process
   @*/
-int MPID_VCR_Get_lpid(MPID_VCR vcr, int * lpid_ptr);
+int MPID_Comm_get_lpid(MPID_Comm *comm_ptr, int idx, int * lpid_ptr, MPIU_BOOL is_remote);
 
 /* prototypes and declarations for the MPID_Sched interface for nonblocking
  * collectives */
@@ -4078,13 +4080,15 @@ int MPIR_Comm_create_group(MPID_Comm * comm_ptr, MPID_Group * group_ptr, int tag
 /* comm_create helper functions, used by both comm_create and comm_create_group */
 int MPIR_Comm_create_calculate_mapping(MPID_Group  *group_ptr,
                                        MPID_Comm   *comm_ptr,
-                                       MPID_VCR   **mapping_vcr_out,
-                                       int        **mapping_out);
-int MPIR_Comm_create_create_and_map_vcrt(int n,
-                                         int *mapping,
-                                         MPID_VCR *mapping_vcr,
-                                         MPID_VCRT *out_vcrt,
-                                         MPID_VCR **out_vcr);
+                                       int        **mapping_out,
+                                       MPID_Comm **mapping_comm);
+
+int MPIR_Comm_create_map(int local_n,
+                         int remote_n,
+                         int *local_mapping,
+                         int *remote_mapping,
+                         MPID_Comm *mapping_comm,
+                         MPID_Comm *newcomm);
 
 /* implements the logic for MPI_Comm_create for intracommunicators only */
 int MPIR_Comm_create_intra(MPID_Comm *comm_ptr, MPID_Group *group_ptr,
@@ -4232,6 +4236,9 @@ int MPIR_Iexscan(const void *sendbuf, void *recvbuf, int count, MPI_Datatype dat
 int MPIR_Ialltoallw_intra(const void *sendbuf, const int *sendcounts, const int *sdispls, const MPI_Datatype *sendtypes, void *recvbuf, const int *recvcounts, const int *rdispls, const MPI_Datatype *recvtypes, MPID_Comm *comm_ptr, MPID_Sched_t s);
 int MPIR_Ialltoallw_inter(const void *sendbuf, const int *sendcounts, const int *sdispls, const MPI_Datatype *sendtypes, void *recvbuf, const int *recvcounts, const int *rdispls, const MPI_Datatype *recvtypes, MPID_Comm *comm_ptr, MPID_Sched_t s);
 
+/* group functionality */
+int MPIR_Group_check_subset(MPID_Group * group_ptr, MPID_Comm * comm_ptr);
+
 /* begin impl functions for MPI_T (MPI_T_ right now) */
 int MPIR_T_cvar_handle_alloc_impl(int cvar_index, void *obj_handle, MPI_T_cvar_handle *handle, int *count);
 int MPIR_T_cvar_read_impl(MPI_T_cvar_handle handle, void *buf);
diff --git a/src/mpi/comm/comm_create.c b/src/mpi/comm/comm_create.c
index 87f31c9..23c109d 100644
--- a/src/mpi/comm/comm_create.c
+++ b/src/mpi/comm/comm_create.c
@@ -32,7 +32,7 @@ PMPI_LOCAL int MPIR_Comm_create_inter(MPID_Comm *comm_ptr, MPID_Group *group_ptr
 #define MPI_Comm_create PMPI_Comm_create
 
 /* This function allocates and calculates an array (*mapping_out) such that
- * (*mapping_out)[i] is the rank in (*mapping_vcr_out) corresponding to local
+ * (*mapping_out)[i] is the rank in (*mapping_comm) corresponding to local
  * rank i in the given group_ptr.
  *
  * Ownership of the (*mapping_out) array is transferred to the caller who is
@@ -43,40 +43,21 @@ PMPI_LOCAL int MPIR_Comm_create_inter(MPID_Comm *comm_ptr, MPID_Group *group_ptr
 #define FCNAME MPIU_QUOTE(FUNCNAME)
 int MPIR_Comm_create_calculate_mapping(MPID_Group  *group_ptr,
                                        MPID_Comm   *comm_ptr,
-                                       MPID_VCR   **mapping_vcr_out,
-                                       int        **mapping_out)
+                                       int        **mapping_out,
+                                       MPID_Comm **mapping_comm)
 {
     int mpi_errno = MPI_SUCCESS;
     int subsetOfWorld = 0;
     int i, j;
     int n;
     int *mapping=0;
-    int vcr_size;
-    MPID_VCR *vcr;
     MPIU_CHKPMEM_DECL(1);
     MPID_MPI_STATE_DECL(MPID_STATE_MPIR_COMM_CREATE_CALCULATE_MAPPING);
 
     MPID_MPI_FUNC_ENTER(MPID_STATE_MPIR_COMM_CREATE_CALCULATE_MAPPING);
 
     *mapping_out = NULL;
-    *mapping_vcr_out = NULL;
-
-    /* N.B. For intracomms only the comm_ptr->vcr is valid and populated,
-     * however local_size and remote_size are always set to the same value for
-     * intracomms.  For intercomms both are valid and populated, with the
-     * local_vcr holding VCs corresponding to the local_group, local_comm, and
-     * local_size.
-     *
-     * For this mapping calculation we always want the logically local vcr,
-     * regardless of whether it is stored in the "plain" vcr or local_vcr. */
-    if (comm_ptr->comm_kind == MPID_INTERCOMM) {
-        vcr      = comm_ptr->local_vcr;
-        vcr_size = comm_ptr->local_size;
-    }
-    else {
-        vcr      = comm_ptr->vcr;
-        vcr_size = comm_ptr->remote_size;
-    }
+    *mapping_comm = comm_ptr;
 
     n = group_ptr->size;
     MPIU_CHKPMEM_MALLOC(mapping,int*,n*sizeof(int),mpi_errno,"mapping");
@@ -125,15 +106,14 @@ int MPIR_Comm_create_calculate_mapping(MPID_Group  *group_ptr,
         {
             MPID_BEGIN_ERROR_CHECKS;
             {
-                mpi_errno = MPIR_GroupCheckVCRSubset( group_ptr, vcr_size, vcr );
+                mpi_errno = MPIR_Group_check_subset( group_ptr, comm_ptr );
                 if (mpi_errno) MPIU_ERR_POP(mpi_errno);
             }
             MPID_END_ERROR_CHECKS;
         }
 #           endif
-        /* Override the vcr to be used with the mapping array. */
-        vcr = MPIR_Process.comm_world->vcr;
-        vcr_size = MPIR_Process.comm_world->local_size;
+        /* Override the comm to be used with the mapping array. */
+        *mapping_comm = MPIR_Process.comm_world;
     }
     else {
         for (i=0; i<n; i++) {
@@ -141,9 +121,9 @@ int MPIR_Comm_create_calculate_mapping(MPID_Group  *group_ptr,
                that is the ith element of the group */
             /* FIXME : BUBBLE SORT */
             mapping[i] = -1;
-            for (j=0; j<vcr_size; j++) {
+            for (j=0; j<comm_ptr->local_size; j++) {
                 int comm_lpid;
-                MPID_VCR_Get_lpid( vcr[j], &comm_lpid );
+                MPID_Comm_get_lpid( comm_ptr, j, &comm_lpid, MPIU_FALSE );
                 if (comm_lpid == group_ptr->lrank_to_lpid[i].lpid) {
                     mapping[i] = j;
                     break;
@@ -154,11 +134,8 @@ int MPIR_Comm_create_calculate_mapping(MPID_Group  *group_ptr,
         }
     }
 
-    MPIU_Assert(vcr != NULL);
     MPIU_Assert(mapping != NULL);
-    *mapping_vcr_out = vcr;
     *mapping_out     = mapping;
-    MPL_VG_CHECK_MEM_IS_DEFINED(*mapping_vcr_out, vcr_size * sizeof(**mapping_vcr_out));
     MPL_VG_CHECK_MEM_IS_DEFINED(*mapping_out, n * sizeof(**mapping_out));
 
     MPIU_CHKPMEM_COMMIT();
@@ -170,38 +147,37 @@ fn_fail:
     goto fn_exit;
 }
 
-/* This function creates a new VCRT and assigns it to out_vcrt, creates a new
- * vcr and assigns it to out_vcr, and then populates it from the mapping_vcr
- * array according to the rank mapping table provided.
- *
- * mapping[i] is the index in the old vcr of index i in the new vcr */
+/* mapping[i] is equivalent network mapping between the old
+ * communicator and the new communicator.  Index 'i' in the old
+ * communicator has the same network address as 'mapping[i]' in the
+ * new communicator. */
+/* WARNING: local_mapping and remote_mapping are stored in this
+ * function.  The caller is responsible for their storage and will
+ * need to retain them till Comm_commit. */
 #undef FUNCNAME
-#define FUNCNAME MPIR_Comm_create_create_and_map_vcrt
+#define FUNCNAME MPIR_Comm_create_map
 #undef FCNAME
 #define FCNAME MPIU_QUOTE(FUNCNAME)
-int MPIR_Comm_create_create_and_map_vcrt(int         n,
-                                         int        *mapping,
-                                         MPID_VCR   *mapping_vcr,
-                                         MPID_VCRT  *out_vcrt,
-                                         MPID_VCR  **out_vcr)
+int MPIR_Comm_create_map(int         local_n,
+                         int         remote_n,
+                         int        *local_mapping,
+                         int        *remote_mapping,
+                         MPID_Comm  *mapping_comm,
+                         MPID_Comm  *newcomm)
 {
     int mpi_errno = MPI_SUCCESS;
-    int i;
-    MPID_VCR *vcr = NULL;
-
-    MPID_VCRT_Create(n, out_vcrt);
-    MPID_VCRT_Get_ptr(*out_vcrt, out_vcr);
-    vcr = *out_vcr;
-    for (i=0; i<n; i++) {
-        MPIU_DBG_MSG_FMT(COMM,VERBOSE,
-                         (MPIU_DBG_FDEST, "dupping from mapping_vcr=%p rank=%d into new_rank=%d/%d in new_vcr=%p",
-                          mapping_vcr, mapping[i], i, n, vcr));
-        mpi_errno = MPID_VCR_Dup(mapping_vcr[mapping[i]], &vcr[i]);
-        if (mpi_errno) MPIU_ERR_POP(mpi_errno);
+
+    MPIR_Comm_map_irregular(newcomm, mapping_comm, local_mapping,
+                            local_n, MPIR_COMM_MAP_DIR_L2L, NULL);
+    if (mapping_comm->comm_kind == MPID_INTERCOMM) {
+        MPIR_Comm_map_irregular(newcomm, mapping_comm, remote_mapping,
+                                remote_n, MPIR_COMM_MAP_DIR_R2R, NULL);
     }
 
-fn_fail:
+fn_exit:
     return mpi_errno;
+fn_fail:
+    goto fn_exit;
 }
 
 
@@ -240,10 +216,10 @@ int MPIR_Comm_create_intra(MPID_Comm *comm_ptr, MPID_Group *group_ptr,
     MPIU_Assert(new_context_id != 0);
 
     if (group_ptr->rank != MPI_UNDEFINED) {
-        MPID_VCR *mapping_vcr = NULL;
+        MPID_Comm *mapping_comm = NULL;
 
-        mpi_errno = MPIR_Comm_create_calculate_mapping(group_ptr, comm_ptr, 
-						       &mapping_vcr, &mapping);
+        mpi_errno = MPIR_Comm_create_calculate_mapping(group_ptr, comm_ptr,
+                                                       &mapping, &mapping_comm);
         if (mpi_errno) MPIU_ERR_POP(mpi_errno);
 
         /* Get the new communicator structure and context id */
@@ -265,13 +241,13 @@ int MPIR_Comm_create_intra(MPID_Comm *comm_ptr, MPID_Group *group_ptr,
         (*newcomm_ptr)->context_id     = (*newcomm_ptr)->recvcontext_id;
         (*newcomm_ptr)->remote_size    = (*newcomm_ptr)->local_size = n;
 
-        /* Setup the communicator's vc table.  This is for the remote group,
+        /* Setup the communicator's network address mapping.  This is for the remote group,
            which is the same as the local group for intracommunicators */
-        mpi_errno = MPIR_Comm_create_create_and_map_vcrt(n,
-                                                         mapping,
-                                                         mapping_vcr,
-                                                         &((*newcomm_ptr)->vcrt),
-                                                         &((*newcomm_ptr)->vcr));
+        mpi_errno = MPIR_Comm_create_map(n, 0,
+                                         mapping,
+                                         NULL,
+                                         mapping_comm,
+                                         *newcomm_ptr);
         if (mpi_errno) MPIU_ERR_POP(mpi_errno);
 
         mpi_errno = MPIR_Comm_commit(*newcomm_ptr);
@@ -291,7 +267,7 @@ fn_exit:
 fn_fail:
     /* --BEGIN ERROR HANDLING-- */
     if (*newcomm_ptr != NULL) {
-        MPIR_Comm_release(*newcomm_ptr, 0/*isDisconnect*/);
+        MPIR_Comm_release(*newcomm_ptr);
         new_context_id = 0; /* MPIR_Comm_release frees the new ctx id */
     }
     if (new_context_id != 0 && group_ptr->rank != MPI_UNDEFINED) {
@@ -314,10 +290,9 @@ PMPI_LOCAL int MPIR_Comm_create_inter(MPID_Comm *comm_ptr, MPID_Group *group_ptr
     MPIR_Context_id_t new_context_id;
     int *mapping = NULL;
     int *remote_mapping = NULL;
+    MPID_Comm *mapping_comm = NULL;
     int remote_size = -1;
     int rinfo[2];
-    MPID_VCR *mapping_vcr = NULL;
-    MPID_VCR *remote_mapping_vcr = NULL;
     mpir_errflag_t errflag = MPIR_ERR_NONE;
     MPIU_CHKLMEM_DECL(1);
     MPID_MPI_STATE_DECL(MPID_STATE_MPIR_COMM_CREATE_INTER);
@@ -343,10 +318,8 @@ PMPI_LOCAL int MPIR_Comm_create_inter(MPID_Comm *comm_ptr, MPID_Group *group_ptr
     MPIU_Assert(new_context_id != 0);
     MPIU_Assert(new_context_id != comm_ptr->recvcontext_id);
 
-    remote_mapping_vcr = comm_ptr->vcr;
-
     mpi_errno = MPIR_Comm_create_calculate_mapping(group_ptr, comm_ptr, 
-						   &mapping_vcr, &mapping);
+						   &mapping, &mapping_comm);
     if (mpi_errno) MPIU_ERR_POP(mpi_errno);
 
     *newcomm_ptr = NULL;
@@ -371,13 +344,14 @@ PMPI_LOCAL int MPIR_Comm_create_inter(MPID_Comm *comm_ptr, MPID_Group *group_ptr
         (*newcomm_ptr)->is_low_group = comm_ptr->is_low_group;
     }
 
-    /* There is an additional step.  We must communicate the information
-       on the local context id and the group members, given by the ranks
-       so that the remote process can construct the appropriate VCRT
-       First we exchange group sizes and context ids.  Then the
-       ranks in the remote group, from which the remote VCRT can
-       be constructed.  We need to use the "collective" context in the
-       original intercommunicator */
+    /* There is an additional step.  We must communicate the
+       information on the local context id and the group members,
+       given by the ranks so that the remote process can construct the
+       appropriate network address mapping.
+       First we exchange group sizes and context ids.  Then the ranks
+       in the remote group, from which the remote network address
+       mapping can be constructed.  We need to use the "collective"
+       context in the original intercommunicator */
     if (comm_ptr->rank == 0) {
         int info[2];
         info[0] = new_context_id;
@@ -436,22 +410,15 @@ PMPI_LOCAL int MPIR_Comm_create_inter(MPID_Comm *comm_ptr, MPID_Group *group_ptr
     if (group_ptr->rank != MPI_UNDEFINED) {
         (*newcomm_ptr)->remote_size    = remote_size;
         /* Now, everyone has the remote_mapping, and can apply that to
-           the vcr table. */
-
-        /* Setup the communicator's local vc table from the local mapping. */
-        mpi_errno = MPIR_Comm_create_create_and_map_vcrt(group_ptr->size,
-                                                         mapping,
-                                                         mapping_vcr,
-                                                         &((*newcomm_ptr)->local_vcrt),
-                                                         &((*newcomm_ptr)->local_vcr));
-        if (mpi_errno) MPIU_ERR_POP(mpi_errno);
-
-        /* Setup the communicator's vc table.  This is for the remote group */
-        mpi_errno = MPIR_Comm_create_create_and_map_vcrt(remote_size,
-                                                         remote_mapping,
-                                                         remote_mapping_vcr,
-                                                         &((*newcomm_ptr)->vcrt),
-                                                         &((*newcomm_ptr)->vcr));
+           the network address mapping. */
+
+        /* Setup the communicator's network addresses from the local mapping. */
+        mpi_errno = MPIR_Comm_create_map(group_ptr->size,
+                                         remote_size,
+                                         mapping,
+                                         remote_mapping,
+                                         mapping_comm,
+                                         *newcomm_ptr);
         if (mpi_errno) MPIU_ERR_POP(mpi_errno);
 
         mpi_errno = MPIR_Comm_commit(*newcomm_ptr);
@@ -465,7 +432,7 @@ PMPI_LOCAL int MPIR_Comm_create_inter(MPID_Comm *comm_ptr, MPID_Group *group_ptr
              * immediately after the communication above because
              * MPIR_Comm_release won't work correctly with a half-constructed
              * comm. */
-            mpi_errno = MPIR_Comm_release(*newcomm_ptr, /*isDisconnect=*/FALSE);
+            mpi_errno = MPIR_Comm_release(*newcomm_ptr);
             if (mpi_errno) MPIU_ERR_POP(mpi_errno);
             *newcomm_ptr = NULL;
         }
diff --git a/src/mpi/comm/comm_create_group.c b/src/mpi/comm/comm_create_group.c
index 7be2949..b04e02e 100644
--- a/src/mpi/comm/comm_create_group.c
+++ b/src/mpi/comm/comm_create_group.c
@@ -52,7 +52,7 @@ int MPIR_Comm_create_group(MPID_Comm * comm_ptr, MPID_Group * group_ptr, int tag
     /* Create a new communicator from the specified group members */
 
     if (group_ptr->rank != MPI_UNDEFINED) {
-        MPID_VCR *mapping_vcr = NULL;
+        MPID_Comm *mapping_comm = NULL;
 
         /* For this routine, creation of the id is collective over the input
            *group*, so processes not in the group do not participate. */
@@ -62,7 +62,7 @@ int MPIR_Comm_create_group(MPID_Comm * comm_ptr, MPID_Group * group_ptr, int tag
         MPIU_Assert(new_context_id != 0);
 
         mpi_errno = MPIR_Comm_create_calculate_mapping(group_ptr, comm_ptr, 
-                                                       &mapping_vcr, &mapping);
+                                                       &mapping, &mapping_comm);
         if (mpi_errno) MPIU_ERR_POP(mpi_errno);
 
         /* Get the new communicator structure and context id */
@@ -86,11 +86,11 @@ int MPIR_Comm_create_group(MPID_Comm * comm_ptr, MPID_Group * group_ptr, int tag
 
         /* Setup the communicator's vc table.  This is for the remote group,
            which is the same as the local group for intracommunicators */
-        mpi_errno = MPIR_Comm_create_create_and_map_vcrt(n,
-                                                         mapping,
-                                                         mapping_vcr,
-                                                         &((*newcomm_ptr)->vcrt),
-                                                         &((*newcomm_ptr)->vcr));
+        mpi_errno = MPIR_Comm_create_map(n, 0,
+                                         mapping,
+                                         NULL,
+                                         mapping_comm,
+                                         *newcomm_ptr);
         if (mpi_errno) MPIU_ERR_POP(mpi_errno);
 
         mpi_errno = MPIR_Comm_commit(*newcomm_ptr);
@@ -110,7 +110,7 @@ fn_exit:
 fn_fail:
     /* --BEGIN ERROR HANDLING-- */
     if (*newcomm_ptr != NULL) {
-        MPIR_Comm_release(*newcomm_ptr, 0/*isDisconnect*/);
+        MPIR_Comm_release(*newcomm_ptr);
         new_context_id = 0; /* MPIR_Comm_release frees the new ctx id */
     }
     if (new_context_id != 0)
diff --git a/src/mpi/comm/comm_free.c b/src/mpi/comm/comm_free.c
index 9046745..000ee6d 100644
--- a/src/mpi/comm/comm_free.c
+++ b/src/mpi/comm/comm_free.c
@@ -32,7 +32,7 @@ int MPI_Comm_free(MPI_Comm *comm) __attribute__((weak,alias("PMPI_Comm_free")));
 #define FCNAME MPIU_QUOTE(FUNCNAME)
 int MPIR_Comm_free_impl(MPID_Comm * comm_ptr)
 {
-    return MPIR_Comm_release(comm_ptr, 0);
+    return MPIR_Comm_release(comm_ptr);
 }
 #endif
 
diff --git a/src/mpi/comm/comm_group.c b/src/mpi/comm/comm_group.c
index 61b37f4..72fff39 100644
--- a/src/mpi/comm/comm_group.c
+++ b/src/mpi/comm/comm_group.c
@@ -33,7 +33,6 @@ int MPI_Comm_group(MPI_Comm comm, MPI_Group *group) __attribute__((weak,alias("P
 int MPIR_Comm_group_impl(MPID_Comm *comm_ptr, MPID_Group **group_ptr)
 {
     int mpi_errno = MPI_SUCCESS;
-    MPID_VCR   *local_vcr;
     int i, lpid, n;
     int comm_world_size = MPIR_Process.comm_world->local_size;
     MPID_MPI_STATE_DECL(MPID_STATE_MPIR_COMM_GROUP_IMPL);
@@ -46,16 +45,9 @@ int MPIR_Comm_group_impl(MPID_Comm *comm_ptr, MPID_Group **group_ptr)
 	mpi_errno = MPIR_Group_create( n, group_ptr );
         if (mpi_errno) MPIU_ERR_POP(mpi_errno);
         
-	/* Make sure that we get the correct group */
-	if (comm_ptr->comm_kind == MPID_INTERCOMM) {
-	    local_vcr = comm_ptr->local_vcr;
-	}
-	else
-	    local_vcr = comm_ptr->vcr;
-
         (*group_ptr)->is_local_dense_monotonic = TRUE;
 	for (i=0; i<n; i++) {
-	    (void) MPID_VCR_Get_lpid( local_vcr[i], &lpid );
+	    (void) MPID_Comm_get_lpid( comm_ptr, i, &lpid, MPIU_FALSE );
 	    (*group_ptr)->lrank_to_lpid[i].lpid  = lpid;
             if (lpid > comm_world_size ||
                 (i > 0 && (*group_ptr)->lrank_to_lpid[i-1].lpid != (lpid-1)))
diff --git a/src/mpi/comm/comm_remote_group.c b/src/mpi/comm/comm_remote_group.c
index 86544a5..27b3b75 100644
--- a/src/mpi/comm/comm_remote_group.c
+++ b/src/mpi/comm/comm_remote_group.c
@@ -44,7 +44,7 @@ int MPIR_Comm_remote_group_impl(MPID_Comm *comm_ptr, MPID_Group **group_ptr)
         if (mpi_errno) MPIU_ERR_POP(mpi_errno);
 
         for (i=0; i<n; i++) {
-            (void) MPID_VCR_Get_lpid( comm_ptr->vcr[i], &lpid );
+            (void) MPID_Comm_get_lpid( comm_ptr, i, &lpid, MPIU_TRUE );
             (*group_ptr)->lrank_to_lpid[i].lpid  = lpid;
             /* TODO calculate is_local_dense_monotonic */
         }
diff --git a/src/mpi/comm/comm_shrink.c b/src/mpi/comm/comm_shrink.c
index 56536d7..3436ad9 100644
--- a/src/mpi/comm/comm_shrink.c
+++ b/src/mpi/comm/comm_shrink.c
@@ -76,7 +76,7 @@ int MPIR_Comm_shrink(MPID_Comm *comm_ptr, MPID_Comm **newcomm_ptr)
             errflag = MPIR_ERR_PROC_FAILED;
         } else if (mpi_errno) {
             errflag = MPIR_ERR_GET_CLASS(mpi_errno);
-            MPIR_Comm_release(*newcomm_ptr, 0);
+            MPIR_Comm_release(*newcomm_ptr);
         }
 
         mpi_errno = MPIR_Allreduce_group(MPI_IN_PLACE, &errflag, 1, MPI_INT, MPI_MAX, comm_ptr,
@@ -86,7 +86,7 @@ int MPIR_Comm_shrink(MPID_Comm *comm_ptr, MPID_Comm **newcomm_ptr)
         if (errflag) {
             if (*newcomm_ptr != NULL && MPIU_Object_get_ref(*newcomm_ptr) > 0) {
                 MPIU_Object_set_ref(*newcomm_ptr, 1);
-                MPIR_Comm_release(*newcomm_ptr, 0);
+                MPIR_Comm_release(*newcomm_ptr);
             }
             if (MPIU_Object_get_ref(new_group_ptr) > 0) {
                 MPIU_Object_set_ref(new_group_ptr, 1);
diff --git a/src/mpi/comm/comm_split.c b/src/mpi/comm/comm_split.c
index effa047..bdbaa01 100644
--- a/src/mpi/comm/comm_split.c
+++ b/src/mpi/comm/comm_split.c
@@ -138,6 +138,7 @@ int MPIR_Comm_split_impl(MPID_Comm *comm_ptr, int color, int key, MPID_Comm **ne
     int in_newcomm; /* TRUE iff *newcomm should be populated */
     MPIR_Context_id_t   new_context_id, remote_context_id;
     mpir_errflag_t errflag = MPIR_ERR_NONE;
+    MPIR_Comm_map_t *mapper;
     MPIU_CHKLMEM_DECL(4);
 
     rank        = comm_ptr->rank;
@@ -314,17 +315,16 @@ int MPIR_Comm_split_impl(MPID_Comm *comm_ptr, int color, int key, MPID_Comm **ne
 	       corresponding process in the input communicator */
 	    MPIU_Sort_inttable( remotekeytable, new_remote_size );
 
-	    MPID_VCRT_Create( new_size, &(*newcomm_ptr)->local_vcrt );
-	    MPID_VCRT_Get_ptr( (*newcomm_ptr)->local_vcrt, 
-			       &(*newcomm_ptr)->local_vcr );
-	    for (i=0; i<new_size; i++) {
-		MPID_VCR_Dup( comm_ptr->local_vcr[keytable[i].color], 
-			      &(*newcomm_ptr)->local_vcr[i] );
-		if (keytable[i].color == comm_ptr->rank) {
+            MPIR_Comm_map_irregular(*newcomm_ptr, comm_ptr, NULL,
+                                    new_size, MPIR_COMM_MAP_DIR_L2L,
+                                    &mapper);
+
+            for (i = 0; i < new_size; i++) {
+                mapper->src_mapping[i] = keytable[i].color;
+		if (keytable[i].color == comm_ptr->rank)
 		    (*newcomm_ptr)->rank = i;
-		}
-	    }
-	    
+            }
+
 	    /* For the remote group, the situation is more complicated.
 	       We need to find the size of our "partner" group in the
 	       remote comm.  The easiest way (in terms of code) is for
@@ -340,12 +340,12 @@ int MPIR_Comm_split_impl(MPID_Comm *comm_ptr, int color, int key, MPID_Comm **ne
 	       is required to return MPI_COMM_NULL instead of an intercomm 
 	       with an empty remote group. */
 
-	    MPID_VCRT_Create( new_remote_size, &(*newcomm_ptr)->vcrt );
-	    MPID_VCRT_Get_ptr( (*newcomm_ptr)->vcrt, &(*newcomm_ptr)->vcr );
-	    for (i=0; i<new_remote_size; i++) {
-		MPID_VCR_Dup( comm_ptr->vcr[remotekeytable[i].color], 
-			      &(*newcomm_ptr)->vcr[i] );
-	    }
+            MPIR_Comm_map_irregular(*newcomm_ptr, comm_ptr, NULL,
+                                    new_remote_size,
+                                    MPIR_COMM_MAP_DIR_R2R, &mapper);
+
+            for (i = 0; i < new_remote_size; i++)
+                mapper->src_mapping[i] = remotekeytable[i].color;
 
 	    (*newcomm_ptr)->context_id     = remote_context_id;
 	    (*newcomm_ptr)->remote_size    = new_remote_size;
@@ -357,15 +357,16 @@ int MPIR_Comm_split_impl(MPID_Comm *comm_ptr, int color, int key, MPID_Comm **ne
 	    /* INTRA Communicator */
 	    (*newcomm_ptr)->context_id     = (*newcomm_ptr)->recvcontext_id;
 	    (*newcomm_ptr)->remote_size    = new_size;
-	    MPID_VCRT_Create( new_size, &(*newcomm_ptr)->vcrt );
-	    MPID_VCRT_Get_ptr( (*newcomm_ptr)->vcrt, &(*newcomm_ptr)->vcr );
-	    for (i=0; i<new_size; i++) {
-		MPID_VCR_Dup( comm_ptr->vcr[keytable[i].color], 
-			      &(*newcomm_ptr)->vcr[i] );
-		if (keytable[i].color == comm_ptr->rank) {
+
+            MPIR_Comm_map_irregular(*newcomm_ptr, comm_ptr, NULL,
+                                    new_size, MPIR_COMM_MAP_DIR_L2L,
+                                    &mapper);
+
+            for (i = 0; i < new_size; i++) {
+                mapper->src_mapping[i] = keytable[i].color;
+		if (keytable[i].color == comm_ptr->rank)
 		    (*newcomm_ptr)->rank = i;
-		}
-	    }
+            }
 	}
 
 	/* Inherit the error handler (if any) */
@@ -423,7 +424,6 @@ Algorithm:
      communicator with that many processes.  If this process has
      'MPI_UNDEFINED' as the color, create a process with a single member.
   3. Use key to order the ranks
-  4. Set the VCRs using the ordered key values
 .ve
  
 .N Errors
diff --git a/src/mpi/comm/commutil.c b/src/mpi/comm/commutil.c
index 3a19b2f..0cf32e5 100644
--- a/src/mpi/comm/commutil.c
+++ b/src/mpi/comm/commutil.c
@@ -147,6 +147,9 @@ int MPIR_Comm_init(MPID_Comm *comm_p)
     comm_p->idup_curr_seqnum = 0;
     comm_p->idup_next_seqnum = 0;
 
+    comm_p->mapper_head = NULL;
+    comm_p->mapper_tail = NULL;
+
     /* Fields not set include context_id, remote and local size, and
        kind, since different communicator construction routines need
        different values */
@@ -218,11 +221,6 @@ int MPIR_Setup_intercomm_localcomm( MPID_Comm *intercomm_ptr )
 
     MPIU_DBG_MSG_FMT(COMM,TYPICAL,(MPIU_DBG_FDEST, "setup_intercomm_localcomm ic=%p ic->context_id=%d ic->recvcontext_id=%d lc->recvcontext_id=%d", intercomm_ptr, intercomm_ptr->context_id, intercomm_ptr->recvcontext_id, localcomm_ptr->recvcontext_id));
 
-    /* Duplicate the VCRT references */
-    MPID_VCRT_Add_ref( intercomm_ptr->local_vcrt );
-    localcomm_ptr->vcrt = intercomm_ptr->local_vcrt;
-    localcomm_ptr->vcr  = intercomm_ptr->local_vcr;
-
     /* Save the kind of the communicator */
     localcomm_ptr->comm_kind   = MPID_INTRACOMM;
 
@@ -231,6 +229,8 @@ int MPIR_Setup_intercomm_localcomm( MPID_Comm *intercomm_ptr )
     localcomm_ptr->local_size  = intercomm_ptr->local_size;
     localcomm_ptr->rank        = intercomm_ptr->rank;
 
+    MPIR_Comm_map_dup(localcomm_ptr, intercomm_ptr, MPIR_COMM_MAP_DIR_L2L);
+
     /* TODO More advanced version: if the group is available, dup it by 
        increasing the reference count instead of recreating it later */
     /* FIXME  : No coll_fns functions for the collectives */
@@ -437,6 +437,123 @@ fn_fail:
     goto fn_exit;
 }
 
+#undef FUNCNAME
+#define FUNCNAME MPIR_Comm_map_irregular
+#undef FCNAME
+#define FCNAME MPIU_QUOTE(FUNCNAME)
+int MPIR_Comm_map_irregular(MPID_Comm *newcomm, MPID_Comm *src_comm,
+                                int *src_mapping, int src_mapping_size,
+                                MPIR_Comm_map_dir_t dir,
+                                MPIR_Comm_map_t **map)
+{
+    int mpi_errno = MPI_SUCCESS;
+    MPIR_Comm_map_t *mapper;
+    MPIU_CHKPMEM_DECL(3);
+    MPID_MPI_STATE_DECL(MPID_STATE_MPIR_COMM_MAP_IRREGULAR);
+
+    MPID_MPI_FUNC_ENTER(MPID_STATE_MPIR_COMM_MAP_IRREGULAR);
+
+    MPIU_CHKPMEM_MALLOC(mapper, MPIR_Comm_map_t *,
+                        sizeof(MPIR_Comm_map_t), mpi_errno,
+                        "mapper");
+
+    mapper->type = MPIR_COMM_MAP_IRREGULAR;
+    mapper->src_comm = src_comm;
+    mapper->dir = dir;
+    mapper->src_mapping_size = src_mapping_size;
+
+    if (src_mapping) {
+        mapper->src_mapping = src_mapping;
+        mapper->free_mapping = 0;
+    }
+    else {
+        MPIU_CHKPMEM_MALLOC(mapper->src_mapping, int *,
+                            src_mapping_size * sizeof(int), mpi_errno,
+                            "mapper mapping");
+        mapper->free_mapping = 1;
+    }
+
+    mapper->next = NULL;
+
+    MPL_LL_APPEND(newcomm->mapper_head, newcomm->mapper_tail, mapper);
+
+    if (map)
+        *map = mapper;
+
+fn_exit:
+    MPIU_CHKPMEM_COMMIT();
+    MPID_MPI_FUNC_EXIT(MPID_STATE_MPIR_COMM_MAP_IRREGULAR);
+    return mpi_errno;
+fn_fail:
+    MPIU_CHKPMEM_REAP();
+    goto fn_exit;
+}
+
+#undef FUNCNAME
+#define FUNCNAME MPIR_Comm_map_dup
+#undef FCNAME
+#define FCNAME MPIU_QUOTE(FUNCNAME)
+int MPIR_Comm_map_dup(MPID_Comm *newcomm, MPID_Comm *src_comm,
+                          MPIR_Comm_map_dir_t dir)
+{
+    int mpi_errno = MPI_SUCCESS;
+    MPIR_Comm_map_t *mapper;
+    MPIU_CHKPMEM_DECL(1);
+    MPID_MPI_STATE_DECL(MPID_STATE_MPIR_COMM_MAP_DUP);
+
+    MPID_MPI_FUNC_ENTER(MPID_STATE_MPIR_COMM_MAP_DUP);
+
+    MPIU_CHKPMEM_MALLOC(mapper, MPIR_Comm_map_t *,
+                        sizeof(MPIR_Comm_map_t), mpi_errno,
+                        "mapper");
+
+    mapper->type = MPIR_COMM_MAP_DUP;
+    mapper->src_comm = src_comm;
+    mapper->dir = dir;
+
+    mapper->next = NULL;
+
+    MPL_LL_APPEND(newcomm->mapper_head, newcomm->mapper_tail, mapper);
+
+fn_exit:
+    MPIU_CHKPMEM_COMMIT();
+    MPID_MPI_FUNC_EXIT(MPID_STATE_MPIR_COMM_MAP_DUP);
+    return mpi_errno;
+fn_fail:
+    MPIU_CHKPMEM_REAP();
+    goto fn_exit;
+}
+
+
+#undef FUNCNAME
+#define FUNCNAME MPIR_Comm_map_free
+#undef FCNAME
+#define FCNAME MPIU_QUOTE(FUNCNAME)
+int MPIR_Comm_map_free(MPID_Comm *comm)
+{
+    int mpi_errno = MPI_SUCCESS;
+    MPIR_Comm_map_t *mapper, *tmp;
+    MPID_MPI_STATE_DECL(MPID_STATE_MPIR_COMM_MAP_FREE);
+
+    MPID_MPI_FUNC_ENTER(MPID_STATE_MPIR_COMM_MAP_FREE);
+
+    for (mapper = comm->mapper_head; mapper;) {
+        tmp = mapper->next;
+        if (mapper->type == MPIR_COMM_MAP_IRREGULAR &&
+            mapper->free_mapping)
+            MPIU_Free(mapper->src_mapping);
+        MPIU_Free(mapper);
+        mapper = tmp;
+    }
+    comm->mapper_head = NULL;
+
+fn_exit:
+    MPID_MPI_FUNC_EXIT(MPID_STATE_MPIR_COMM_MAP_FREE);
+    return mpi_errno;
+fn_fail:
+    goto fn_exit;
+}
+
 /* Provides a hook for the top level functions to perform some manipulation on a
    communicator just before it is given to the application level.
   
@@ -449,7 +566,6 @@ fn_fail:
 int MPIR_Comm_commit(MPID_Comm *comm)
 {
     int mpi_errno = MPI_SUCCESS;
-    int i;
     int num_local = -1, num_external = -1;
     int local_rank = -1, external_rank = -1;
     int *local_procs = NULL, *external_procs = NULL;
@@ -470,6 +586,8 @@ int MPIR_Comm_commit(MPID_Comm *comm)
     mpi_errno = MPID_Dev_comm_create_hook(comm);
     if (mpi_errno) MPIU_ERR_POP(mpi_errno);
 
+    MPIR_Comm_map_free(comm);
+
     if (comm->comm_kind == MPID_INTRACOMM) {
 
         mpi_errno = MPIU_Find_local_and_external(comm,
@@ -521,14 +639,9 @@ int MPIR_Comm_commit(MPID_Comm *comm)
             comm->node_comm->local_size  = num_local;
             comm->node_comm->remote_size = num_local;
 
-            MPID_VCRT_Create( num_local, &comm->node_comm->vcrt );
-            MPID_VCRT_Get_ptr( comm->node_comm->vcrt, &comm->node_comm->vcr );
-            for (i = 0; i < num_local; ++i) {
-                /* For rank i in the new communicator, find the corresponding
-                   rank in the input communicator */
-                MPID_VCR_Dup( comm->vcr[local_procs[i]], 
-                              &comm->node_comm->vcr[i] );
-            }
+            MPIR_Comm_map_irregular(comm->node_comm, comm, local_procs,
+                                    num_local, MPIR_COMM_MAP_DIR_L2L,
+                                    NULL);
 
             mpi_errno = set_collops(comm->node_comm);
             if (mpi_errno) MPIU_ERR_POP(mpi_errno);
@@ -537,6 +650,8 @@ int MPIR_Comm_commit(MPID_Comm *comm)
             mpi_errno = MPID_Dev_comm_create_hook( comm->node_comm );
             if (mpi_errno) MPIU_ERR_POP(mpi_errno);
             /* don't call MPIR_Comm_commit here */
+
+            MPIR_Comm_map_free(comm->node_comm);
         }
 
 
@@ -555,14 +670,9 @@ int MPIR_Comm_commit(MPID_Comm *comm)
             comm->node_roots_comm->local_size  = num_external;
             comm->node_roots_comm->remote_size = num_external;
 
-            MPID_VCRT_Create( num_external, &comm->node_roots_comm->vcrt );
-            MPID_VCRT_Get_ptr( comm->node_roots_comm->vcrt, &comm->node_roots_comm->vcr );
-            for (i = 0; i < num_external; ++i) {
-                /* For rank i in the new communicator, find the corresponding
-                   rank in the input communicator */
-                MPID_VCR_Dup( comm->vcr[external_procs[i]], 
-                              &comm->node_roots_comm->vcr[i] );
-            }
+            MPIR_Comm_map_irregular(comm->node_roots_comm, comm,
+                                    external_procs, num_external,
+                                    MPIR_COMM_MAP_DIR_L2L, NULL);
 
             mpi_errno = set_collops(comm->node_roots_comm);
             if (mpi_errno) MPIU_ERR_POP(mpi_errno);
@@ -571,6 +681,8 @@ int MPIR_Comm_commit(MPID_Comm *comm)
             mpi_errno = MPID_Dev_comm_create_hook( comm->node_roots_comm );
             if (mpi_errno) MPIU_ERR_POP(mpi_errno);
             /* don't call MPIR_Comm_commit here */
+
+            MPIR_Comm_map_free(comm->node_roots_comm);
         }
 
         comm->hierarchy_kind = MPID_HIERARCHY_PARENT;
@@ -1768,6 +1880,7 @@ int MPIR_Comm_copy( MPID_Comm *comm_ptr, int size, MPID_Comm **outcomm_ptr )
     int mpi_errno = MPI_SUCCESS;
     MPIR_Context_id_t new_context_id, new_recvcontext_id;
     MPID_Comm *newcomm_ptr = NULL;
+    MPIR_Comm_map_t *map;
     MPID_MPI_STATE_DECL(MPID_STATE_MPIR_COMM_COPY);
 
     MPID_MPI_FUNC_ENTER(MPID_STATE_MPIR_COMM_COPY);
@@ -1824,32 +1937,34 @@ int MPIR_Comm_copy( MPID_Comm *comm_ptr, int size, MPID_Comm **outcomm_ptr )
 
     /* There are two cases here - size is the same as the old communicator,
        or it is smaller.  If the size is the same, we can just add a reference.
-       Otherwise, we need to create a new VCRT.  Note that this is the
+       Otherwise, we need to create a new network address mapping.  Note that this is the
        test that matches the test on rank above. */
     if (size == comm_ptr->local_size) {
-	/* Duplicate the VCRT references */
-	MPID_VCRT_Add_ref( comm_ptr->vcrt );
-	newcomm_ptr->vcrt = comm_ptr->vcrt;
-	newcomm_ptr->vcr  = comm_ptr->vcr;
+       /* Duplicate the network address mapping */
+       if (comm_ptr->comm_kind == MPID_INTRACOMM)
+           MPIR_Comm_map_dup(newcomm_ptr, comm_ptr, MPIR_COMM_MAP_DIR_L2L);
+       else
+           MPIR_Comm_map_dup(newcomm_ptr, comm_ptr, MPIR_COMM_MAP_DIR_R2R);
     }
     else {
-	int i;
-	/* The "remote" vcr gets the shortened vcrt */
-	MPID_VCRT_Create( size, &newcomm_ptr->vcrt );
-	MPID_VCRT_Get_ptr( newcomm_ptr->vcrt, 
-			   &newcomm_ptr->vcr );
-	for (i=0; i<size; i++) {
-	    /* For rank i in the new communicator, find the corresponding
-	       rank in the input communicator */
-	    MPID_VCR_Dup( comm_ptr->vcr[i], &newcomm_ptr->vcr[i] );
-	}
+       int i;
+
+       if (comm_ptr->comm_kind == MPID_INTRACOMM)
+           MPIR_Comm_map_irregular(newcomm_ptr, comm_ptr, NULL, size,
+                                   MPIR_COMM_MAP_DIR_L2L, &map);
+       else
+           MPIR_Comm_map_irregular(newcomm_ptr, comm_ptr, NULL, size,
+                                   MPIR_COMM_MAP_DIR_R2R, &map);
+       for (i = 0; i < size; i++) {
+           /* For rank i in the new communicator, find the corresponding
+              rank in the input communicator */
+           map->src_mapping[i] = i;
+       }
     }
 
-    /* If it is an intercomm, duplicate the local vcrt references */
+    /* If it is an intercomm, duplicate the local network address references */
     if (comm_ptr->comm_kind == MPID_INTERCOMM) {
-	MPID_VCRT_Add_ref( comm_ptr->local_vcrt );
-	newcomm_ptr->local_vcrt = comm_ptr->local_vcrt;
-	newcomm_ptr->local_vcr  = comm_ptr->local_vcr;
+       MPIR_Comm_map_dup(newcomm_ptr, comm_ptr, MPIR_COMM_MAP_DIR_L2L);
     }
 
     /* Set the sizes and ranks */
@@ -1925,16 +2040,14 @@ int MPIR_Comm_copy_data(MPID_Comm *comm_ptr, MPID_Comm **outcomm_ptr)
     newcomm_ptr->comm_kind  = comm_ptr->comm_kind;
     newcomm_ptr->local_comm = 0;
 
-    /* Duplicate the VCRT references */
-    MPID_VCRT_Add_ref(comm_ptr->vcrt);
-    newcomm_ptr->vcrt = comm_ptr->vcrt;
-    newcomm_ptr->vcr  = comm_ptr->vcr;
+    if (comm_ptr->comm_kind == MPID_INTRACOMM)
+        MPIR_Comm_map_dup(newcomm_ptr, comm_ptr, MPIR_COMM_MAP_DIR_L2L);
+    else
+        MPIR_Comm_map_dup(newcomm_ptr, comm_ptr, MPIR_COMM_MAP_DIR_R2R);
 
-    /* If it is an intercomm, duplicate the local vcrt references */
+    /* If it is an intercomm, duplicate the network address mapping */
     if (comm_ptr->comm_kind == MPID_INTERCOMM) {
-        MPID_VCRT_Add_ref(comm_ptr->local_vcrt);
-        newcomm_ptr->local_vcrt = comm_ptr->local_vcrt;
-        newcomm_ptr->local_vcr  = comm_ptr->local_vcr;
+        MPIR_Comm_map_dup(newcomm_ptr, comm_ptr, MPIR_COMM_MAP_DIR_L2L);
     }
 
     /* Set the sizes and ranks */
@@ -1967,7 +2080,7 @@ fn_exit:
 }
 /* Common body between MPIR_Comm_release and MPIR_comm_release_always.  This
  * helper function frees the actual MPID_Comm structure and any associated
- * storage.  It also releases any refernces to other objects, such as the VCRT.
+ * storage.  It also releases any references to other objects.
  * This function should only be called when the communicator's reference count
  * has dropped to 0.
  *
@@ -1977,7 +2090,7 @@ fn_exit:
 #define FUNCNAME MPIR_Comm_delete_internal
 #undef FCNAME
 #define FCNAME MPIU_QUOTE(FUNCNAME)
-int MPIR_Comm_delete_internal(MPID_Comm * comm_ptr, int isDisconnect)
+int MPIR_Comm_delete_internal(MPID_Comm * comm_ptr)
 {
     int in_use;
     int mpi_errno = MPI_SUCCESS;
@@ -2029,20 +2142,8 @@ int MPIR_Comm_delete_internal(MPID_Comm * comm_ptr, int isDisconnect)
             comm_ptr->coll_fns = NULL;
         }
 
-        /* Free the VCRT */
-        mpi_errno = MPID_VCRT_Release(comm_ptr->vcrt, isDisconnect);
-        if (mpi_errno != MPI_SUCCESS) {
-            MPIU_ERR_POP(mpi_errno);
-        }
-        if (comm_ptr->comm_kind == MPID_INTERCOMM) {
-            mpi_errno = MPID_VCRT_Release(
-                                          comm_ptr->local_vcrt, isDisconnect);
-            if (mpi_errno != MPI_SUCCESS) {
-                MPIU_ERR_POP(mpi_errno);
-            }
-            if (comm_ptr->local_comm)
-                MPIR_Comm_release(comm_ptr->local_comm, isDisconnect );
-        }
+        if (comm_ptr->comm_kind == MPID_INTERCOMM && comm_ptr->local_comm)
+            MPIR_Comm_release(comm_ptr->local_comm);
 
         /* Free the local and remote groups, if they exist */
         if (comm_ptr->local_group)
@@ -2052,9 +2153,9 @@ int MPIR_Comm_delete_internal(MPID_Comm * comm_ptr, int isDisconnect)
 
         /* free the intra/inter-node communicators, if they exist */
         if (comm_ptr->node_comm)
-            MPIR_Comm_release(comm_ptr->node_comm, isDisconnect);
+            MPIR_Comm_release(comm_ptr->node_comm);
         if (comm_ptr->node_roots_comm)
-            MPIR_Comm_release(comm_ptr->node_roots_comm, isDisconnect);
+            MPIR_Comm_release(comm_ptr->node_roots_comm);
         if (comm_ptr->intranode_table != NULL)
             MPIU_Free(comm_ptr->intranode_table);
         if (comm_ptr->internode_table != NULL)
@@ -2114,7 +2215,7 @@ int MPIR_Comm_delete_internal(MPID_Comm * comm_ptr, int isDisconnect)
 #define FUNCNAME MPIR_Comm_release_always
 #undef FCNAME
 #define FCNAME MPIU_QUOTE(FUNCNAME)
-int MPIR_Comm_release_always(MPID_Comm *comm_ptr, int isDisconnect)
+int MPIR_Comm_release_always(MPID_Comm *comm_ptr)
 {
     int mpi_errno = MPI_SUCCESS;
     int in_use;
@@ -2126,7 +2227,7 @@ int MPIR_Comm_release_always(MPID_Comm *comm_ptr, int isDisconnect)
      * predefined communicators, such as MPI_COMM_WORLD or MPI_COMM_SELF. */
     MPIU_Object_release_ref_always(comm_ptr, &in_use);
     if (!in_use) {
-        mpi_errno = MPIR_Comm_delete_internal(comm_ptr, isDisconnect);
+        mpi_errno = MPIR_Comm_delete_internal(comm_ptr);
         if (mpi_errno) MPIU_ERR_POP(mpi_errno);
     }
 
diff --git a/src/mpi/comm/intercomm_create.c b/src/mpi/comm/intercomm_create.c
index b832624..01770f0 100644
--- a/src/mpi/comm/intercomm_create.c
+++ b/src/mpi/comm/intercomm_create.c
@@ -110,7 +110,7 @@ PMPI_LOCAL int MPID_LPID_GetAllInComm( MPID_Comm *comm_ptr, int local_size,
     /* FIXME: Should be using the local_size argument */
     MPIU_Assert( comm_ptr->local_size == local_size );
     for (i=0; i<comm_ptr->local_size; i++) {
-	(void)MPID_VCR_Get_lpid( comm_ptr->vcr[i], &local_lpids[i] );
+	(void)MPID_Comm_get_lpid( comm_ptr, i, &local_lpids[i], MPIU_FALSE );
     }
     return 0;
 }
@@ -130,7 +130,6 @@ int MPIR_Intercomm_create_impl(MPID_Comm *local_comm_ptr, int local_leader,
     int comm_info[3];
     int is_low_group = 0;
     int cts_tag;
-    int i;
     mpir_errflag_t errflag = MPIR_ERR_NONE;
     MPIU_CHKLMEM_DECL(4);
     MPID_MPI_STATE_DECL(MPID_STATE_MPIR_INTERCOMM_CREATE_IMPL);
@@ -333,16 +332,10 @@ int MPIR_Intercomm_create_impl(MPID_Comm *local_comm_ptr, int local_leader,
     (*new_intercomm_ptr)->local_comm     = 0;
     (*new_intercomm_ptr)->is_low_group   = is_low_group;
 
-    mpi_errno = MPID_VCR_CommFromLpids( *new_intercomm_ptr, remote_size, remote_lpids );
+    mpi_errno = MPID_Create_intercomm_from_lpids( *new_intercomm_ptr, remote_size, remote_lpids );
     if (mpi_errno) goto fn_fail;
 
-    /* Setup the communicator's vc table: local group.  This is
-     just a duplicate of the local_comm's group */
-    MPID_VCRT_Create( local_comm_ptr->local_size, &(*new_intercomm_ptr)->local_vcrt );
-    MPID_VCRT_Get_ptr( (*new_intercomm_ptr)->local_vcrt, &(*new_intercomm_ptr)->local_vcr );
-    for (i = 0; i < local_comm_ptr->local_size; i++) {
-        MPID_VCR_Dup( local_comm_ptr->vcr[i], &(*new_intercomm_ptr)->local_vcr[i] );
-    }
+    MPIR_Comm_map_dup(*new_intercomm_ptr, local_comm_ptr, MPIR_COMM_MAP_DIR_L2L);
 
     /* Inherit the error handler (if any) */
     MPIU_THREAD_CS_ENTER(MPI_OBJ, local_comm_ptr);
diff --git a/src/mpi/comm/intercomm_merge.c b/src/mpi/comm/intercomm_merge.c
index 4f85628..0a16b06 100644
--- a/src/mpi/comm/intercomm_merge.c
+++ b/src/mpi/comm/intercomm_merge.c
@@ -27,52 +27,38 @@ int MPI_Intercomm_merge(MPI_Comm intercomm, int high, MPI_Comm *newintracomm) __
 #undef MPI_Intercomm_merge
 #define MPI_Intercomm_merge PMPI_Intercomm_merge
 
-/* This function creates VCRT for new communicator
- * basing on VCRT of existing communicator.
+/* This function creates mapping for new communicator
+ * basing on network addresses of existing communicator.
  */
 
 #undef FUNCNAME
-#define FUNCNAME create_and_map_vcrt
+#define FUNCNAME create_and_map
 #undef FCNAME
 #define FCNAME MPIU_QUOTE(FUNCNAME)
-static int create_and_map_vcrt(MPID_Comm *comm_ptr, int local_high, MPID_Comm *new_intracomm_ptr)
+static int create_and_map(MPID_Comm *comm_ptr, int local_high, MPID_Comm *new_intracomm_ptr)
 {
     int mpi_errno = MPI_SUCCESS;
-    int i, j;
-
-    /* Now we know which group comes first.  Build the new vcr
-       from the existing vcrs */
-    mpi_errno = MPID_VCRT_Create( comm_ptr->local_size + comm_ptr->remote_size, &new_intracomm_ptr->vcrt );
-    if (mpi_errno) MPIU_ERR_POP(mpi_errno);
-
-    mpi_errno = MPID_VCRT_Get_ptr( new_intracomm_ptr->vcrt, &new_intracomm_ptr->vcr );
-    if (mpi_errno) MPIU_ERR_POP(mpi_errno);
+    int i;
 
+    /* Now we know which group comes first.  Build the new mapping
+       from the existing comm */
     if (local_high) {
         /* remote group first */
-        j = 0;
-        for (i = 0; i < comm_ptr->remote_size; i++) {
-            mpi_errno = MPID_VCR_Dup( comm_ptr->vcr[i], &new_intracomm_ptr->vcr[j++] );
-            if (mpi_errno) MPIU_ERR_POP(mpi_errno);
-        }
-        for (i = 0; i < comm_ptr->local_size; i++) {
-            if (i == comm_ptr->rank) new_intracomm_ptr->rank = j;
-            mpi_errno = MPID_VCR_Dup( comm_ptr->local_vcr[i], &new_intracomm_ptr->vcr[j++] );
-            if (mpi_errno) MPIU_ERR_POP(mpi_errno);
-        }
+        MPIR_Comm_map_dup(new_intracomm_ptr, comm_ptr, MPIR_COMM_MAP_DIR_R2L);
+
+        MPIR_Comm_map_dup(new_intracomm_ptr, comm_ptr, MPIR_COMM_MAP_DIR_L2L);
+        for (i = 0; i < comm_ptr->local_size; i++)
+            if (i == comm_ptr->rank)
+                new_intracomm_ptr->rank = comm_ptr->remote_size + i;
     }
     else {
         /* local group first */
-        j = 0;
-        for (i = 0; i < comm_ptr->local_size; i++) {
-            if (i == comm_ptr->rank) new_intracomm_ptr->rank = j;
-            mpi_errno = MPID_VCR_Dup( comm_ptr->local_vcr[i], &new_intracomm_ptr->vcr[j++] );
-            if (mpi_errno) MPIU_ERR_POP(mpi_errno);
-        }
-        for (i = 0; i < comm_ptr->remote_size; i++) {
-            mpi_errno = MPID_VCR_Dup( comm_ptr->vcr[i], &new_intracomm_ptr->vcr[j++] );
-            if (mpi_errno) MPIU_ERR_POP(mpi_errno);
-        }
+        MPIR_Comm_map_dup(new_intracomm_ptr, comm_ptr, MPIR_COMM_MAP_DIR_L2L);
+        for (i = 0; i < comm_ptr->local_size; i++)
+            if (i == comm_ptr->rank)
+                new_intracomm_ptr->rank = i;
+
+        MPIR_Comm_map_dup(new_intracomm_ptr, comm_ptr, MPIR_COMM_MAP_DIR_R2L);
     }
 
 fn_fail:
@@ -169,9 +155,9 @@ int MPIR_Intercomm_merge_impl(MPID_Comm *comm_ptr, int high, MPID_Comm **new_int
     (*new_intracomm_ptr)->rank           = -1;
     (*new_intracomm_ptr)->comm_kind      = MPID_INTRACOMM;
 
-    /* Now we know which group comes first.  Build the new vcr
-       from the existing vcrs */
-    mpi_errno = create_and_map_vcrt(comm_ptr, local_high, (*new_intracomm_ptr));
+    /* Now we know which group comes first.  Build the new mapping
+       from the existing comm */
+    mpi_errno = create_and_map(comm_ptr, local_high, (*new_intracomm_ptr));
     if (mpi_errno) MPIU_ERR_POP(mpi_errno);
 
     /* We've setup a temporary context id, based on the context id
@@ -193,7 +179,7 @@ int MPIR_Intercomm_merge_impl(MPID_Comm *comm_ptr, int high, MPID_Comm **new_int
     /* We release this communicator that was involved just to
      * get valid context id and create true one
      */
-    mpi_errno = MPIR_Comm_release( (*new_intracomm_ptr),0);
+    mpi_errno = MPIR_Comm_release(*new_intracomm_ptr);
     if (mpi_errno) MPIU_ERR_POP(mpi_errno);
 
     mpi_errno = MPIR_Comm_create( new_intracomm_ptr );
@@ -205,7 +191,7 @@ int MPIR_Intercomm_merge_impl(MPID_Comm *comm_ptr, int high, MPID_Comm **new_int
     (*new_intracomm_ptr)->context_id = new_context_id;
     (*new_intracomm_ptr)->recvcontext_id = new_context_id;
 
-    mpi_errno = create_and_map_vcrt(comm_ptr, local_high, (*new_intracomm_ptr));
+    mpi_errno = create_and_map(comm_ptr, local_high, (*new_intracomm_ptr));
     if (mpi_errno) MPIU_ERR_POP(mpi_errno);
 
     mpi_errno = MPIR_Comm_commit((*new_intracomm_ptr));
diff --git a/src/mpi/group/grouputil.c b/src/mpi/group/grouputil.c
index 44bf084..91ab9a0 100644
--- a/src/mpi/group/grouputil.c
+++ b/src/mpi/group/grouputil.c
@@ -369,27 +369,29 @@ int MPIR_Group_check_valid_ranges( MPID_Group *group_ptr,
 
     return mpi_errno;
 }
-/* Given a group and a VCR, check that the group is a subset of the processes
-   defined by the VCR.
 
-   We sort the lpids for the group and the vcr.  If the group has an
-   lpid that is not in the vcr, then report an error.
+/* Given a group and a comm, check that the group is a subset of the processes
+   defined by the comm.
+
+   We sort the lpids for the group and the comm.  If the group has an
+   lpid that is not in the comm, then report an error.
 */
-int MPIR_GroupCheckVCRSubset( MPID_Group *group_ptr, int vsize, MPID_VCR *vcr )
+int MPIR_Group_check_subset( MPID_Group *group_ptr, MPID_Comm *comm_ptr )
 {
     int mpi_errno = MPI_SUCCESS;
     int g1_idx, g2_idx, l1_pid, l2_pid, i;
     MPID_Group_pmap_t *vmap=0;
+    int vsize = comm_ptr->comm_kind == MPID_INTERCOMM ? comm_ptr->local_size :
+        comm_ptr->remote_size;
     MPIU_CHKLMEM_DECL(1);
 
     MPIU_Assert(group_ptr != NULL);
-    MPIU_Assert(vcr != NULL);
 
     MPIU_CHKLMEM_MALLOC(vmap,MPID_Group_pmap_t*,
 			vsize*sizeof(MPID_Group_pmap_t),mpi_errno, "" );
     /* Initialize the vmap */
     for (i=0; i<vsize; i++) {
-	MPID_VCR_Get_lpid( vcr[i], &vmap[i].lpid );
+	MPID_Comm_get_lpid(comm_ptr, i, &vmap[i].lpid, MPIU_FALSE);
 	vmap[i].next_lpid = 0;
 	vmap[i].flag      = 0;
     }
diff --git a/src/mpid/ch3/channels/nemesis/netmod/ofi/ofi_tagged_template.c b/src/mpid/ch3/channels/nemesis/netmod/ofi/ofi_tagged_template.c
index 4ab75d2..02ffcb1 100644
--- a/src/mpid/ch3/channels/nemesis/netmod/ofi/ofi_tagged_template.c
+++ b/src/mpid/ch3/channels/nemesis/netmod/ofi/ofi_tagged_template.c
@@ -54,7 +54,7 @@ int ADD_SUFFIX(MPID_nem_ofi_recv_callback)(cq_tagged_entry_t * wc, MPID_Request
         /* ---------------------------------------------------- */
         vc = REQ_OFI(rreq)->vc;
         if (!vc) {      /* MPI_ANY_SOURCE -- Post message from status, complete the VC */
-            vc = rreq->comm->vcr[src];
+            vc = rreq->comm->dev.vcrt->vcr_table[src];
             MPIU_Assert(vc);
         }
 #if API_SET == API_SET_1
diff --git a/src/mpid/ch3/include/mpidimpl.h b/src/mpid/ch3/include/mpidimpl.h
index 7573ea1..8db9b56 100644
--- a/src/mpid/ch3/include/mpidimpl.h
+++ b/src/mpid/ch3/include/mpidimpl.h
@@ -495,7 +495,7 @@ extern MPIDI_Process_t MPIDI_Process;
 /*------------------
   BEGIN COMM SECTION
   ------------------*/
-#define MPIDI_Comm_get_vc(comm_, rank_, vcp_) *(vcp_) = (comm_)->vcr[(rank_)]
+#define MPIDI_Comm_get_vc(comm_, rank_, vcp_) *(vcp_) = (comm_)->dev.vcrt->vcr_table[(rank_)]
 
 #ifdef USE_MPIDI_DBG_PRINT_VC
 void MPIDI_DBG_PrintVC(MPIDI_VC_t *vc);
@@ -508,7 +508,7 @@ void MPIDI_DBG_PrintVCState(MPIDI_VC_t *vc);
 #endif
 
 #define MPIDI_Comm_get_vc_set_active(comm_, rank_, vcp_) do {           \
-        *(vcp_) = (comm_)->vcr[(rank_)];                                \
+        *(vcp_) = (comm_)->dev.vcrt->vcr_table[(rank_)];                \
         if ((*(vcp_))->state == MPIDI_VC_STATE_INACTIVE)                \
         {                                                               \
             MPIDI_DBG_PrintVCState2(*(vcp_), MPIDI_VC_STATE_ACTIVE);     \
@@ -550,6 +550,11 @@ void MPIDI_DBG_PrintVCState(MPIDI_VC_t *vc);
 typedef int (*MPIDI_PG_Compare_ids_fn_t)(void * id1, void * id2);
 typedef int (*MPIDI_PG_Destroy_fn_t)(MPIDI_PG_t * pg);
 
+int MPIDI_VCRT_Create(int size, struct MPIDI_VCRT **vcrt_ptr);
+int MPIDI_VCRT_Add_ref(struct MPIDI_VCRT *vcrt);
+int MPIDI_VCRT_Release(struct MPIDI_VCRT *vcrt, int isDisconnect);
+int MPIDI_VCR_Dup(MPIDI_VCR orig_vcr, MPIDI_VCR * new_vcr);
+
 int MPIDI_PG_Init( int *, char ***, 
 		   MPIDI_PG_Compare_ids_fn_t, MPIDI_PG_Destroy_fn_t);
 int MPIDI_PG_Finalize(void);
@@ -773,11 +778,23 @@ typedef enum MPIDI_VC_Event
 }
 MPIDI_VC_Event_t;
 
-#ifndef HAVE_MPIDI_VCRT
-#define HAVE_MPIDI_VCRT
-typedef struct MPIDI_VCRT * MPID_VCRT;
-typedef struct MPIDI_VC * MPID_VCR;
-#endif
+/*S
+ * MPIDI_VCRT - virtual connection reference table
+ *
+ * handle - this element is not used, but exists so that we may use the
+ * MPIU_Object routines for reference counting
+ *
+ * ref_count - number of references to this table
+ *
+ * vcr_table - array of virtual connection references
+ S*/
+typedef struct MPIDI_VCRT
+{
+    MPIU_OBJECT_HEADER; /* adds handle and ref_count fields */
+    int size;
+    MPIDI_VC_t * vcr_table[1];
+}
+MPIDI_VCRT_t;
 
 /* number of VCs that are in MORIBUND state */
 extern int MPIDI_Failed_vc_count;
diff --git a/src/mpid/ch3/include/mpidpost.h b/src/mpid/ch3/include/mpidpost.h
index 25f84c1..d4ce7f9 100644
--- a/src/mpid/ch3/include/mpidpost.h
+++ b/src/mpid/ch3/include/mpidpost.h
@@ -177,7 +177,7 @@ int MPID_GPID_GetAllInComm( MPID_Comm *comm_ptr, int local_size,
 			    int local_gpids[], int *singlePG );
 int MPID_GPID_Get( MPID_Comm *comm_ptr, int rank, int gpid[] );
 int MPID_GPID_ToLpidArray( int size, int gpid[], int lpid[] );
-int MPID_VCR_CommFromLpids( MPID_Comm *newcomm_ptr, 
+int MPID_Create_intercomm_from_lpids( MPID_Comm *newcomm_ptr,
 			    int size, const int lpids[] );
 int MPID_PG_ForwardPGInfo( MPID_Comm *peer_ptr, MPID_Comm *comm_ptr, 
 			   int nPGids, const int gpids[], 
diff --git a/src/mpid/ch3/include/mpidpre.h b/src/mpid/ch3/include/mpidpre.h
index c916223..e6bdadc 100644
--- a/src/mpid/ch3/include/mpidpre.h
+++ b/src/mpid/ch3/include/mpidpre.h
@@ -166,6 +166,11 @@ typedef union {
 #define MPID_Dev_comm_create_hook(comm_) MPIDI_CH3I_Comm_create_hook(comm_)
 #define MPID_Dev_comm_destroy_hook(comm_) MPIDI_CH3I_Comm_destroy_hook(comm_)
 
+#ifndef HAVE_MPIDI_VCRT
+#define HAVE_MPIDI_VCRT
+typedef struct MPIDI_VC * MPIDI_VCR;
+#endif
+
 typedef struct MPIDI_CH3I_comm
 {
     int eager_max_msg_sz;   /* comm-wide eager/rendezvous message threshold */
@@ -174,6 +179,14 @@ typedef struct MPIDI_CH3I_comm
     int waiting_for_revoke; /* The number of other processes from which we are
                              * waiting for a revoke message before we can release
                              * the context id */
+
+    int is_disconnected;    /* set to TRUE if this communicator was
+                             * disconnected as a part of
+                             * MPI_COMM_DISCONNECT; FALSE otherwise. */
+
+    struct MPIDI_VCRT *vcrt;          /* virtual connecton reference table */
+    struct MPIDI_VCRT *local_vcrt;    /* local virtual connecton reference table */
+
     struct MPID_Comm *next; /* next pointer for list of communicators */
     struct MPID_Comm *prev; /* prev pointer for list of communicators */
     MPIDI_CH3I_CH_comm_t ch;
@@ -182,12 +195,6 @@ MPIDI_CH3I_comm_t;
 
 #define MPID_DEV_COMM_DECL MPIDI_CH3I_comm_t dev;
 
-#ifndef HAVE_MPIDI_VCRT
-#define HAVE_MPIDI_VCRT
-typedef struct MPIDI_VCRT * MPID_VCRT;
-typedef struct MPIDI_VC * MPID_VCR;
-#endif
-
 #ifndef DEFINED_REQ
 #define DEFINED_REQ
 #if defined(MPID_USE_SEQUENCE_NUMBERS)
diff --git a/src/mpid/ch3/src/ch3u_comm.c b/src/mpid/ch3/src/ch3u_comm.c
index 8d2c524..13e94c3 100644
--- a/src/mpid/ch3/src/ch3u_comm.c
+++ b/src/mpid/ch3/src/ch3u_comm.c
@@ -118,6 +118,66 @@ int MPIDI_CH3I_Comm_init(void)
 }
 
 
+static void dup_vcrt(struct MPIDI_VCRT *src_vcrt, struct MPIDI_VCRT **dest_vcrt,
+                     MPIR_Comm_map_t *mapper, int src_comm_size, int vcrt_size,
+                     int vcrt_offset)
+{
+    int flag, i;
+
+    /* try to find the simple case where the new comm is a simple
+     * duplicate of the previous comm.  in that case, we simply add a
+     * reference to the previous VCRT instead of recreating it. */
+    if (mapper->type == MPIR_COMM_MAP_DUP && src_comm_size == vcrt_size) {
+        *dest_vcrt = src_vcrt;
+        MPIDI_VCRT_Add_ref(src_vcrt);
+        return;
+    }
+    else if (mapper->type == MPIR_COMM_MAP_IRREGULAR &&
+             mapper->src_mapping_size == vcrt_size) {
+        /* if the mapping array is exactly the same as the original
+         * comm's VC list, there is no need to create a new VCRT.
+         * instead simply point to the original comm's VCRT and bump
+         * up it's reference count */
+        flag = 1;
+        for (i = 0; i < mapper->src_mapping_size; i++)
+            if (mapper->src_mapping[i] != i)
+                flag = 0;
+
+        if (flag) {
+            *dest_vcrt = src_vcrt;
+            MPIDI_VCRT_Add_ref(src_vcrt);
+            return;
+        }
+    }
+
+    /* we are in the more complex case where we need to allocate a new
+     * VCRT */
+
+    if (!vcrt_offset)
+        MPIDI_VCRT_Create(vcrt_size, dest_vcrt);
+
+    if (mapper->type == MPIR_COMM_MAP_DUP) {
+        for (i = 0; i < src_comm_size; i++)
+            MPIDI_VCR_Dup(src_vcrt->vcr_table[i],
+                          &((*dest_vcrt)->vcr_table[i + vcrt_offset]));
+    }
+    else {
+        for (i = 0; i < mapper->src_mapping_size; i++)
+            MPIDI_VCR_Dup(src_vcrt->vcr_table[mapper->src_mapping[i]],
+                          &((*dest_vcrt)->vcr_table[i + vcrt_offset]));
+    }
+}
+
+static inline int map_size(MPIR_Comm_map_t map)
+{
+    if (map.type == MPIR_COMM_MAP_IRREGULAR)
+        return map.src_mapping_size;
+    else if (map.dir == MPIR_COMM_MAP_DIR_L2L || map.dir == MPIR_COMM_MAP_DIR_L2R)
+        return map.src_comm->local_size;
+    else
+        return map.src_comm->remote_size;
+}
+
 #undef FUNCNAME
 #define FUNCNAME MPIDI_CH3U_Comm_create_hook
 #undef FCNAME
@@ -126,11 +186,120 @@ int MPIDI_CH3I_Comm_create_hook(MPID_Comm *comm)
 {
     int mpi_errno = MPI_SUCCESS;
     hook_elt *elt;
+    MPIR_Comm_map_t *mapper;
+    MPID_Comm *src_comm;
+    int vcrt_size, vcrt_offset;
     
     MPIDI_STATE_DECL(MPID_STATE_MPIDI_CH3U_COMM_CREATE_HOOK);
 
     MPIDI_FUNC_ENTER(MPID_STATE_MPIDI_CH3U_COMM_CREATE_HOOK);
 
+    /* initialize the is_disconnected variable to FALSE.  this will be
+     * set to TRUE if the communicator is freed by an
+     * MPI_COMM_DISCONNECT call. */
+    comm->dev.is_disconnected = 0;
+
+    /* do some sanity checks */
+    MPL_LL_FOREACH(comm->mapper_head, mapper) {
+        if (mapper->src_comm->comm_kind == MPID_INTRACOMM)
+            MPIU_Assert(mapper->dir == MPIR_COMM_MAP_DIR_L2L ||
+                        mapper->dir == MPIR_COMM_MAP_DIR_L2R);
+        if (comm->comm_kind == MPID_INTRACOMM)
+            MPIU_Assert(mapper->dir == MPIR_COMM_MAP_DIR_L2L ||
+                        mapper->dir == MPIR_COMM_MAP_DIR_R2L);
+    }
+
+    /* First, handle all the mappers that contribute to the local part
+     * of the comm */
+    vcrt_size = 0;
+    MPL_LL_FOREACH(comm->mapper_head, mapper) {
+        if (mapper->dir == MPIR_COMM_MAP_DIR_L2R ||
+            mapper->dir == MPIR_COMM_MAP_DIR_R2R)
+            continue;
+
+        vcrt_size += map_size(*mapper);
+    }
+    vcrt_offset = 0;
+    MPL_LL_FOREACH(comm->mapper_head, mapper) {
+        src_comm = mapper->src_comm;
+
+        if (mapper->dir == MPIR_COMM_MAP_DIR_L2R ||
+            mapper->dir == MPIR_COMM_MAP_DIR_R2R)
+            continue;
+
+        if (mapper->dir == MPIR_COMM_MAP_DIR_L2L) {
+            if (src_comm->comm_kind == MPID_INTRACOMM && comm->comm_kind == MPID_INTRACOMM) {
+                dup_vcrt(src_comm->dev.vcrt, &comm->dev.vcrt, mapper, mapper->src_comm->local_size,
+                         vcrt_size, vcrt_offset);
+            }
+            else if (src_comm->comm_kind == MPID_INTRACOMM && comm->comm_kind == MPID_INTERCOMM)
+                dup_vcrt(src_comm->dev.vcrt, &comm->dev.local_vcrt, mapper, mapper->src_comm->local_size,
+                         vcrt_size, vcrt_offset);
+            else if (src_comm->comm_kind == MPID_INTERCOMM && comm->comm_kind == MPID_INTRACOMM) {
+                dup_vcrt(src_comm->dev.local_vcrt, &comm->dev.vcrt, mapper, mapper->src_comm->local_size,
+                         vcrt_size, vcrt_offset);
+            }
+            else
+                dup_vcrt(src_comm->dev.local_vcrt, &comm->dev.local_vcrt, mapper,
+                         mapper->src_comm->local_size, vcrt_size, vcrt_offset);
+        }
+        else {  /* mapper->dir == MPIR_COMM_MAP_DIR_R2L */
+            MPIU_Assert(src_comm->comm_kind == MPID_INTERCOMM);
+            if (comm->comm_kind == MPID_INTRACOMM) {
+                dup_vcrt(src_comm->dev.vcrt, &comm->dev.vcrt, mapper, mapper->src_comm->remote_size,
+                         vcrt_size, vcrt_offset);
+            }
+            else
+                dup_vcrt(src_comm->dev.vcrt, &comm->dev.local_vcrt, mapper, mapper->src_comm->remote_size,
+                         vcrt_size, vcrt_offset);
+        }
+        vcrt_offset += map_size(*mapper);
+    }
+
+    /* Next, handle all the mappers that contribute to the remote part
+     * of the comm (only valid for intercomms) */
+    vcrt_size = 0;
+    MPL_LL_FOREACH(comm->mapper_head, mapper) {
+        if (mapper->dir == MPIR_COMM_MAP_DIR_L2L ||
+            mapper->dir == MPIR_COMM_MAP_DIR_R2L)
+            continue;
+
+        vcrt_size += map_size(*mapper);
+    }
+    vcrt_offset = 0;
+    MPL_LL_FOREACH(comm->mapper_head, mapper) {
+        src_comm = mapper->src_comm;
+
+        if (mapper->dir == MPIR_COMM_MAP_DIR_L2L ||
+            mapper->dir == MPIR_COMM_MAP_DIR_R2L)
+            continue;
+
+        MPIU_Assert(comm->comm_kind == MPID_INTERCOMM);
+
+        if (mapper->dir == MPIR_COMM_MAP_DIR_L2R) {
+            if (src_comm->comm_kind == MPID_INTRACOMM)
+                dup_vcrt(src_comm->dev.vcrt, &comm->dev.vcrt, mapper, mapper->src_comm->local_size,
+                         vcrt_size, vcrt_offset);
+            else
+                dup_vcrt(src_comm->dev.local_vcrt, &comm->dev.vcrt, mapper,
+                         mapper->src_comm->local_size, vcrt_size, vcrt_offset);
+        }
+        else {  /* mapper->dir == MPIR_COMM_MAP_DIR_R2R */
+            MPIU_Assert(src_comm->comm_kind == MPID_INTERCOMM);
+            dup_vcrt(src_comm->dev.vcrt, &comm->dev.vcrt, mapper, mapper->src_comm->remote_size,
+                     vcrt_size, vcrt_offset);
+        }
+        vcrt_offset += map_size(*mapper);
+    }
+
+    if (comm->comm_kind == MPID_INTERCOMM) {
+        /* setup the vcrt for the local_comm in the intercomm */
+        if (comm->local_comm) {
+            comm->local_comm->dev.vcrt = comm->dev.local_vcrt;
+            MPIDI_VCRT_Add_ref(comm->dev.local_vcrt);
+        }
+    }
+
     MPL_LL_FOREACH(create_hooks_head, elt) {
         mpi_errno = elt->hook_fn(comm, elt->param);
         if (mpi_errno) MPIU_ERR_POP(mpi_errno);;
@@ -160,6 +329,14 @@ int MPIDI_CH3I_Comm_destroy_hook(MPID_Comm *comm)
         if (mpi_errno) MPIU_ERR_POP(mpi_errno);
     }
 
+    mpi_errno = MPIDI_VCRT_Release(comm->dev.vcrt, comm->dev.is_disconnected);
+    if (mpi_errno) MPIU_ERR_POP(mpi_errno);
+
+    if (comm->comm_kind == MPID_INTERCOMM) {
+        mpi_errno = MPIDI_VCRT_Release(comm->dev.local_vcrt, comm->dev.is_disconnected);
+        if (mpi_errno) MPIU_ERR_POP(mpi_errno);
+    }
+
  fn_exit:
     MPIDI_FUNC_EXIT(MPID_STATE_MPIDI_CH3U_COMM_DESTROY_HOOK);
     return mpi_errno;
diff --git a/src/mpid/ch3/src/ch3u_port.c b/src/mpid/ch3/src/ch3u_port.c
index d982acd..9a4aa93 100644
--- a/src/mpid/ch3/src/ch3u_port.c
+++ b/src/mpid/ch3/src/ch3u_port.c
@@ -280,28 +280,23 @@ static int MPIDI_CH3I_Initialize_tmp_comm(MPID_Comm **comm_pptr,
     /* No pg structure needed since vc has already been set up 
        (connection has been established). */
 
-    /* Point local vcr, vcrt at those of commself_ptr */
+    /* Point local vcrt at those of commself_ptr */
     /* FIXME: Explain why */
-    tmp_comm->local_vcrt = commself_ptr->vcrt;
-    MPID_VCRT_Add_ref(commself_ptr->vcrt);
-    tmp_comm->local_vcr  = commself_ptr->vcr;
+    tmp_comm->dev.local_vcrt = commself_ptr->dev.vcrt;
+    MPIDI_VCRT_Add_ref(commself_ptr->dev.vcrt);
 
     /* No pg needed since connection has already been formed. 
        FIXME - ensure that the comm_release code does not try to
        free an unallocated pg */
 
     /* Set up VC reference table */
-    mpi_errno = MPID_VCRT_Create(tmp_comm->remote_size, &tmp_comm->vcrt);
+    mpi_errno = MPIDI_VCRT_Create(tmp_comm->remote_size, &tmp_comm->dev.vcrt);
     if (mpi_errno != MPI_SUCCESS) {
 	MPIU_ERR_SETANDJUMP(mpi_errno,MPI_ERR_OTHER, "**init_vcrt");
     }
-    mpi_errno = MPID_VCRT_Get_ptr(tmp_comm->vcrt, &tmp_comm->vcr);
-    if (mpi_errno != MPI_SUCCESS) {
-	MPIU_ERR_SETANDJUMP(mpi_errno,MPI_ERR_OTHER, "**init_getptr");
-    }
 
     /* FIXME: Why do we do a dup here? */
-    MPID_VCR_Dup(vc_ptr, tmp_comm->vcr);
+    MPIDI_VCR_Dup(vc_ptr, &tmp_comm->dev.vcrt->vcr_table[0]);
 
     /* Even though this is a tmp comm and we don't call
        MPI_Comm_commit, we still need to call the creation hook
@@ -506,7 +501,7 @@ int MPIDI_Comm_connect(const char *port_name, MPID_Info *info, int root,
         }
 
         /* All communication with remote root done. Release the communicator. */
-        MPIR_Comm_release(tmp_comm,0);
+        MPIR_Comm_release(tmp_comm);
     }
 
     /*printf("connect:barrier\n");fflush(stdout);*/
@@ -606,19 +601,19 @@ static int ExtractLocalPGInfo( MPID_Comm *comm_p,
     MPIU_CHKPMEM_MALLOC(pg_list,pg_node*,sizeof(pg_node),mpi_errno,
 			"pg_list");
     
-    pg_list->pg_id = MPIU_Strdup(comm_p->vcr[0]->pg->id);
+    pg_list->pg_id = MPIU_Strdup(comm_p->dev.vcrt->vcr_table[0]->pg->id);
     pg_list->index = cur_index++;
     pg_list->next = NULL;
     /* XXX DJG FIXME-MT should we be checking this?  the add/release macros already check this */
-    MPIU_Assert( MPIU_Object_get_ref(comm_p->vcr[0]->pg));
-    mpi_errno = MPIDI_PG_To_string(comm_p->vcr[0]->pg, &pg_list->str, 
+    MPIU_Assert( MPIU_Object_get_ref(comm_p->dev.vcrt->vcr_table[0]->pg));
+    mpi_errno = MPIDI_PG_To_string(comm_p->dev.vcrt->vcr_table[0]->pg, &pg_list->str,
 				   &pg_list->lenStr );
     if (mpi_errno != MPI_SUCCESS) {
 	MPIU_ERR_POP(mpi_errno);
     }
     MPIU_DBG_STMT(CH3_CONNECT,VERBOSE,MPIDI_PrintConnStr(__FILE__,__LINE__,"PG as string is", pg_list->str ));
     local_translation[0].pg_index = 0;
-    local_translation[0].pg_rank = comm_p->vcr[0]->pg_rank;
+    local_translation[0].pg_rank = comm_p->dev.vcrt->vcr_table[0]->pg_rank;
     pg_iter = pg_list;
     for (i=1; i<local_comm_size; i++) {
 	pg_iter = pg_list;
@@ -626,10 +621,10 @@ static int ExtractLocalPGInfo( MPID_Comm *comm_p,
 	while (pg_iter != NULL) {
 	    /* Check to ensure pg is (probably) valid */
             /* XXX DJG FIXME-MT should we be checking this?  the add/release macros already check this */
-	    MPIU_Assert(MPIU_Object_get_ref(comm_p->vcr[i]->pg) != 0);
-	    if (MPIDI_PG_Id_compare(comm_p->vcr[i]->pg->id, pg_iter->pg_id)) {
+	    MPIU_Assert(MPIU_Object_get_ref(comm_p->dev.vcrt->vcr_table[i]->pg) != 0);
+	    if (MPIDI_PG_Id_compare(comm_p->dev.vcrt->vcr_table[i]->pg->id, pg_iter->pg_id)) {
 		local_translation[i].pg_index = pg_iter->index;
-		local_translation[i].pg_rank  = comm_p->vcr[i]->pg_rank;
+		local_translation[i].pg_rank  = comm_p->dev.vcrt->vcr_table[i]->pg_rank;
 		break;
 	    }
 	    if (pg_trailer != pg_iter)
@@ -643,16 +638,16 @@ static int ExtractLocalPGInfo( MPID_Comm *comm_p,
 	    if (!pg_iter) {
 		MPIU_ERR_POP(mpi_errno);
 	    }
-	    pg_iter->pg_id = MPIU_Strdup(comm_p->vcr[i]->pg->id);
+	    pg_iter->pg_id = MPIU_Strdup(comm_p->dev.vcrt->vcr_table[i]->pg->id);
 	    pg_iter->index = cur_index++;
 	    pg_iter->next = NULL;
-	    mpi_errno = MPIDI_PG_To_string(comm_p->vcr[i]->pg, &pg_iter->str,
+	    mpi_errno = MPIDI_PG_To_string(comm_p->dev.vcrt->vcr_table[i]->pg, &pg_iter->str,
 					   &pg_iter->lenStr );
 	    if (mpi_errno != MPI_SUCCESS) {
 		MPIU_ERR_POP(mpi_errno);
 	    }
 	    local_translation[i].pg_index = pg_iter->index;
-	    local_translation[i].pg_rank = comm_p->vcr[i]->pg_rank;
+	    local_translation[i].pg_rank = comm_p->dev.vcrt->vcr_table[i]->pg_rank;
 	    pg_trailer->next = pg_iter;
 	}
     }
@@ -1095,7 +1090,7 @@ int MPIDI_Comm_accept(const char *port_name, MPID_Info *info, int root,
         }
 
         /* All communication with remote root done. Release the communicator. */
-        MPIR_Comm_release(tmp_comm,0);
+        MPIR_Comm_release(tmp_comm);
     }
 
     MPIU_DBG_MSG(CH3_CONNECT,VERBOSE,"Barrier");
@@ -1169,23 +1164,18 @@ static int SetupNewIntercomm( MPID_Comm *comm_ptr, int remote_comm_size,
     intercomm->local_comm   = NULL;
     intercomm->coll_fns     = NULL;
 
-    /* Point local vcr, vcrt at those of incoming intracommunicator */
-    intercomm->local_vcrt = comm_ptr->vcrt;
-    MPID_VCRT_Add_ref(comm_ptr->vcrt);
-    intercomm->local_vcr  = comm_ptr->vcr;
+    /* Point local vcrt at those of incoming intracommunicator */
+    intercomm->dev.local_vcrt = comm_ptr->dev.vcrt;
+    MPIDI_VCRT_Add_ref(comm_ptr->dev.vcrt);
 
     /* Set up VC reference table */
-    mpi_errno = MPID_VCRT_Create(intercomm->remote_size, &intercomm->vcrt);
+    mpi_errno = MPIDI_VCRT_Create(intercomm->remote_size, &intercomm->dev.vcrt);
     if (mpi_errno != MPI_SUCCESS) {
 	MPIU_ERR_SETANDJUMP(mpi_errno,MPI_ERR_OTHER, "**init_vcrt");
     }
-    mpi_errno = MPID_VCRT_Get_ptr(intercomm->vcrt, &intercomm->vcr);
-    if (mpi_errno != MPI_SUCCESS) {
-	MPIU_ERR_SETANDJUMP(mpi_errno,MPI_ERR_OTHER, "**init_getptr");
-    }
     for (i=0; i < intercomm->remote_size; i++) {
 	MPIDI_PG_Dup_vcr(remote_pg[remote_translation[i].pg_index], 
-			 remote_translation[i].pg_rank, &intercomm->vcr[i]);
+			 remote_translation[i].pg_rank, &intercomm->dev.vcrt->vcr_table[i]);
     }
 
     mpi_errno = MPIR_Comm_commit(intercomm);
diff --git a/src/mpid/ch3/src/ch3u_request.c b/src/mpid/ch3/src/ch3u_request.c
index 251024e..63e444c 100644
--- a/src/mpid/ch3/src/ch3u_request.c
+++ b/src/mpid/ch3/src/ch3u_request.c
@@ -667,7 +667,7 @@ void MPID_Request_release(MPID_Request *req)
         /* FIXME: We need a way to call these routines ONLY when the
            related ref count has become zero. */
         if (req->comm != NULL) {
-            MPIR_Comm_release(req->comm, 0);
+            MPIR_Comm_release(req->comm);
         }
 
         if (req->greq_fns != NULL) {
diff --git a/src/mpid/ch3/src/mpid_comm_disconnect.c b/src/mpid/ch3/src/mpid_comm_disconnect.c
index 8553f65..d7a0d87 100644
--- a/src/mpid/ch3/src/mpid_comm_disconnect.c
+++ b/src/mpid/ch3/src/mpid_comm_disconnect.c
@@ -37,7 +37,8 @@ int MPID_Comm_disconnect(MPID_Comm *comm_ptr)
     /* it's more than a comm_release, but ok for now */
     /* FIXME: Describe what more might be required */
     /* MPIU_PG_Printall( stdout ); */
-    mpi_errno = MPIR_Comm_release(comm_ptr,1);
+    comm_ptr->dev.is_disconnected = 1;
+    mpi_errno = MPIR_Comm_release(comm_ptr);
     if (mpi_errno) MPIU_ERR_POP(mpi_errno);
     /* If any of the VCs were released by this Comm_release, wait
      for those close operations to complete */
diff --git a/src/mpid/ch3/src/mpid_comm_revoke.c b/src/mpid/ch3/src/mpid_comm_revoke.c
index 2d88ddc..c0e5304 100644
--- a/src/mpid/ch3/src/mpid_comm_revoke.c
+++ b/src/mpid/ch3/src/mpid_comm_revoke.c
@@ -75,7 +75,7 @@ int MPID_Comm_revoke(MPID_Comm *comm_ptr, int is_remote)
 
         /* Check to see if we are done revoking */
         if (comm_ptr->dev.waiting_for_revoke == 0) {
-            MPIR_Comm_release(comm_ptr, 0);
+            MPIR_Comm_release(comm_ptr);
         }
 
         /* Go clean up all of the existing operations involving this
@@ -94,7 +94,7 @@ int MPID_Comm_revoke(MPID_Comm *comm_ptr, int is_remote)
 
         /* Check to see if we are done revoking */
         if (comm_ptr->dev.waiting_for_revoke == 0) {
-            MPIR_Comm_release(comm_ptr, 0);
+            MPIR_Comm_release(comm_ptr);
         }
     }
 
diff --git a/src/mpid/ch3/src/mpid_finalize.c b/src/mpid/ch3/src/mpid_finalize.c
index 48abc26..e41c27d 100644
--- a/src/mpid/ch3/src/mpid_finalize.c
+++ b/src/mpid/ch3/src/mpid_finalize.c
@@ -113,14 +113,14 @@ int MPID_Finalize(void)
     if (mpi_errno) { MPIU_ERR_POP(mpi_errno); }
 
 #ifdef MPID_NEEDS_ICOMM_WORLD
-    mpi_errno = MPIR_Comm_release_always(MPIR_Process.icomm_world, 0);
+    mpi_errno = MPIR_Comm_release_always(MPIR_Process.icomm_world);
     if (mpi_errno) MPIU_ERR_POP(mpi_errno);
 #endif
 
-    mpi_errno = MPIR_Comm_release_always(MPIR_Process.comm_self, 0);
+    mpi_errno = MPIR_Comm_release_always(MPIR_Process.comm_self);
     if (mpi_errno) MPIU_ERR_POP(mpi_errno);
 
-    mpi_errno = MPIR_Comm_release_always(MPIR_Process.comm_world, 0);
+    mpi_errno = MPIR_Comm_release_always(MPIR_Process.comm_world);
     if (mpi_errno) MPIU_ERR_POP(mpi_errno);
 
     /* Tell the process group code that we're done with the process groups.
diff --git a/src/mpid/ch3/src/mpid_init.c b/src/mpid/ch3/src/mpid_init.c
index e07f24b..1b8ffff 100644
--- a/src/mpid/ch3/src/mpid_init.c
+++ b/src/mpid/ch3/src/mpid_init.c
@@ -206,25 +206,18 @@ int MPID_Init(int *argc, char ***argv, int requested, int *provided,
     comm->remote_size = pg_size;
     comm->local_size  = pg_size;
     
-    mpi_errno = MPID_VCRT_Create(comm->remote_size, &comm->vcrt);
+    mpi_errno = MPIDI_VCRT_Create(comm->remote_size, &comm->dev.vcrt);
     if (mpi_errno != MPI_SUCCESS)
     {
 	MPIU_ERR_SETANDJUMP1(mpi_errno,MPI_ERR_OTHER,"**dev|vcrt_create", 
 			     "**dev|vcrt_create %s", "MPI_COMM_WORLD");
     }
-    
-    mpi_errno = MPID_VCRT_Get_ptr(comm->vcrt, &comm->vcr);
-    if (mpi_errno != MPI_SUCCESS)
-    {
-	MPIU_ERR_SETANDJUMP1(mpi_errno,MPI_ERR_OTHER,"**dev|vcrt_get_ptr", 
-			     "dev|vcrt_get_ptr %s", "MPI_COMM_WORLD");
-    }
-    
+
     /* Initialize the connection table on COMM_WORLD from the process group's
        connection table */
     for (p = 0; p < pg_size; p++)
     {
-	MPID_VCR_Dup(&pg->vct[p], &comm->vcr[p]);
+	MPIDI_VCR_Dup(&pg->vct[p], &comm->dev.vcrt->vcr_table[p]);
     }
 
     mpi_errno = MPIR_Comm_commit(comm);
@@ -238,21 +231,14 @@ int MPID_Init(int *argc, char ***argv, int requested, int *provided,
     comm->remote_size = 1;
     comm->local_size  = 1;
     
-    mpi_errno = MPID_VCRT_Create(comm->remote_size, &comm->vcrt);
+    mpi_errno = MPIDI_VCRT_Create(comm->remote_size, &comm->dev.vcrt);
     if (mpi_errno != MPI_SUCCESS)
     {
 	MPIU_ERR_SETANDJUMP1(mpi_errno,MPI_ERR_OTHER, "**dev|vcrt_create", 
 			     "**dev|vcrt_create %s", "MPI_COMM_SELF");
     }
     
-    mpi_errno = MPID_VCRT_Get_ptr(comm->vcrt, &comm->vcr);
-    if (mpi_errno != MPI_SUCCESS)
-    {
-	MPIU_ERR_SETANDJUMP1(mpi_errno,MPI_ERR_OTHER, "**dev|vcrt_get_ptr", 
-			     "dev|vcrt_get_ptr %s", "MPI_COMM_WORLD");
-    }
-    
-    MPID_VCR_Dup(&pg->vct[pg_rank], &comm->vcr[0]);
+    MPIDI_VCR_Dup(&pg->vct[pg_rank], &comm->dev.vcrt->vcr_table[0]);
 
     mpi_errno = MPIR_Comm_commit(comm);
     if (mpi_errno) MPIU_ERR_POP(mpi_errno);
@@ -268,9 +254,8 @@ int MPID_Init(int *argc, char ***argv, int requested, int *provided,
     comm->rank        = pg_rank;
     comm->remote_size = pg_size;
     comm->local_size  = pg_size;
-    MPID_VCRT_Add_ref( MPIR_Process.comm_world->vcrt );
-    comm->vcrt = MPIR_Process.comm_world->vcrt;
-    comm->vcr  = MPIR_Process.comm_world->vcr;
+    MPIDI_VCRT_Add_ref( MPIR_Process.comm_world->dev.vcrt );
+    comm->dev.vcrt = MPIR_Process.comm_world->dev.vcrt;
     
     mpi_errno = MPIR_Comm_commit(comm);
     if (mpi_errno) MPIU_ERR_POP(mpi_errno);
diff --git a/src/mpid/ch3/src/mpid_vc.c b/src/mpid/ch3/src/mpid_vc.c
index 1de638b..1fad710 100644
--- a/src/mpid/ch3/src/mpid_vc.c
+++ b/src/mpid/ch3/src/mpid_vc.c
@@ -66,24 +66,6 @@ cvars:
 === END_MPI_T_CVAR_INFO_BLOCK ===
 */
 
-/*S
- * MPIDI_VCRT - virtual connection reference table
- *
- * handle - this element is not used, but exists so that we may use the 
- * MPIU_Object routines for reference counting
- *
- * ref_count - number of references to this table
- *
- * vcr_table - array of virtual connection references
- S*/
-typedef struct MPIDI_VCRT
-{
-    MPIU_OBJECT_HEADER; /* adds handle and ref_count fields */
-    int size;
-    MPIDI_VC_t * vcr_table[1];
-}
-MPIDI_VCRT_t;
-
 /* What is the arrangement of VCRT and VCR and VC? 
    
    Each VC (the virtual connection itself) is refered to by a reference 
@@ -97,25 +79,25 @@ MPIDI_VCRT_t;
  */
 
 /*@
-  MPID_VCRT_Create - Create a table of VC references
+  MPIDI_VCRT_Create - Create a table of VC references
 
   Notes:
   This routine only provides space for the VC references.  Those should
   be added by assigning to elements of the vc array within the 
-  'MPID_VCRT' object.
+  'MPIDI_VCRT' object.
   @*/
 #undef FUNCNAME
-#define FUNCNAME MPID_VCRT_Create
+#define FUNCNAME MPIDI_VCRT_Create
 #undef FCNAME
 #define FCNAME MPIU_QUOTE(FUNCNAME)
-int MPID_VCRT_Create(int size, MPID_VCRT *vcrt_ptr)
+int MPIDI_VCRT_Create(int size, struct MPIDI_VCRT **vcrt_ptr)
 {
     MPIDI_VCRT_t * vcrt;
     int mpi_errno = MPI_SUCCESS;
     MPIU_CHKPMEM_DECL(1);
-    MPIDI_STATE_DECL(MPID_STATE_MPID_VCRT_CREATE);
+    MPIDI_STATE_DECL(MPID_STATE_MPIDI_VCRT_CREATE);
 
-    MPIDI_FUNC_ENTER(MPID_STATE_MPID_VCRT_CREATE);
+    MPIDI_FUNC_ENTER(MPID_STATE_MPIDI_VCRT_CREATE);
 
     MPIU_CHKPMEM_MALLOC(vcrt, MPIDI_VCRT_t *, sizeof(MPIDI_VCRT_t) + (size - 1) * sizeof(MPIDI_VC_t *),	mpi_errno, "**nomem");
     vcrt->handle = HANDLE_SET_KIND(0, HANDLE_KIND_INVALID);
@@ -125,7 +107,7 @@ int MPID_VCRT_Create(int size, MPID_VCRT *vcrt_ptr)
 
  fn_exit:
     MPIU_CHKPMEM_COMMIT();
-    MPIDI_FUNC_EXIT(MPID_STATE_MPID_VCRT_CREATE);
+    MPIDI_FUNC_EXIT(MPID_STATE_MPIDI_VCRT_CREATE);
     return mpi_errno;
  fn_fail:
     /* --BEGIN ERROR HANDLING-- */
@@ -135,7 +117,7 @@ int MPID_VCRT_Create(int size, MPID_VCRT *vcrt_ptr)
 }
 
 /*@
-  MPID_VCRT_Add_ref - Add a reference to a VC reference table
+  MPIDI_VCRT_Add_ref - Add a reference to a VC reference table
 
   Notes:
   This is called when a communicator duplicates its group of processes.
@@ -144,39 +126,39 @@ int MPID_VCRT_Create(int size, MPID_VCRT *vcrt_ptr)
   virtural connections (VCs).
   @*/
 #undef FUNCNAME
-#define FUNCNAME MPID_VCRT_Add_ref
+#define FUNCNAME MPIDI_VCRT_Add_ref
 #undef FCNAME
 #define FCNAME MPIU_QUOTE(FUNCNAME)
-int MPID_VCRT_Add_ref(MPID_VCRT vcrt)
+int MPIDI_VCRT_Add_ref(struct MPIDI_VCRT *vcrt)
 {
-    MPIDI_STATE_DECL(MPID_STATE_MPID_VCRT_ADD_REF);
+    MPIDI_STATE_DECL(MPID_STATE_MPIDI_VCRT_ADD_REF);
 
-    MPIDI_FUNC_ENTER(MPID_STATE_MPID_VCRT_ADD_REF);
+    MPIDI_FUNC_ENTER(MPID_STATE_MPIDI_VCRT_ADD_REF);
     MPIU_Object_add_ref(vcrt);
     MPIU_DBG_MSG_FMT(REFCOUNT,TYPICAL,(MPIU_DBG_FDEST, "Incr VCRT %p ref count",vcrt));
-    MPIDI_FUNC_EXIT(MPID_STATE_MPID_VCRT_ADD_REF);
+    MPIDI_FUNC_EXIT(MPID_STATE_MPIDI_VCRT_ADD_REF);
     return MPI_SUCCESS;
 }
 
 /* FIXME: What should this do?  See proc group and vc discussion */
 
 /*@
-  MPID_VCRT_Release - Release a reference to a VC reference table
+  MPIDI_VCRT_Release - Release a reference to a VC reference table
 
   Notes:
   
   @*/
 #undef FUNCNAME
-#define FUNCNAME MPID_VCRT_Release
+#define FUNCNAME MPIDI_VCRT_Release
 #undef FCNAME
 #define FCNAME MPIU_QUOTE(FUNCNAME)
-int MPID_VCRT_Release(MPID_VCRT vcrt, int isDisconnect )
+int MPIDI_VCRT_Release(struct MPIDI_VCRT *vcrt, int isDisconnect )
 {
     int in_use;
     int mpi_errno = MPI_SUCCESS;
-    MPIDI_STATE_DECL(MPID_STATE_MPID_VCRT_RELEASE);
+    MPIDI_STATE_DECL(MPID_STATE_MPIDI_VCRT_RELEASE);
 
-    MPIDI_FUNC_ENTER(MPID_STATE_MPID_VCRT_RELEASE);
+    MPIDI_FUNC_ENTER(MPID_STATE_MPIDI_VCRT_RELEASE);
 
     MPIU_Object_release_ref(vcrt, &in_use);
     MPIU_DBG_MSG_FMT(REFCOUNT,TYPICAL,(MPIU_DBG_FDEST, "Decr VCRT %p ref count",vcrt));
@@ -262,37 +244,14 @@ int MPID_VCRT_Release(MPID_VCRT vcrt, int isDisconnect )
     }
 
  fn_exit:    
-    MPIDI_FUNC_EXIT(MPID_STATE_MPID_VCRT_RELEASE);
+    MPIDI_FUNC_EXIT(MPID_STATE_MPIDI_VCRT_RELEASE);
     return mpi_errno;
  fn_fail:
     goto fn_exit;
 }
 
 /*@
-  MPID_VCRT_Get_ptr - Return a pointer to the array of VCs for this 
-  reference table
-
-  Notes:
-  This routine is always used with MPID_VCRT_Create and should be 
-  combined with it.
-
-  @*/
-#undef FUNCNAME
-#define FUNCNAME MPID_VCRT_Get_ptr
-#undef FCNAME
-#define FCNAME MPIU_QUOTE(FUNCNAME)
-int MPID_VCRT_Get_ptr(MPID_VCRT vcrt, MPID_VCR **vc_pptr)
-{
-    MPIDI_STATE_DECL(MPID_STATE_MPID_VCRT_GET_PTR);
-
-    MPIDI_FUNC_ENTER(MPID_STATE_MPID_VCRT_GET_PTR);
-    *vc_pptr = vcrt->vcr_table;
-    MPIDI_FUNC_EXIT(MPID_STATE_MPID_VCRT_GET_PTR);
-    return MPI_SUCCESS;
-}
-
-/*@
-  MPID_VCR_Dup - Duplicate a virtual connection reference 
+  MPIDI_VCR_Dup - Duplicate a virtual connection reference
 
   Notes:
   If the VC is being used for the first time in a VC reference
@@ -306,10 +265,10 @@ int MPID_VCRT_Get_ptr(MPID_VCRT vcrt, MPID_VCR **vc_pptr)
   
   @*/
 #undef FUNCNAME
-#define FUNCNAME MPID_VCR_Dup
+#define FUNCNAME MPIDI_VCR_Dup
 #undef FCNAME
 #define FCNAME MPIU_QUOTE(FUNCNAME)
-int MPID_VCR_Dup(MPID_VCR orig_vcr, MPID_VCR * new_vcr)
+int MPIDI_VCR_Dup(MPIDI_VCR orig_vcr, MPIDI_VCR * new_vcr)
 {
     MPIDI_STATE_DECL(MPID_STATE_MPID_VCR_DUP);
 
@@ -335,18 +294,25 @@ int MPID_VCR_Dup(MPID_VCR orig_vcr, MPID_VCR * new_vcr)
 }
 
 /*@
-  MPID_VCR_Get_lpid - Get the local process ID for a given VC reference
+  MPID_Comm_get_lpid - Get the local process ID for a given VC reference
   @*/
 #undef FUNCNAME
-#define FUNCNAME MPID_VCR_Get_lpid
+#define FUNCNAME MPID_Comm_get_lpid
 #undef FCNAME
 #define FCNAME MPIU_QUOTE(FUNCNAME)
-int MPID_VCR_Get_lpid(MPID_VCR vcr, int * lpid_ptr)
+int MPID_Comm_get_lpid(MPID_Comm *comm_ptr, int idx, int * lpid_ptr, MPIU_BOOL is_remote)
 {
     MPIDI_STATE_DECL(MPID_STATE_MPID_VCR_GET_LPID);
 
     MPIDI_FUNC_ENTER(MPID_STATE_MPID_VCR_GET_LPID);
-    *lpid_ptr = vcr->lpid;
+
+    if (comm_ptr->comm_kind == MPID_INTRACOMM)
+        *lpid_ptr = comm_ptr->dev.vcrt->vcr_table[idx]->lpid;
+    else if (is_remote)
+        *lpid_ptr = comm_ptr->dev.vcrt->vcr_table[idx]->lpid;
+    else
+        *lpid_ptr = comm_ptr->dev.local_vcrt->vcr_table[idx]->lpid;
+
     MPIDI_FUNC_EXIT(MPID_STATE_MPID_VCR_GET_LPID);
     return MPI_SUCCESS;
 }
@@ -368,7 +334,7 @@ int MPID_GPID_GetAllInComm( MPID_Comm *comm_ptr, int local_size,
     int i;
     int *gpid = local_gpids;
     int lastPGID = -1, pgid;
-    MPID_VCR vc;
+    MPIDI_VCR vc;
     MPIDI_STATE_DECL(MPID_STATE_MPID_GPID_GETALLINCOMM);
 
     MPIDI_FUNC_ENTER(MPID_STATE_MPID_GPID_GETALLINCOMM);
@@ -377,7 +343,7 @@ int MPID_GPID_GetAllInComm( MPID_Comm *comm_ptr, int local_size,
     
     *singlePG = 1;
     for (i=0; i<comm_ptr->local_size; i++) {
-	vc = comm_ptr->vcr[i];
+	vc = comm_ptr->dev.vcrt->vcr_table[i];
 
 	/* Get the process group id as an int */
 	MPIDI_PG_IdToNum( vc->pg, &pgid );
@@ -406,9 +372,9 @@ int MPID_GPID_GetAllInComm( MPID_Comm *comm_ptr, int local_size,
 int MPID_GPID_Get( MPID_Comm *comm_ptr, int rank, int gpid[] )
 {
     int      pgid;
-    MPID_VCR vc;
+    MPIDI_VCR vc;
     
-    vc = comm_ptr->vcr[rank];
+    vc = comm_ptr->dev.vcrt->vcr_table[rank];
 
     /* Get the process group id as an int */
     MPIDI_PG_IdToNum( vc->pg, &pgid );
@@ -483,19 +449,19 @@ int MPID_GPID_ToLpidArray( int size, int gpid[], int lpid[] )
 }
 
 /*@
-  MPID_VCR_CommFromLpids - Create a new communicator from a given set
+  MPID_Create_intercomm_from_lpids - Create a new communicator from a given set
   of lpids.  
 
   Notes:
   This is used to create a communicator that is not a subset of some
   existing communicator, for example, in a 'MPI_Comm_spawn' or 
-  'MPI_Comm_connect/MPI_Comm_accept'.
+  'MPI_Comm_connect/MPI_Comm_accept'.  Thus, it is only used for intercommunicators.
  @*/
 #undef FUNCNAME
-#define FUNCNAME MPID_VCR_CommFromLpids
+#define FUNCNAME MPID_Create_intercomm_from_lpids
 #undef FCNAME
 #define FCNAME MPIU_QUOTE(FUNCNAME)
-int MPID_VCR_CommFromLpids( MPID_Comm *newcomm_ptr, 
+int MPID_Create_intercomm_from_lpids( MPID_Comm *newcomm_ptr,
 			    int size, const int lpids[] )
 {
     int mpi_errno = MPI_SUCCESS;
@@ -505,8 +471,7 @@ int MPID_VCR_CommFromLpids( MPID_Comm *newcomm_ptr,
 
     commworld_ptr = MPIR_Process.comm_world;
     /* Setup the communicator's vc table: remote group */
-    MPID_VCRT_Create( size, &newcomm_ptr->vcrt );
-    MPID_VCRT_Get_ptr( newcomm_ptr->vcrt, &newcomm_ptr->vcr );
+    MPIDI_VCRT_Create( size, &newcomm_ptr->dev.vcrt );
     for (i=0; i<size; i++) {
 	MPIDI_VC_t *vc = 0;
 
@@ -518,7 +483,7 @@ int MPID_VCR_CommFromLpids( MPID_Comm *newcomm_ptr,
 	/* printf( "[%d] Remote rank %d has lpid %d\n", 
 	   MPIR_Process.comm_world->rank, i, lpids[i] ); */
 	if (lpids[i] < commworld_ptr->remote_size) {
-	    vc = commworld_ptr->vcr[lpids[i]];
+	    vc = commworld_ptr->dev.vcrt->vcr_table[lpids[i]];
 	}
 	else {
 	    /* We must find the corresponding vcr for a given lpid */	
@@ -552,7 +517,7 @@ int MPID_VCR_CommFromLpids( MPID_Comm *newcomm_ptr,
 	   (int)vc, lpids[i] ); */
 	/* Note that his will increment the ref count for the associate
 	   PG if necessary.  */
-	MPID_VCR_Dup( vc, &newcomm_ptr->vcr[i] );
+	MPIDI_VCR_Dup( vc, &newcomm_ptr->dev.vcrt->vcr_table[i] );
     }
 fn_exit:
     return mpi_errno;
@@ -697,7 +662,7 @@ char MPIU_hostname[MAX_HOSTNAME_LEN] = "_UNKNOWN_"; /* '_' is an illegal char fo
 #define FCNAME MPIU_QUOTE(FUNCNAME)
 int MPID_Get_node_id(MPID_Comm *comm, int rank, MPID_Node_id_t *id_p)
 {
-    *id_p = comm->vcr[rank]->node_id;
+    *id_p = comm->dev.vcrt->vcr_table[rank]->node_id;
     return MPI_SUCCESS;
 }
 
diff --git a/src/mpid/ch3/src/mpidi_pg.c b/src/mpid/ch3/src/mpidi_pg.c
index 4dfdc8b..f31cc27 100644
--- a/src/mpid/ch3/src/mpidi_pg.c
+++ b/src/mpid/ch3/src/mpidi_pg.c
@@ -308,7 +308,7 @@ int MPIDI_PG_Destroy(MPIDI_PG_t * pg)
 
                 MPIU_DBG_MSG_FMT(CH3_DISCONNECT, VERBOSE, (MPIU_DBG_FDEST, "about to free pg->vct=%p which contains vc=%p", pg->vct, &pg->vct[i]));
 
-                /* This used to be handled in MPID_VCRT_Release, but that was
+                /* This used to be handled in MPIDI_VCRT_Release, but that was
                    not the right place to do this.  The VC should only be freed
                    when the PG that it belongs to is freed, not just when the
                    VC's refcount drops to zero. [goodell@ 2008-06-13] */
diff --git a/src/mpid/common/hcoll/hcoll_rte.c b/src/mpid/common/hcoll/hcoll_rte.c
index 12d0c2b..2a2f174 100644
--- a/src/mpid/common/hcoll/hcoll_rte.c
+++ b/src/mpid/common/hcoll/hcoll_rte.c
@@ -288,7 +288,7 @@ static int get_ec_handles(int num_ec,
     comm = (MPID_Comm *) grp_h;
     for (i = 0; i < num_ec; i++) {
         ec_handles[i].rank = ec_indexes[i];
-        ec_handles[i].handle = (void *) (comm->vcr[ec_indexes[i]]);
+        ec_handles[i].handle = (void *) (comm->vcrt->vcr_table[ec_indexes[i]]);
     }
     return HCOLL_SUCCESS;
 }
@@ -302,7 +302,7 @@ static int get_my_ec(rte_grp_handle_t grp_h, rte_ec_handle_t * ec_handle)
     MPID_Comm *comm;
     comm = (MPID_Comm *) grp_h;
     int my_rank = MPIR_Comm_rank(comm);
-    ec_handle->handle = (void *) (comm->vcr[my_rank]);
+    ec_handle->handle = (void *) (comm->vcrt->vcr_table[my_rank]);
     ec_handle->rank = my_rank;
     return HCOLL_SUCCESS;
 }
@@ -430,5 +430,5 @@ static void coll_handle_complete(void *handle)
 #define FCNAME MPIU_QUOTE(FUNCNAME)
 static int world_rank(rte_grp_handle_t grp_h, rte_ec_handle_t ec)
 {
-    return ((MPID_VCR) ec.handle)->pg_rank;
+    return (MPIR_Process.comm_world->rank);
 }
diff --git a/src/mpid/common/sched/mpid_sched.c b/src/mpid/common/sched/mpid_sched.c
index 80ddfd9..a6e7037 100644
--- a/src/mpid/common/sched/mpid_sched.c
+++ b/src/mpid/common/sched/mpid_sched.c
@@ -852,7 +852,7 @@ static int MPIDU_Sched_progress_state(struct MPIDU_Sched_state *state, int *made
                             e->status = MPIDU_SCHED_ENTRY_STATUS_COMPLETE;
                         MPID_Request_release(e->u.send.sreq);
                         e->u.send.sreq = NULL;
-                        MPIR_Comm_release(e->u.send.comm, /*isDisconnect=*/FALSE);
+                        MPIR_Comm_release(e->u.send.comm);
                         dtype_release_if_not_builtin(e->u.send.datatype);
                     }
                     break;
@@ -867,7 +867,7 @@ static int MPIDU_Sched_progress_state(struct MPIDU_Sched_state *state, int *made
                             e->status = MPIDU_SCHED_ENTRY_STATUS_COMPLETE;
                         MPID_Request_release(e->u.recv.rreq);
                         e->u.recv.rreq = NULL;
-                        MPIR_Comm_release(e->u.recv.comm, /*isDisconnect=*/FALSE);
+                        MPIR_Comm_release(e->u.recv.comm);
                         dtype_release_if_not_builtin(e->u.recv.datatype);
                     }
                     break;

http://git.mpich.org/mpich.git/commitdiff/b14c5f968ecd132ada7d961eed5406413648f452

commit b14c5f968ecd132ada7d961eed5406413648f452
Author: Pavan Balaji <balaji at anl.gov>
Date:   Wed Jul 15 09:36:59 2015 -0500

    Call device hooks on a communicator before its child communicators.
    
    Creation of child communicators might require information from the
    parent communicators.  This will not be possible if don't call the
    device hook for the parent before calling those for the child
    communicators.
    
    Signed-off-by: Charles J Archer <charles.j.archer at intel.com>

diff --git a/src/mpi/comm/commutil.c b/src/mpi/comm/commutil.c
index cb27d73..3a19b2f 100644
--- a/src/mpi/comm/commutil.c
+++ b/src/mpi/comm/commutil.c
@@ -463,6 +463,13 @@ int MPIR_Comm_commit(MPID_Comm *comm)
     MPIU_Assert(comm->node_comm == NULL);
     MPIU_Assert(comm->node_roots_comm == NULL);
 
+    mpi_errno = set_collops(comm);
+    if (mpi_errno) MPIU_ERR_POP(mpi_errno);
+
+    /* Notify device of communicator creation */
+    mpi_errno = MPID_Dev_comm_create_hook(comm);
+    if (mpi_errno) MPIU_ERR_POP(mpi_errno);
+
     if (comm->comm_kind == MPID_INTRACOMM) {
 
         mpi_errno = MPIU_Find_local_and_external(comm,
@@ -570,17 +577,6 @@ int MPIR_Comm_commit(MPID_Comm *comm)
     }
 
 fn_exit:
-    if (!mpi_errno) {
-        /* catch all of the early-bail, non-error cases */
-
-        mpi_errno = set_collops(comm);
-        if (mpi_errno) MPIU_ERR_POP(mpi_errno);
-
-        /* Notify device of communicator creation */
-        mpi_errno = MPID_Dev_comm_create_hook(comm);
-        if (mpi_errno) MPIU_ERR_POP(mpi_errno);
-    }
-
     if (external_procs != NULL)
         MPIU_Free(external_procs);
     if (local_procs != NULL)

http://git.mpich.org/mpich.git/commitdiff/cb4c8e78f4f4d57624a627d919b084e2a773aea9

commit cb4c8e78f4f4d57624a627d919b084e2a773aea9
Author: Pavan Balaji <balaji at anl.gov>
Date:   Wed Jul 15 09:27:34 2015 -0500

    Remove namespacing for static functions.
    
    Signed-off-by: Charles J Archer <charles.j.archer at intel.com>

diff --git a/src/mpi/group/grouputil.c b/src/mpi/group/grouputil.c
index ff2ce39..44bf084 100644
--- a/src/mpi/group/grouputil.c
+++ b/src/mpi/group/grouputil.c
@@ -102,7 +102,7 @@ int MPIR_Group_create( int nproc, MPID_Group **new_group_ptr )
  * in group rank order).  Instead it builds the traversal order (in increasing
  * lpid order) through the maparray given by the "next_lpid" fields.
  */
-static int MPIR_Mergesort_lpidarray( MPID_Group_pmap_t maparray[], int n )
+static int mergesort_lpidarray( MPID_Group_pmap_t maparray[], int n )
 {
     int idx1, idx2, first_idx, cur_idx, next_lpid, idx2_offset;
 
@@ -128,8 +128,8 @@ static int MPIR_Mergesort_lpidarray( MPID_Group_pmap_t maparray[], int n )
 
     /* Sort each half */
     idx2_offset = n/2;
-    idx1 = MPIR_Mergesort_lpidarray( maparray, n/2 );
-    idx2 = MPIR_Mergesort_lpidarray( maparray + idx2_offset, n - n/2 ) + idx2_offset;
+    idx1 = mergesort_lpidarray( maparray, n/2 );
+    idx2 = mergesort_lpidarray( maparray + idx2_offset, n - n/2 ) + idx2_offset;
     /* merge the results */
     /* There are three lists:
        first_idx - points to the HEAD of the sorted, merged list
@@ -206,8 +206,8 @@ void MPIR_Group_setup_lpid_list( MPID_Group *group_ptr )
 {
     if (group_ptr->idx_of_first_lpid == -1) {
 	group_ptr->idx_of_first_lpid = 
-	    MPIR_Mergesort_lpidarray( group_ptr->lrank_to_lpid, 
-				      group_ptr->size );
+	    mergesort_lpidarray( group_ptr->lrank_to_lpid,
+                                 group_ptr->size );
     }
 }
 
@@ -396,7 +396,7 @@ int MPIR_GroupCheckVCRSubset( MPID_Group *group_ptr, int vsize, MPID_VCR *vcr )
     
     MPIR_Group_setup_lpid_list( group_ptr );
     g1_idx = group_ptr->idx_of_first_lpid;
-    g2_idx = MPIR_Mergesort_lpidarray( vmap, vsize );
+    g2_idx = mergesort_lpidarray( vmap, vsize );
     MPIU_DBG_MSG_FMT(COMM,VERBOSE,(MPIU_DBG_FDEST,
 			   "initial indices: %d %d\n", g1_idx, g2_idx ));
     while (g1_idx >= 0 && g2_idx >= 0) {

http://git.mpich.org/mpich.git/commitdiff/f8fd3d81ae217b2fbf3d3a2221f7c64d295ceef4

commit f8fd3d81ae217b2fbf3d3a2221f7c64d295ceef4
Author: Pavan Balaji <balaji at anl.gov>
Date:   Wed Jul 15 09:09:02 2015 -0500

    Initialize comm local and remote size to -1.
    
    Helps with debugging.
    
    Signed-off-by: Charles J Archer <charles.j.archer at intel.com>

diff --git a/src/mpi/comm/commutil.c b/src/mpi/comm/commutil.c
index f4b2930..cb27d73 100644
--- a/src/mpi/comm/commutil.c
+++ b/src/mpi/comm/commutil.c
@@ -115,6 +115,11 @@ int MPIR_Comm_init(MPID_Comm *comm_p)
 
     MPIU_THREAD_MPI_OBJ_INIT(comm_p);
 
+    /* initialize local and remote sizes to -1 to allow other parts of
+     * the stack to detect errors more easily */
+    comm_p->local_size = -1;
+    comm_p->remote_size = -1;
+
     /* Clear many items (empty means to use the default; some of these
        may be overridden within the upper-level communicator initialization) */
     comm_p->errhandler   = NULL;

-----------------------------------------------------------------------

Summary of changes:
 src/include/mpiimpl.h                              |  121 +++++-----
 src/mpi/comm/comm_create.c                         |  157 +++++-------
 src/mpi/comm/comm_create_group.c                   |   16 +-
 src/mpi/comm/comm_free.c                           |    2 +-
 src/mpi/comm/comm_group.c                          |   10 +-
 src/mpi/comm/comm_remote_group.c                   |    2 +-
 src/mpi/comm/comm_shrink.c                         |    4 +-
 src/mpi/comm/comm_split.c                          |   50 ++--
 src/mpi/comm/commutil.c                            |  262 ++++++++++++++------
 src/mpi/comm/intercomm_create.c                    |   13 +-
 src/mpi/comm/intercomm_merge.c                     |   62 ++---
 src/mpi/group/grouputil.c                          |   28 ++-
 .../nemesis/netmod/ofi/ofi_tagged_template.c       |    2 +-
 src/mpid/ch3/include/mpidimpl.h                    |   31 ++-
 src/mpid/ch3/include/mpidpost.h                    |    2 +-
 src/mpid/ch3/include/mpidpre.h                     |   19 +-
 src/mpid/ch3/src/ch3u_comm.c                       |  177 +++++++++++++
 src/mpid/ch3/src/ch3u_port.c                       |   54 ++---
 src/mpid/ch3/src/ch3u_request.c                    |    2 +-
 src/mpid/ch3/src/mpid_comm_disconnect.c            |    3 +-
 src/mpid/ch3/src/mpid_comm_revoke.c                |    4 +-
 src/mpid/ch3/src/mpid_finalize.c                   |    6 +-
 src/mpid/ch3/src/mpid_init.c                       |   29 +--
 src/mpid/ch3/src/mpid_vc.c                         |  125 ++++------
 src/mpid/ch3/src/mpidi_pg.c                        |    2 +-
 src/mpid/common/hcoll/hcoll_rte.c                  |    6 +-
 src/mpid/common/sched/mpid_sched.c                 |    4 +-
 27 files changed, 692 insertions(+), 501 deletions(-)


hooks/post-receive
-- 
MPICH primary repository


More information about the commits mailing list