|
Packit Service |
c5cf8c |
/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */
|
|
Packit Service |
c5cf8c |
/*
|
|
Packit Service |
c5cf8c |
* (C) 2001 by Argonne National Laboratory.
|
|
Packit Service |
c5cf8c |
* See COPYRIGHT in top-level directory.
|
|
Packit Service |
c5cf8c |
*/
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
#include "mpiimpl.h"
|
|
Packit Service |
c5cf8c |
#include "mpicomm.h"
|
|
Packit Service |
c5cf8c |
#include "mpir_info.h" /* MPIR_Info_free */
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
#include "utlist.h"
|
|
Packit Service |
c5cf8c |
#include "uthash.h"
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
/* This is the utility file for comm that contains the basic comm items
|
|
Packit Service |
c5cf8c |
and storage management */
|
|
Packit Service |
c5cf8c |
#ifndef MPID_COMM_PREALLOC
|
|
Packit Service |
c5cf8c |
#define MPID_COMM_PREALLOC 8
|
|
Packit Service |
c5cf8c |
#endif
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
/* Preallocated comm objects */
|
|
Packit Service |
c5cf8c |
/* initialized in initthread.c */
|
|
Packit Service |
c5cf8c |
MPIR_Comm MPIR_Comm_builtin[MPIR_COMM_N_BUILTIN] = { {0}
|
|
Packit Service |
c5cf8c |
};
|
|
Packit Service |
c5cf8c |
MPIR_Comm MPIR_Comm_direct[MPID_COMM_PREALLOC] = { {0}
|
|
Packit Service |
c5cf8c |
};
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
MPIR_Object_alloc_t MPIR_Comm_mem = {
|
|
Packit Service |
c5cf8c |
0,
|
|
Packit Service |
c5cf8c |
0,
|
|
Packit Service |
c5cf8c |
0,
|
|
Packit Service |
c5cf8c |
0,
|
|
Packit Service |
c5cf8c |
MPIR_COMM,
|
|
Packit Service |
c5cf8c |
sizeof(MPIR_Comm),
|
|
Packit Service |
c5cf8c |
MPIR_Comm_direct,
|
|
Packit Service |
c5cf8c |
MPID_COMM_PREALLOC
|
|
Packit Service |
c5cf8c |
};
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
/* Communicator creation functions */
|
|
Packit Service |
c5cf8c |
struct MPIR_Commops *MPIR_Comm_fns = NULL;
|
|
Packit Service |
c5cf8c |
struct MPIR_Comm_hint_fn_elt {
|
|
Packit Service |
c5cf8c |
char name[MPI_MAX_INFO_KEY];
|
|
Packit Service |
c5cf8c |
MPIR_Comm_hint_fn_t fn;
|
|
Packit Service |
c5cf8c |
void *state;
|
|
Packit Service |
c5cf8c |
UT_hash_handle hh;
|
|
Packit Service |
c5cf8c |
};
|
|
Packit Service |
c5cf8c |
static struct MPIR_Comm_hint_fn_elt *MPID_hint_fns = NULL;
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
/* FIXME :
|
|
Packit Service |
c5cf8c |
Reusing context ids can lead to a race condition if (as is desirable)
|
|
Packit Service |
c5cf8c |
MPI_Comm_free does not include a barrier. Consider the following:
|
|
Packit Service |
c5cf8c |
Process A frees the communicator.
|
|
Packit Service |
c5cf8c |
Process A creates a new communicator, reusing the just released id
|
|
Packit Service |
c5cf8c |
Process B sends a message to A on the old communicator.
|
|
Packit Service |
c5cf8c |
Process A receives the message, and believes that it belongs to the
|
|
Packit Service |
c5cf8c |
new communicator.
|
|
Packit Service |
c5cf8c |
Process B then cancels the message, and frees the communicator.
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
The likelihood of this happening can be reduced by introducing a gap
|
|
Packit Service |
c5cf8c |
between when a context id is released and when it is reused. An alternative
|
|
Packit Service |
c5cf8c |
is to use an explicit message (in the implementation of MPI_Comm_free)
|
|
Packit Service |
c5cf8c |
to indicate that a communicator is being freed; this will often require
|
|
Packit Service |
c5cf8c |
less communication than a barrier in MPI_Comm_free, and will ensure that
|
|
Packit Service |
c5cf8c |
no messages are later sent to the same communicator (we may also want to
|
|
Packit Service |
c5cf8c |
have a similar check when building fault-tolerant versions of MPI).
|
|
Packit Service |
c5cf8c |
*/
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
/* Zeroes most non-handle fields in a communicator, as well as initializing any
|
|
Packit Service |
c5cf8c |
* other special fields, such as a per-object mutex. Also defaults the
|
|
Packit Service |
c5cf8c |
* reference count to 1, under the assumption that the caller holds a reference
|
|
Packit Service |
c5cf8c |
* to it.
|
|
Packit Service |
c5cf8c |
*
|
|
Packit Service |
c5cf8c |
* !!! The resulting struct is _not_ ready for communication !!! */
|
|
Packit Service |
c5cf8c |
int MPII_Comm_init(MPIR_Comm * comm_p)
|
|
Packit Service |
c5cf8c |
{
|
|
Packit Service |
c5cf8c |
int mpi_errno = MPI_SUCCESS;
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
MPIR_Object_set_ref(comm_p, 1);
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
/* initialize local and remote sizes to -1 to allow other parts of
|
|
Packit Service |
c5cf8c |
* the stack to detect errors more easily */
|
|
Packit Service |
c5cf8c |
comm_p->local_size = -1;
|
|
Packit Service |
c5cf8c |
comm_p->remote_size = -1;
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
/* Clear many items (empty means to use the default; some of these
|
|
Packit Service |
c5cf8c |
* may be overridden within the upper-level communicator initialization) */
|
|
Packit Service |
c5cf8c |
comm_p->errhandler = NULL;
|
|
Packit Service |
c5cf8c |
comm_p->attributes = NULL;
|
|
Packit Service |
c5cf8c |
comm_p->remote_group = NULL;
|
|
Packit Service |
c5cf8c |
comm_p->local_group = NULL;
|
|
Packit Service |
c5cf8c |
comm_p->topo_fns = NULL;
|
|
Packit Service |
c5cf8c |
comm_p->name[0] = '\0';
|
|
Packit Service |
c5cf8c |
comm_p->info = NULL;
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
comm_p->hierarchy_kind = MPIR_COMM_HIERARCHY_KIND__FLAT;
|
|
Packit Service |
c5cf8c |
comm_p->node_comm = NULL;
|
|
Packit Service |
c5cf8c |
comm_p->node_roots_comm = NULL;
|
|
Packit Service |
c5cf8c |
comm_p->intranode_table = NULL;
|
|
Packit Service |
c5cf8c |
comm_p->internode_table = NULL;
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
/* abstractions bleed a bit here... :(*/
|
|
Packit Service |
c5cf8c |
comm_p->next_sched_tag = MPIR_FIRST_NBC_TAG;
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
/* Initialize the revoked flag as false */
|
|
Packit Service |
c5cf8c |
comm_p->revoked = 0;
|
|
Packit Service |
c5cf8c |
comm_p->mapper_head = NULL;
|
|
Packit Service |
c5cf8c |
comm_p->mapper_tail = NULL;
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
#if MPICH_THREAD_GRANULARITY == MPICH_THREAD_GRANULARITY__POBJ
|
|
Packit Service |
c5cf8c |
{
|
|
Packit Service |
c5cf8c |
int thr_err;
|
|
Packit Service |
c5cf8c |
MPID_Thread_mutex_create(&MPIR_THREAD_POBJ_COMM_MUTEX(comm_p), &thr_err);
|
|
Packit Service |
c5cf8c |
MPIR_Assert(thr_err == 0);
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
#endif
|
|
Packit Service |
c5cf8c |
/* Fields not set include context_id, remote and local size, and
|
|
Packit Service |
c5cf8c |
* kind, since different communicator construction routines need
|
|
Packit Service |
c5cf8c |
* different values */
|
|
Packit Service |
c5cf8c |
return mpi_errno;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
/*
|
|
Packit Service |
c5cf8c |
Create a communicator structure and perform basic initialization
|
|
Packit Service |
c5cf8c |
(mostly clearing fields and updating the reference count).
|
|
Packit Service |
c5cf8c |
*/
|
|
Packit Service |
c5cf8c |
#undef FUNCNAME
|
|
Packit Service |
c5cf8c |
#define FUNCNAME MPIR_Comm_create
|
|
Packit Service |
c5cf8c |
#undef FCNAME
|
|
Packit Service |
c5cf8c |
#define FCNAME "MPIR_Comm_create"
|
|
Packit Service |
c5cf8c |
int MPIR_Comm_create(MPIR_Comm ** newcomm_ptr)
|
|
Packit Service |
c5cf8c |
{
|
|
Packit Service |
c5cf8c |
int mpi_errno = MPI_SUCCESS;
|
|
Packit Service |
c5cf8c |
MPIR_Comm *newptr;
|
|
Packit Service |
c5cf8c |
MPIR_FUNC_TERSE_STATE_DECL(MPID_STATE_MPIR_COMM_CREATE);
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
MPIR_FUNC_TERSE_ENTER(MPID_STATE_MPIR_COMM_CREATE);
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
newptr = (MPIR_Comm *) MPIR_Handle_obj_alloc(&MPIR_Comm_mem);
|
|
Packit Service |
c5cf8c |
MPIR_ERR_CHKANDJUMP(!newptr, mpi_errno, MPI_ERR_OTHER, "**nomem");
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
*newcomm_ptr = newptr;
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
mpi_errno = MPII_Comm_init(newptr);
|
|
Packit Service |
c5cf8c |
if (mpi_errno)
|
|
Packit Service |
c5cf8c |
MPIR_ERR_POP(mpi_errno);
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
/* Insert this new communicator into the list of known communicators.
|
|
Packit Service |
c5cf8c |
* Make this conditional on debugger support to match the test in
|
|
Packit Service |
c5cf8c |
* MPIR_Comm_release . */
|
|
Packit Service |
c5cf8c |
MPII_COMML_REMEMBER(newptr);
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
fn_fail:
|
|
Packit Service |
c5cf8c |
MPIR_FUNC_TERSE_EXIT(MPID_STATE_MPIR_COMM_CREATE);
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
return mpi_errno;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
/* Create a local intra communicator from the local group of the
|
|
Packit Service |
c5cf8c |
specified intercomm. */
|
|
Packit Service |
c5cf8c |
/* FIXME this is an alternative constructor that doesn't use MPIR_Comm_create! */
|
|
Packit Service |
c5cf8c |
#undef FUNCNAME
|
|
Packit Service |
c5cf8c |
#define FUNCNAME MPII_Setup_intercomm_localcomm
|
|
Packit Service |
c5cf8c |
#undef FCNAME
|
|
Packit Service |
c5cf8c |
#define FCNAME "MPII_Setup_intercomm_localcomm"
|
|
Packit Service |
c5cf8c |
int MPII_Setup_intercomm_localcomm(MPIR_Comm * intercomm_ptr)
|
|
Packit Service |
c5cf8c |
{
|
|
Packit Service |
c5cf8c |
MPIR_Comm *localcomm_ptr;
|
|
Packit Service |
c5cf8c |
int mpi_errno = MPI_SUCCESS;
|
|
Packit Service |
c5cf8c |
MPIR_FUNC_TERSE_STATE_DECL(MPID_STATE_MPIR_SETUP_INTERCOMM_LOCALCOMM);
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
MPIR_FUNC_TERSE_ENTER(MPID_STATE_MPIR_SETUP_INTERCOMM_LOCALCOMM);
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
localcomm_ptr = (MPIR_Comm *) MPIR_Handle_obj_alloc(&MPIR_Comm_mem);
|
|
Packit Service |
c5cf8c |
MPIR_ERR_CHKANDJUMP(!localcomm_ptr, mpi_errno, MPI_ERR_OTHER, "**nomem");
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
/* get sensible default values for most fields (usually zeros) */
|
|
Packit Service |
c5cf8c |
mpi_errno = MPII_Comm_init(localcomm_ptr);
|
|
Packit Service |
c5cf8c |
if (mpi_errno)
|
|
Packit Service |
c5cf8c |
MPIR_ERR_POP(mpi_errno);
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
/* use the parent intercomm's recv ctx as the basis for our ctx */
|
|
Packit Service |
c5cf8c |
localcomm_ptr->recvcontext_id =
|
|
Packit Service |
c5cf8c |
MPIR_CONTEXT_SET_FIELD(IS_LOCALCOMM, intercomm_ptr->recvcontext_id, 1);
|
|
Packit Service |
c5cf8c |
localcomm_ptr->context_id = localcomm_ptr->recvcontext_id;
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
MPL_DBG_MSG_FMT(MPIR_DBG_COMM, TYPICAL,
|
|
Packit Service |
c5cf8c |
(MPL_DBG_FDEST,
|
|
Packit Service |
c5cf8c |
"setup_intercomm_localcomm ic=%p ic->context_id=%d ic->recvcontext_id=%d lc->recvcontext_id=%d",
|
|
Packit Service |
c5cf8c |
intercomm_ptr, intercomm_ptr->context_id, intercomm_ptr->recvcontext_id,
|
|
Packit Service |
c5cf8c |
localcomm_ptr->recvcontext_id));
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
/* Save the kind of the communicator */
|
|
Packit Service |
c5cf8c |
localcomm_ptr->comm_kind = MPIR_COMM_KIND__INTRACOMM;
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
/* Set the sizes and ranks */
|
|
Packit Service |
c5cf8c |
localcomm_ptr->remote_size = intercomm_ptr->local_size;
|
|
Packit Service |
c5cf8c |
localcomm_ptr->local_size = intercomm_ptr->local_size;
|
|
Packit Service |
c5cf8c |
localcomm_ptr->pof2 = intercomm_ptr->pof2;
|
|
Packit Service |
c5cf8c |
localcomm_ptr->rank = intercomm_ptr->rank;
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
MPIR_Comm_map_dup(localcomm_ptr, intercomm_ptr, MPIR_COMM_MAP_DIR__L2L);
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
/* TODO More advanced version: if the group is available, dup it by
|
|
Packit Service |
c5cf8c |
* increasing the reference count instead of recreating it later */
|
|
Packit Service |
c5cf8c |
/* FIXME : No local functions for the topology routines */
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
intercomm_ptr->local_comm = localcomm_ptr;
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
/* sets up the SMP-aware sub-communicators and tables */
|
|
Packit Service |
c5cf8c |
mpi_errno = MPIR_Comm_commit(localcomm_ptr);
|
|
Packit Service |
c5cf8c |
if (mpi_errno)
|
|
Packit Service |
c5cf8c |
MPIR_ERR_POP(mpi_errno);
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
fn_fail:
|
|
Packit Service |
c5cf8c |
MPIR_FUNC_TERSE_EXIT(MPID_STATE_MPIR_SETUP_INTERCOMM_LOCALCOMM);
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
return mpi_errno;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
#undef FUNCNAME
|
|
Packit Service |
c5cf8c |
#define FUNCNAME MPIR_Comm_map_irregular
|
|
Packit Service |
c5cf8c |
#undef FCNAME
|
|
Packit Service |
c5cf8c |
#define FCNAME MPL_QUOTE(FUNCNAME)
|
|
Packit Service |
c5cf8c |
int MPIR_Comm_map_irregular(MPIR_Comm * newcomm, MPIR_Comm * src_comm,
|
|
Packit Service |
c5cf8c |
int *src_mapping, int src_mapping_size,
|
|
Packit Service |
c5cf8c |
MPIR_Comm_map_dir_t dir, MPIR_Comm_map_t ** map)
|
|
Packit Service |
c5cf8c |
{
|
|
Packit Service |
c5cf8c |
int mpi_errno = MPI_SUCCESS;
|
|
Packit Service |
c5cf8c |
MPIR_Comm_map_t *mapper;
|
|
Packit Service |
c5cf8c |
MPIR_CHKPMEM_DECL(3);
|
|
Packit Service |
c5cf8c |
MPIR_FUNC_TERSE_STATE_DECL(MPID_STATE_MPIR_COMM_MAP_TYPE__IRREGULAR);
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
MPIR_FUNC_TERSE_ENTER(MPID_STATE_MPIR_COMM_MAP_TYPE__IRREGULAR);
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
MPIR_CHKPMEM_MALLOC(mapper, MPIR_Comm_map_t *, sizeof(MPIR_Comm_map_t), mpi_errno, "mapper",
|
|
Packit Service |
c5cf8c |
MPL_MEM_COMM);
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
mapper->type = MPIR_COMM_MAP_TYPE__IRREGULAR;
|
|
Packit Service |
c5cf8c |
mapper->src_comm = src_comm;
|
|
Packit Service |
c5cf8c |
mapper->dir = dir;
|
|
Packit Service |
c5cf8c |
mapper->src_mapping_size = src_mapping_size;
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
if (src_mapping) {
|
|
Packit Service |
c5cf8c |
mapper->src_mapping = src_mapping;
|
|
Packit Service |
c5cf8c |
mapper->free_mapping = 0;
|
|
Packit Service |
c5cf8c |
} else {
|
|
Packit Service |
c5cf8c |
MPIR_CHKPMEM_MALLOC(mapper->src_mapping, int *,
|
|
Packit Service |
c5cf8c |
src_mapping_size * sizeof(int), mpi_errno, "mapper mapping",
|
|
Packit Service |
c5cf8c |
MPL_MEM_COMM);
|
|
Packit Service |
c5cf8c |
mapper->free_mapping = 1;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
mapper->next = NULL;
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
LL_APPEND(newcomm->mapper_head, newcomm->mapper_tail, mapper);
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
if (map)
|
|
Packit Service |
c5cf8c |
*map = mapper;
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
fn_exit:
|
|
Packit Service |
c5cf8c |
MPIR_CHKPMEM_COMMIT();
|
|
Packit Service |
c5cf8c |
MPIR_FUNC_TERSE_EXIT(MPID_STATE_MPIR_COMM_MAP_TYPE__IRREGULAR);
|
|
Packit Service |
c5cf8c |
return mpi_errno;
|
|
Packit Service |
c5cf8c |
fn_fail:
|
|
Packit Service |
c5cf8c |
MPIR_CHKPMEM_REAP();
|
|
Packit Service |
c5cf8c |
goto fn_exit;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
#undef FUNCNAME
|
|
Packit Service |
c5cf8c |
#define FUNCNAME MPIR_Comm_map_dup
|
|
Packit Service |
c5cf8c |
#undef FCNAME
|
|
Packit Service |
c5cf8c |
#define FCNAME MPL_QUOTE(FUNCNAME)
|
|
Packit Service |
c5cf8c |
int MPIR_Comm_map_dup(MPIR_Comm * newcomm, MPIR_Comm * src_comm, MPIR_Comm_map_dir_t dir)
|
|
Packit Service |
c5cf8c |
{
|
|
Packit Service |
c5cf8c |
int mpi_errno = MPI_SUCCESS;
|
|
Packit Service |
c5cf8c |
MPIR_Comm_map_t *mapper;
|
|
Packit Service |
c5cf8c |
MPIR_CHKPMEM_DECL(1);
|
|
Packit Service |
c5cf8c |
MPIR_FUNC_TERSE_STATE_DECL(MPID_STATE_MPIR_COMM_MAP_TYPE__DUP);
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
MPIR_FUNC_TERSE_ENTER(MPID_STATE_MPIR_COMM_MAP_TYPE__DUP);
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
MPIR_CHKPMEM_MALLOC(mapper, MPIR_Comm_map_t *, sizeof(MPIR_Comm_map_t), mpi_errno, "mapper",
|
|
Packit Service |
c5cf8c |
MPL_MEM_COMM);
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
mapper->type = MPIR_COMM_MAP_TYPE__DUP;
|
|
Packit Service |
c5cf8c |
mapper->src_comm = src_comm;
|
|
Packit Service |
c5cf8c |
mapper->dir = dir;
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
mapper->next = NULL;
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
LL_APPEND(newcomm->mapper_head, newcomm->mapper_tail, mapper);
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
fn_exit:
|
|
Packit Service |
c5cf8c |
MPIR_CHKPMEM_COMMIT();
|
|
Packit Service |
c5cf8c |
MPIR_FUNC_TERSE_EXIT(MPID_STATE_MPIR_COMM_MAP_TYPE__DUP);
|
|
Packit Service |
c5cf8c |
return mpi_errno;
|
|
Packit Service |
c5cf8c |
fn_fail:
|
|
Packit Service |
c5cf8c |
MPIR_CHKPMEM_REAP();
|
|
Packit Service |
c5cf8c |
goto fn_exit;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
#undef FUNCNAME
|
|
Packit Service |
c5cf8c |
#define FUNCNAME MPIR_Comm_map_free
|
|
Packit Service |
c5cf8c |
#undef FCNAME
|
|
Packit Service |
c5cf8c |
#define FCNAME MPL_QUOTE(FUNCNAME)
|
|
Packit Service |
c5cf8c |
int MPIR_Comm_map_free(MPIR_Comm * comm)
|
|
Packit Service |
c5cf8c |
{
|
|
Packit Service |
c5cf8c |
int mpi_errno = MPI_SUCCESS;
|
|
Packit Service |
c5cf8c |
MPIR_Comm_map_t *mapper, *tmp;
|
|
Packit Service |
c5cf8c |
MPIR_FUNC_TERSE_STATE_DECL(MPID_STATE_MPIR_COMM_MAP_FREE);
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
MPIR_FUNC_TERSE_ENTER(MPID_STATE_MPIR_COMM_MAP_FREE);
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
for (mapper = comm->mapper_head; mapper;) {
|
|
Packit Service |
c5cf8c |
tmp = mapper->next;
|
|
Packit Service |
c5cf8c |
if (mapper->type == MPIR_COMM_MAP_TYPE__IRREGULAR && mapper->free_mapping)
|
|
Packit Service |
c5cf8c |
MPL_free(mapper->src_mapping);
|
|
Packit Service |
c5cf8c |
MPL_free(mapper);
|
|
Packit Service |
c5cf8c |
mapper = tmp;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
comm->mapper_head = NULL;
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
MPIR_FUNC_TERSE_EXIT(MPID_STATE_MPIR_COMM_MAP_FREE);
|
|
Packit Service |
c5cf8c |
return mpi_errno;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
/* Provides a hook for the top level functions to perform some manipulation on a
|
|
Packit Service |
c5cf8c |
communicator just before it is given to the application level.
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
For example, we create sub-communicators for SMP-aware collectives at this
|
|
Packit Service |
c5cf8c |
step. */
|
|
Packit Service |
c5cf8c |
#undef FUNCNAME
|
|
Packit Service |
c5cf8c |
#define FUNCNAME MPIR_Comm_commit
|
|
Packit Service |
c5cf8c |
#undef FCNAME
|
|
Packit Service |
c5cf8c |
#define FCNAME MPL_QUOTE(FUNCNAME)
|
|
Packit Service |
c5cf8c |
int MPIR_Comm_commit(MPIR_Comm * comm)
|
|
Packit Service |
c5cf8c |
{
|
|
Packit Service |
c5cf8c |
int mpi_errno = MPI_SUCCESS;
|
|
Packit Service |
c5cf8c |
int num_local = -1, num_external = -1;
|
|
Packit Service |
c5cf8c |
int local_rank = -1, external_rank = -1;
|
|
Packit Service |
c5cf8c |
int *local_procs = NULL, *external_procs = NULL;
|
|
Packit Service |
c5cf8c |
MPIR_FUNC_TERSE_STATE_DECL(MPID_STATE_MPIR_COMM_COMMIT);
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
MPIR_FUNC_TERSE_ENTER(MPID_STATE_MPIR_COMM_COMMIT);
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
/* It's OK to relax these assertions, but we should do so very
|
|
Packit Service |
c5cf8c |
* intentionally. For now this function is the only place that we create
|
|
Packit Service |
c5cf8c |
* our hierarchy of communicators */
|
|
Packit Service |
c5cf8c |
MPIR_Assert(comm->node_comm == NULL);
|
|
Packit Service |
c5cf8c |
MPIR_Assert(comm->node_roots_comm == NULL);
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
/* Notify device of communicator creation */
|
|
Packit Service |
c5cf8c |
if (comm != MPIR_Process.comm_world) {
|
|
Packit Service |
c5cf8c |
mpi_errno = MPID_Comm_create_hook(comm);
|
|
Packit Service |
c5cf8c |
if (mpi_errno)
|
|
Packit Service |
c5cf8c |
MPIR_ERR_POP(mpi_errno);
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
MPIR_Comm_map_free(comm);
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
/* Create collectives-specific infrastructure */
|
|
Packit Service |
c5cf8c |
mpi_errno = MPIR_Coll_comm_init(comm);
|
|
Packit Service |
c5cf8c |
if (mpi_errno)
|
|
Packit Service |
c5cf8c |
MPIR_ERR_POP(mpi_errno);
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
MPIR_Comm_map_free(comm);
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
comm->pof2 = MPL_pof2(comm->local_size);
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
if (comm->comm_kind == MPIR_COMM_KIND__INTRACOMM && !MPIR_CONTEXT_READ_FIELD(SUBCOMM, comm->context_id)) { /*make sure this is not a subcomm */
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
mpi_errno = MPIR_Find_local_and_external(comm,
|
|
Packit Service |
c5cf8c |
&num_local, &local_rank, &local_procs,
|
|
Packit Service |
c5cf8c |
&num_external, &external_rank, &external_procs,
|
|
Packit Service |
c5cf8c |
&comm->intranode_table, &comm->internode_table);
|
|
Packit Service |
c5cf8c |
/* --BEGIN ERROR HANDLING-- */
|
|
Packit Service |
c5cf8c |
if (mpi_errno) {
|
|
Packit Service |
c5cf8c |
if (MPIR_Err_is_fatal(mpi_errno))
|
|
Packit Service |
c5cf8c |
MPIR_ERR_POP(mpi_errno);
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
/* Non-fatal errors simply mean that this communicator will not have
|
|
Packit Service |
c5cf8c |
* any node awareness. Node-aware collectives are an optimization. */
|
|
Packit Service |
c5cf8c |
MPL_DBG_MSG_P(MPIR_DBG_COMM, VERBOSE,
|
|
Packit Service |
c5cf8c |
"MPIR_Find_local_and_external failed for comm_ptr=%p", comm);
|
|
Packit Service |
c5cf8c |
if (comm->intranode_table)
|
|
Packit Service |
c5cf8c |
MPL_free(comm->intranode_table);
|
|
Packit Service |
c5cf8c |
if (comm->internode_table)
|
|
Packit Service |
c5cf8c |
MPL_free(comm->internode_table);
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
mpi_errno = MPI_SUCCESS;
|
|
Packit Service |
c5cf8c |
goto fn_exit;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
/* --END ERROR HANDLING-- */
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
/* defensive checks */
|
|
Packit Service |
c5cf8c |
MPIR_Assert(num_local > 0);
|
|
Packit Service |
c5cf8c |
MPIR_Assert(num_local > 1 || external_rank >= 0);
|
|
Packit Service |
c5cf8c |
MPIR_Assert(external_rank < 0 || external_procs != NULL);
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
/* if the node_roots_comm and comm would be the same size, then creating
|
|
Packit Service |
c5cf8c |
* the second communicator is useless and wasteful. */
|
|
Packit Service |
c5cf8c |
if (num_external == comm->remote_size) {
|
|
Packit Service |
c5cf8c |
MPIR_Assert(num_local == 1);
|
|
Packit Service |
c5cf8c |
goto fn_exit;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
/* we don't need a local comm if this process is the only one on this node */
|
|
Packit Service |
c5cf8c |
if (num_local > 1) {
|
|
Packit Service |
c5cf8c |
mpi_errno = MPIR_Comm_create(&comm->node_comm);
|
|
Packit Service |
c5cf8c |
if (mpi_errno)
|
|
Packit Service |
c5cf8c |
MPIR_ERR_POP(mpi_errno);
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
comm->node_comm->context_id = comm->context_id + MPIR_CONTEXT_INTRANODE_OFFSET;
|
|
Packit Service |
c5cf8c |
comm->node_comm->recvcontext_id = comm->node_comm->context_id;
|
|
Packit Service |
c5cf8c |
comm->node_comm->rank = local_rank;
|
|
Packit Service |
c5cf8c |
comm->node_comm->comm_kind = MPIR_COMM_KIND__INTRACOMM;
|
|
Packit Service |
c5cf8c |
comm->node_comm->hierarchy_kind = MPIR_COMM_HIERARCHY_KIND__NODE;
|
|
Packit Service |
c5cf8c |
comm->node_comm->local_comm = NULL;
|
|
Packit Service |
c5cf8c |
MPL_DBG_MSG_D(MPIR_DBG_COMM, VERBOSE, "Create node_comm=%p\n", comm->node_comm);
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
comm->node_comm->local_size = num_local;
|
|
Packit Service |
c5cf8c |
comm->node_comm->pof2 = MPL_pof2(comm->node_comm->local_size);
|
|
Packit Service |
c5cf8c |
comm->node_comm->remote_size = num_local;
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
MPIR_Comm_map_irregular(comm->node_comm, comm, local_procs,
|
|
Packit Service |
c5cf8c |
num_local, MPIR_COMM_MAP_DIR__L2L, NULL);
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
/* Notify device of communicator creation */
|
|
Packit Service |
c5cf8c |
mpi_errno = MPID_Comm_create_hook(comm->node_comm);
|
|
Packit Service |
c5cf8c |
if (mpi_errno)
|
|
Packit Service |
c5cf8c |
MPIR_ERR_POP(mpi_errno);
|
|
Packit Service |
c5cf8c |
/* don't call MPIR_Comm_commit here */
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
/* Create collectives-specific infrastructure */
|
|
Packit Service |
c5cf8c |
mpi_errno = MPIR_Coll_comm_init(comm->node_comm);
|
|
Packit Service |
c5cf8c |
if (mpi_errno)
|
|
Packit Service |
c5cf8c |
MPIR_ERR_POP(mpi_errno);
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
MPIR_Comm_map_free(comm->node_comm);
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
/* this process may not be a member of the node_roots_comm */
|
|
Packit Service |
c5cf8c |
if (local_rank == 0) {
|
|
Packit Service |
c5cf8c |
mpi_errno = MPIR_Comm_create(&comm->node_roots_comm);
|
|
Packit Service |
c5cf8c |
if (mpi_errno)
|
|
Packit Service |
c5cf8c |
MPIR_ERR_POP(mpi_errno);
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
comm->node_roots_comm->context_id = comm->context_id + MPIR_CONTEXT_INTERNODE_OFFSET;
|
|
Packit Service |
c5cf8c |
comm->node_roots_comm->recvcontext_id = comm->node_roots_comm->context_id;
|
|
Packit Service |
c5cf8c |
comm->node_roots_comm->rank = external_rank;
|
|
Packit Service |
c5cf8c |
comm->node_roots_comm->comm_kind = MPIR_COMM_KIND__INTRACOMM;
|
|
Packit Service |
c5cf8c |
comm->node_roots_comm->hierarchy_kind = MPIR_COMM_HIERARCHY_KIND__NODE_ROOTS;
|
|
Packit Service |
c5cf8c |
comm->node_roots_comm->local_comm = NULL;
|
|
Packit Service |
c5cf8c |
MPL_DBG_MSG_D(MPIR_DBG_COMM, VERBOSE, "Create node_roots_comm=%p\n",
|
|
Packit Service |
c5cf8c |
comm->node_roots_comm);
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
comm->node_roots_comm->local_size = num_external;
|
|
Packit Service |
c5cf8c |
comm->node_roots_comm->pof2 = MPL_pof2(comm->node_roots_comm->local_size);
|
|
Packit Service |
c5cf8c |
comm->node_roots_comm->remote_size = num_external;
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
MPIR_Comm_map_irregular(comm->node_roots_comm, comm,
|
|
Packit Service |
c5cf8c |
external_procs, num_external, MPIR_COMM_MAP_DIR__L2L, NULL);
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
/* Notify device of communicator creation */
|
|
Packit Service |
c5cf8c |
mpi_errno = MPID_Comm_create_hook(comm->node_roots_comm);
|
|
Packit Service |
c5cf8c |
if (mpi_errno)
|
|
Packit Service |
c5cf8c |
MPIR_ERR_POP(mpi_errno);
|
|
Packit Service |
c5cf8c |
/* don't call MPIR_Comm_commit here */
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
/* Create collectives-specific infrastructure */
|
|
Packit Service |
c5cf8c |
mpi_errno = MPIR_Coll_comm_init(comm->node_roots_comm);
|
|
Packit Service |
c5cf8c |
if (mpi_errno)
|
|
Packit Service |
c5cf8c |
MPIR_ERR_POP(mpi_errno);
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
MPIR_Comm_map_free(comm->node_roots_comm);
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
comm->hierarchy_kind = MPIR_COMM_HIERARCHY_KIND__PARENT;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
fn_exit:
|
|
Packit Service |
c5cf8c |
if (comm == MPIR_Process.comm_world) {
|
|
Packit Service |
c5cf8c |
mpi_errno = MPID_Comm_create_hook(comm);
|
|
Packit Service |
c5cf8c |
if (mpi_errno)
|
|
Packit Service |
c5cf8c |
MPIR_ERR_POP(mpi_errno);
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
MPIR_Comm_map_free(comm);
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
if (external_procs != NULL)
|
|
Packit Service |
c5cf8c |
MPL_free(external_procs);
|
|
Packit Service |
c5cf8c |
if (local_procs != NULL)
|
|
Packit Service |
c5cf8c |
MPL_free(local_procs);
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
MPIR_FUNC_TERSE_EXIT(MPID_STATE_MPIR_COMM_COMMIT);
|
|
Packit Service |
c5cf8c |
return mpi_errno;
|
|
Packit Service |
c5cf8c |
fn_fail:
|
|
Packit Service |
c5cf8c |
goto fn_exit;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
/* Returns true if the given communicator is aware of node topology information,
|
|
Packit Service |
c5cf8c |
false otherwise. Such information could be used to implement more efficient
|
|
Packit Service |
c5cf8c |
collective communication, for example. */
|
|
Packit Service |
c5cf8c |
int MPIR_Comm_is_node_aware(MPIR_Comm * comm)
|
|
Packit Service |
c5cf8c |
{
|
|
Packit Service |
c5cf8c |
return (comm->hierarchy_kind == MPIR_COMM_HIERARCHY_KIND__PARENT);
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
/* Returns true if the communicator is node-aware and processes in all the nodes
|
|
Packit Service |
c5cf8c |
are consecutive. For example, if node 0 contains "0, 1, 2, 3", node 1
|
|
Packit Service |
c5cf8c |
contains "4, 5, 6", and node 2 contains "7", we shall return true. */
|
|
Packit Service |
c5cf8c |
int MPII_Comm_is_node_consecutive(MPIR_Comm * comm)
|
|
Packit Service |
c5cf8c |
{
|
|
Packit Service |
c5cf8c |
int i = 0, curr_nodeidx = 0;
|
|
Packit Service |
c5cf8c |
int *internode_table = comm->internode_table;
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
if (!MPIR_Comm_is_node_aware(comm))
|
|
Packit Service |
c5cf8c |
return 0;
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
for (; i < comm->local_size; i++) {
|
|
Packit Service |
c5cf8c |
if (internode_table[i] == curr_nodeidx + 1)
|
|
Packit Service |
c5cf8c |
curr_nodeidx++;
|
|
Packit Service |
c5cf8c |
else if (internode_table[i] != curr_nodeidx)
|
|
Packit Service |
c5cf8c |
return 0;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
return 1;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
/*
|
|
Packit Service |
c5cf8c |
* Copy a communicator, including creating a new context and copying the
|
|
Packit Service |
c5cf8c |
* virtual connection tables and clearing the various fields.
|
|
Packit Service |
c5cf8c |
* Does *not* copy attributes. If size is < the size of the local group
|
|
Packit Service |
c5cf8c |
* in the input communicator, copy only the first size elements.
|
|
Packit Service |
c5cf8c |
* If this process is not a member, return a null pointer in outcomm_ptr.
|
|
Packit Service |
c5cf8c |
* This is only supported in the case where the communicator is in
|
|
Packit Service |
c5cf8c |
* Intracomm (not an Intercomm). Note that this is all that is required
|
|
Packit Service |
c5cf8c |
* for cart_create and graph_create.
|
|
Packit Service |
c5cf8c |
*
|
|
Packit Service |
c5cf8c |
* Used by cart_create, graph_create, and dup_create
|
|
Packit Service |
c5cf8c |
*/
|
|
Packit Service |
c5cf8c |
#undef FUNCNAME
|
|
Packit Service |
c5cf8c |
#define FUNCNAME MPII_Comm_copy
|
|
Packit Service |
c5cf8c |
#undef FCNAME
|
|
Packit Service |
c5cf8c |
#define FCNAME "MPII_Comm_copy"
|
|
Packit Service |
c5cf8c |
int MPII_Comm_copy(MPIR_Comm * comm_ptr, int size, MPIR_Comm ** outcomm_ptr)
|
|
Packit Service |
c5cf8c |
{
|
|
Packit Service |
c5cf8c |
int mpi_errno = MPI_SUCCESS;
|
|
Packit Service |
c5cf8c |
MPIR_Context_id_t new_context_id, new_recvcontext_id;
|
|
Packit Service |
c5cf8c |
MPIR_Comm *newcomm_ptr = NULL;
|
|
Packit Service |
c5cf8c |
MPIR_Comm_map_t *map = NULL;
|
|
Packit Service |
c5cf8c |
MPIR_FUNC_TERSE_STATE_DECL(MPID_STATE_MPIR_COMM_COPY);
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
MPIR_FUNC_TERSE_ENTER(MPID_STATE_MPIR_COMM_COPY);
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
/* Get a new context first. We need this to be collective over the
|
|
Packit Service |
c5cf8c |
* input communicator */
|
|
Packit Service |
c5cf8c |
/* If there is a context id cache in oldcomm, use it here. Otherwise,
|
|
Packit Service |
c5cf8c |
* use the appropriate algorithm to get a new context id. Be careful
|
|
Packit Service |
c5cf8c |
* of intercomms here */
|
|
Packit Service |
c5cf8c |
if (comm_ptr->comm_kind == MPIR_COMM_KIND__INTERCOMM) {
|
|
Packit Service |
c5cf8c |
mpi_errno = MPIR_Get_intercomm_contextid(comm_ptr, &new_context_id, &new_recvcontext_id);
|
|
Packit Service |
c5cf8c |
if (mpi_errno)
|
|
Packit Service |
c5cf8c |
MPIR_ERR_POP(mpi_errno);
|
|
Packit Service |
c5cf8c |
} else {
|
|
Packit Service |
c5cf8c |
mpi_errno = MPIR_Get_contextid_sparse(comm_ptr, &new_context_id, FALSE);
|
|
Packit Service |
c5cf8c |
new_recvcontext_id = new_context_id;
|
|
Packit Service |
c5cf8c |
if (mpi_errno)
|
|
Packit Service |
c5cf8c |
MPIR_ERR_POP(mpi_errno);
|
|
Packit Service |
c5cf8c |
MPIR_Assert(new_context_id != 0);
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
/* This is the local size, not the remote size, in the case of
|
|
Packit Service |
c5cf8c |
* an intercomm */
|
|
Packit Service |
c5cf8c |
if (comm_ptr->rank >= size) {
|
|
Packit Service |
c5cf8c |
*outcomm_ptr = 0;
|
|
Packit Service |
c5cf8c |
/* always free the recvcontext ID, never the "send" ID */
|
|
Packit Service |
c5cf8c |
MPIR_Free_contextid(new_recvcontext_id);
|
|
Packit Service |
c5cf8c |
goto fn_exit;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
/* We're left with the processes that will have a non-null communicator.
|
|
Packit Service |
c5cf8c |
* Create the object, initialize the data, and return the result */
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
mpi_errno = MPIR_Comm_create(&newcomm_ptr);
|
|
Packit Service |
c5cf8c |
if (mpi_errno)
|
|
Packit Service |
c5cf8c |
goto fn_fail;
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
newcomm_ptr->context_id = new_context_id;
|
|
Packit Service |
c5cf8c |
newcomm_ptr->recvcontext_id = new_recvcontext_id;
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
/* Save the kind of the communicator */
|
|
Packit Service |
c5cf8c |
newcomm_ptr->comm_kind = comm_ptr->comm_kind;
|
|
Packit Service |
c5cf8c |
newcomm_ptr->local_comm = 0;
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
/* There are two cases here - size is the same as the old communicator,
|
|
Packit Service |
c5cf8c |
* or it is smaller. If the size is the same, we can just add a reference.
|
|
Packit Service |
c5cf8c |
* Otherwise, we need to create a new network address mapping. Note that this is the
|
|
Packit Service |
c5cf8c |
* test that matches the test on rank above. */
|
|
Packit Service |
c5cf8c |
if (size == comm_ptr->local_size) {
|
|
Packit Service |
c5cf8c |
/* Duplicate the network address mapping */
|
|
Packit Service |
c5cf8c |
if (comm_ptr->comm_kind == MPIR_COMM_KIND__INTRACOMM)
|
|
Packit Service |
c5cf8c |
MPIR_Comm_map_dup(newcomm_ptr, comm_ptr, MPIR_COMM_MAP_DIR__L2L);
|
|
Packit Service |
c5cf8c |
else
|
|
Packit Service |
c5cf8c |
MPIR_Comm_map_dup(newcomm_ptr, comm_ptr, MPIR_COMM_MAP_DIR__R2R);
|
|
Packit Service |
c5cf8c |
} else {
|
|
Packit Service |
c5cf8c |
int i;
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
if (comm_ptr->comm_kind == MPIR_COMM_KIND__INTRACOMM)
|
|
Packit Service |
c5cf8c |
MPIR_Comm_map_irregular(newcomm_ptr, comm_ptr, NULL, size, MPIR_COMM_MAP_DIR__L2L,
|
|
Packit Service |
c5cf8c |
&map);
|
|
Packit Service |
c5cf8c |
else
|
|
Packit Service |
c5cf8c |
MPIR_Comm_map_irregular(newcomm_ptr, comm_ptr, NULL, size, MPIR_COMM_MAP_DIR__R2R,
|
|
Packit Service |
c5cf8c |
&map);
|
|
Packit Service |
c5cf8c |
for (i = 0; i < size; i++) {
|
|
Packit Service |
c5cf8c |
/* For rank i in the new communicator, find the corresponding
|
|
Packit Service |
c5cf8c |
* rank in the input communicator */
|
|
Packit Service |
c5cf8c |
map->src_mapping[i] = i;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
/* If it is an intercomm, duplicate the local network address references */
|
|
Packit Service |
c5cf8c |
if (comm_ptr->comm_kind == MPIR_COMM_KIND__INTERCOMM) {
|
|
Packit Service |
c5cf8c |
MPIR_Comm_map_dup(newcomm_ptr, comm_ptr, MPIR_COMM_MAP_DIR__L2L);
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
/* Set the sizes and ranks */
|
|
Packit Service |
c5cf8c |
newcomm_ptr->rank = comm_ptr->rank;
|
|
Packit Service |
c5cf8c |
if (comm_ptr->comm_kind == MPIR_COMM_KIND__INTERCOMM) {
|
|
Packit Service |
c5cf8c |
newcomm_ptr->local_size = comm_ptr->local_size;
|
|
Packit Service |
c5cf8c |
newcomm_ptr->remote_size = comm_ptr->remote_size;
|
|
Packit Service |
c5cf8c |
newcomm_ptr->is_low_group = comm_ptr->is_low_group;
|
|
Packit Service |
c5cf8c |
} else {
|
|
Packit Service |
c5cf8c |
newcomm_ptr->local_size = size;
|
|
Packit Service |
c5cf8c |
newcomm_ptr->remote_size = size;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
newcomm_ptr->pof2 = MPL_pof2(newcomm_ptr->local_size);
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
/* Inherit the error handler (if any) */
|
|
Packit Service |
c5cf8c |
MPID_THREAD_CS_ENTER(POBJ, MPIR_THREAD_POBJ_COMM_MUTEX(comm_ptr));
|
|
Packit Service |
c5cf8c |
newcomm_ptr->errhandler = comm_ptr->errhandler;
|
|
Packit Service |
c5cf8c |
if (comm_ptr->errhandler) {
|
|
Packit Service |
c5cf8c |
MPIR_Errhandler_add_ref(comm_ptr->errhandler);
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
MPID_THREAD_CS_EXIT(POBJ, MPIR_THREAD_POBJ_COMM_MUTEX(comm_ptr));
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
mpi_errno = MPIR_Comm_commit(newcomm_ptr);
|
|
Packit Service |
c5cf8c |
if (mpi_errno)
|
|
Packit Service |
c5cf8c |
MPIR_ERR_POP(mpi_errno);
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
/* Start with no attributes on this communicator */
|
|
Packit Service |
c5cf8c |
newcomm_ptr->attributes = 0;
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
/* Copy over the info hints from the original communicator. */
|
|
Packit Service |
c5cf8c |
mpi_errno = MPIR_Info_dup_impl(comm_ptr->info, &(newcomm_ptr->info));
|
|
Packit Service |
c5cf8c |
if (mpi_errno)
|
|
Packit Service |
c5cf8c |
MPIR_ERR_POP(mpi_errno);
|
|
Packit Service |
c5cf8c |
mpi_errno = MPII_Comm_apply_hints(newcomm_ptr, newcomm_ptr->info);
|
|
Packit Service |
c5cf8c |
if (mpi_errno)
|
|
Packit Service |
c5cf8c |
MPIR_ERR_POP(mpi_errno);
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
*outcomm_ptr = newcomm_ptr;
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
fn_fail:
|
|
Packit Service |
c5cf8c |
fn_exit:
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
MPIR_FUNC_TERSE_EXIT(MPID_STATE_MPIR_COMM_COPY);
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
return mpi_errno;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
/* Copy a communicator, including copying the virtual connection tables and
|
|
Packit Service |
c5cf8c |
* clearing the various fields. Does *not* allocate a context ID or commit the
|
|
Packit Service |
c5cf8c |
* communicator. Does *not* copy attributes.
|
|
Packit Service |
c5cf8c |
*
|
|
Packit Service |
c5cf8c |
* Used by comm_idup.
|
|
Packit Service |
c5cf8c |
*/
|
|
Packit Service |
c5cf8c |
#undef FUNCNAME
|
|
Packit Service |
c5cf8c |
#define FUNCNAME MPII_Comm_copy_data
|
|
Packit Service |
c5cf8c |
#undef FCNAME
|
|
Packit Service |
c5cf8c |
#define FCNAME MPL_QUOTE(FUNCNAME)
|
|
Packit Service |
c5cf8c |
int MPII_Comm_copy_data(MPIR_Comm * comm_ptr, MPIR_Comm ** outcomm_ptr)
|
|
Packit Service |
c5cf8c |
{
|
|
Packit Service |
c5cf8c |
int mpi_errno = MPI_SUCCESS;
|
|
Packit Service |
c5cf8c |
MPIR_Comm *newcomm_ptr = NULL;
|
|
Packit Service |
c5cf8c |
MPIR_FUNC_TERSE_STATE_DECL(MPID_STATE_MPIR_COMM_COPY_DATA);
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
MPIR_FUNC_TERSE_ENTER(MPID_STATE_MPIR_COMM_COPY_DATA);
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
mpi_errno = MPIR_Comm_create(&newcomm_ptr);
|
|
Packit Service |
c5cf8c |
if (mpi_errno)
|
|
Packit Service |
c5cf8c |
goto fn_fail;
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
/* use a large garbage value to ensure errors are caught more easily */
|
|
Packit Service |
c5cf8c |
newcomm_ptr->context_id = 32767;
|
|
Packit Service |
c5cf8c |
newcomm_ptr->recvcontext_id = 32767;
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
/* Save the kind of the communicator */
|
|
Packit Service |
c5cf8c |
newcomm_ptr->comm_kind = comm_ptr->comm_kind;
|
|
Packit Service |
c5cf8c |
newcomm_ptr->local_comm = 0;
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
if (comm_ptr->comm_kind == MPIR_COMM_KIND__INTRACOMM)
|
|
Packit Service |
c5cf8c |
MPIR_Comm_map_dup(newcomm_ptr, comm_ptr, MPIR_COMM_MAP_DIR__L2L);
|
|
Packit Service |
c5cf8c |
else
|
|
Packit Service |
c5cf8c |
MPIR_Comm_map_dup(newcomm_ptr, comm_ptr, MPIR_COMM_MAP_DIR__R2R);
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
/* If it is an intercomm, duplicate the network address mapping */
|
|
Packit Service |
c5cf8c |
if (comm_ptr->comm_kind == MPIR_COMM_KIND__INTERCOMM) {
|
|
Packit Service |
c5cf8c |
MPIR_Comm_map_dup(newcomm_ptr, comm_ptr, MPIR_COMM_MAP_DIR__L2L);
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
/* Set the sizes and ranks */
|
|
Packit Service |
c5cf8c |
newcomm_ptr->rank = comm_ptr->rank;
|
|
Packit Service |
c5cf8c |
newcomm_ptr->local_size = comm_ptr->local_size;
|
|
Packit Service |
c5cf8c |
newcomm_ptr->pof2 = comm_ptr->pof2;
|
|
Packit Service |
c5cf8c |
newcomm_ptr->remote_size = comm_ptr->remote_size;
|
|
Packit Service |
c5cf8c |
newcomm_ptr->is_low_group = comm_ptr->is_low_group; /* only relevant for intercomms */
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
/* Inherit the error handler (if any) */
|
|
Packit Service |
c5cf8c |
MPID_THREAD_CS_ENTER(POBJ, MPIR_THREAD_POBJ_COMM_MUTEX(comm_ptr));
|
|
Packit Service |
c5cf8c |
newcomm_ptr->errhandler = comm_ptr->errhandler;
|
|
Packit Service |
c5cf8c |
if (comm_ptr->errhandler) {
|
|
Packit Service |
c5cf8c |
MPIR_Errhandler_add_ref(comm_ptr->errhandler);
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
MPID_THREAD_CS_EXIT(POBJ, MPIR_THREAD_POBJ_COMM_MUTEX(comm_ptr));
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
/* Start with no attributes on this communicator */
|
|
Packit Service |
c5cf8c |
newcomm_ptr->attributes = 0;
|
|
Packit Service |
c5cf8c |
*outcomm_ptr = newcomm_ptr;
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
fn_fail:
|
|
Packit Service |
c5cf8c |
MPIR_FUNC_TERSE_EXIT(MPID_STATE_MPIR_COMM_COPY_DATA);
|
|
Packit Service |
c5cf8c |
return mpi_errno;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
/* Common body between MPIR_Comm_release and MPIR_comm_release_always. This
|
|
Packit Service |
c5cf8c |
* helper function frees the actual MPIR_Comm structure and any associated
|
|
Packit Service |
c5cf8c |
* storage. It also releases any references to other objects.
|
|
Packit Service |
c5cf8c |
* This function should only be called when the communicator's reference count
|
|
Packit Service |
c5cf8c |
* has dropped to 0.
|
|
Packit Service |
c5cf8c |
*
|
|
Packit Service |
c5cf8c |
* !!! This routine should *never* be called outside of MPIR_Comm_release{,_always} !!!
|
|
Packit Service |
c5cf8c |
*/
|
|
Packit Service |
c5cf8c |
#undef FUNCNAME
|
|
Packit Service |
c5cf8c |
#define FUNCNAME MPIR_Comm_delete_internal
|
|
Packit Service |
c5cf8c |
#undef FCNAME
|
|
Packit Service |
c5cf8c |
#define FCNAME MPL_QUOTE(FUNCNAME)
|
|
Packit Service |
c5cf8c |
int MPIR_Comm_delete_internal(MPIR_Comm * comm_ptr)
|
|
Packit Service |
c5cf8c |
{
|
|
Packit Service |
c5cf8c |
int in_use;
|
|
Packit Service |
c5cf8c |
int mpi_errno = MPI_SUCCESS;
|
|
Packit Service |
c5cf8c |
MPIR_FUNC_TERSE_STATE_DECL(MPID_STATE_COMM_DELETE_INTERNAL);
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
MPIR_FUNC_TERSE_ENTER(MPID_STATE_COMM_DELETE_INTERNAL);
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
MPIR_Assert(MPIR_Object_get_ref(comm_ptr) == 0); /* sanity check */
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
/* Remove the attributes, executing the attribute delete routine.
|
|
Packit Service |
c5cf8c |
* Do this only if the attribute functions are defined.
|
|
Packit Service |
c5cf8c |
* This must be done first, because if freeing the attributes
|
|
Packit Service |
c5cf8c |
* returns an error, the communicator is not freed */
|
|
Packit Service |
c5cf8c |
if (MPIR_Process.attr_free && comm_ptr->attributes) {
|
|
Packit Service |
c5cf8c |
/* Temporarily add a reference to this communicator because
|
|
Packit Service |
c5cf8c |
* the attr_free code requires a valid communicator */
|
|
Packit Service |
c5cf8c |
MPIR_Object_add_ref(comm_ptr);
|
|
Packit Service |
c5cf8c |
mpi_errno = MPIR_Process.attr_free(comm_ptr->handle, &comm_ptr->attributes);
|
|
Packit Service |
c5cf8c |
/* Release the temporary reference added before the call to
|
|
Packit Service |
c5cf8c |
* attr_free */
|
|
Packit Service |
c5cf8c |
MPIR_Object_release_ref(comm_ptr, &in_use);
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
/* If the attribute delete functions return failure, the
|
|
Packit Service |
c5cf8c |
* communicator must not be freed. That is the reason for the
|
|
Packit Service |
c5cf8c |
* test on mpi_errno here. */
|
|
Packit Service |
c5cf8c |
if (mpi_errno == MPI_SUCCESS) {
|
|
Packit Service |
c5cf8c |
/* If this communicator is our parent, and we're disconnecting
|
|
Packit Service |
c5cf8c |
* from the parent, mark that fact */
|
|
Packit Service |
c5cf8c |
if (MPIR_Process.comm_parent == comm_ptr)
|
|
Packit Service |
c5cf8c |
MPIR_Process.comm_parent = NULL;
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
/* Cleanup collectives-specific infrastructure */
|
|
Packit Service |
c5cf8c |
mpi_errno = MPII_Coll_comm_cleanup(comm_ptr);
|
|
Packit Service |
c5cf8c |
if (mpi_errno)
|
|
Packit Service |
c5cf8c |
MPIR_ERR_POP(mpi_errno);
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
/* Notify the device that the communicator is about to be
|
|
Packit Service |
c5cf8c |
* destroyed */
|
|
Packit Service |
c5cf8c |
mpi_errno = MPID_Comm_free_hook(comm_ptr);
|
|
Packit Service |
c5cf8c |
if (mpi_errno)
|
|
Packit Service |
c5cf8c |
MPIR_ERR_POP(mpi_errno);
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
/* Free info hints */
|
|
Packit Service |
c5cf8c |
if (comm_ptr->info != NULL) {
|
|
Packit Service |
c5cf8c |
MPIR_Info_free(comm_ptr->info);
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
if (comm_ptr->comm_kind == MPIR_COMM_KIND__INTERCOMM && comm_ptr->local_comm)
|
|
Packit Service |
c5cf8c |
MPIR_Comm_release(comm_ptr->local_comm);
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
/* Free the local and remote groups, if they exist */
|
|
Packit Service |
c5cf8c |
if (comm_ptr->local_group)
|
|
Packit Service |
c5cf8c |
MPIR_Group_release(comm_ptr->local_group);
|
|
Packit Service |
c5cf8c |
if (comm_ptr->remote_group)
|
|
Packit Service |
c5cf8c |
MPIR_Group_release(comm_ptr->remote_group);
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
/* free the intra/inter-node communicators, if they exist */
|
|
Packit Service |
c5cf8c |
if (comm_ptr->node_comm)
|
|
Packit Service |
c5cf8c |
MPIR_Comm_release(comm_ptr->node_comm);
|
|
Packit Service |
c5cf8c |
if (comm_ptr->node_roots_comm)
|
|
Packit Service |
c5cf8c |
MPIR_Comm_release(comm_ptr->node_roots_comm);
|
|
Packit Service |
c5cf8c |
if (comm_ptr->intranode_table != NULL)
|
|
Packit Service |
c5cf8c |
MPL_free(comm_ptr->intranode_table);
|
|
Packit Service |
c5cf8c |
if (comm_ptr->internode_table != NULL)
|
|
Packit Service |
c5cf8c |
MPL_free(comm_ptr->internode_table);
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
/* Free the context value. This should come after freeing the
|
|
Packit Service |
c5cf8c |
* intra/inter-node communicators since those free calls won't
|
|
Packit Service |
c5cf8c |
* release this context ID and releasing this before then could lead
|
|
Packit Service |
c5cf8c |
* to races once we make threading finer grained. */
|
|
Packit Service |
c5cf8c |
/* This must be the recvcontext_id (i.e. not the (send)context_id)
|
|
Packit Service |
c5cf8c |
* because in the case of intercommunicators the send context ID is
|
|
Packit Service |
c5cf8c |
* allocated out of the remote group's bit vector, not ours. */
|
|
Packit Service |
c5cf8c |
MPIR_Free_contextid(comm_ptr->recvcontext_id);
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
#if MPICH_THREAD_GRANULARITY == MPICH_THREAD_GRANULARITY__POBJ
|
|
Packit Service |
c5cf8c |
{
|
|
Packit Service |
c5cf8c |
int thr_err;
|
|
Packit Service |
c5cf8c |
MPID_Thread_mutex_destroy(&MPIR_THREAD_POBJ_COMM_MUTEX(comm_ptr), &thr_err);
|
|
Packit Service |
c5cf8c |
MPIR_Assert(thr_err == 0);
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
#endif
|
|
Packit Service |
c5cf8c |
/* We need to release the error handler */
|
|
Packit Service |
c5cf8c |
if (comm_ptr->errhandler &&
|
|
Packit Service |
c5cf8c |
!(HANDLE_GET_KIND(comm_ptr->errhandler->handle) == HANDLE_KIND_BUILTIN)) {
|
|
Packit Service |
c5cf8c |
int errhInuse;
|
|
Packit Service |
c5cf8c |
MPIR_Errhandler_release_ref(comm_ptr->errhandler, &errhInuse);
|
|
Packit Service |
c5cf8c |
if (!errhInuse) {
|
|
Packit Service |
c5cf8c |
MPIR_Handle_obj_free(&MPIR_Errhandler_mem, comm_ptr->errhandler);
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
/* Remove from the list of active communicators if
|
|
Packit Service |
c5cf8c |
* we are supporting message-queue debugging. We make this
|
|
Packit Service |
c5cf8c |
* conditional on having debugger support since the
|
|
Packit Service |
c5cf8c |
* operation is not constant-time */
|
|
Packit Service |
c5cf8c |
MPII_COMML_FORGET(comm_ptr);
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
/* Check for predefined communicators - these should not
|
|
Packit Service |
c5cf8c |
* be freed */
|
|
Packit Service |
c5cf8c |
if (!(HANDLE_GET_KIND(comm_ptr->handle) == HANDLE_KIND_BUILTIN))
|
|
Packit Service |
c5cf8c |
MPIR_Handle_obj_free(&MPIR_Comm_mem, comm_ptr);
|
|
Packit Service |
c5cf8c |
} else {
|
|
Packit Service |
c5cf8c |
/* If the user attribute free function returns an error,
|
|
Packit Service |
c5cf8c |
* then do not free the communicator */
|
|
Packit Service |
c5cf8c |
MPIR_Comm_add_ref(comm_ptr);
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
fn_exit:
|
|
Packit Service |
c5cf8c |
MPIR_FUNC_TERSE_EXIT(MPID_STATE_COMM_DELETE_INTERNAL);
|
|
Packit Service |
c5cf8c |
return mpi_errno;
|
|
Packit Service |
c5cf8c |
fn_fail:
|
|
Packit Service |
c5cf8c |
goto fn_exit;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
/* Release a reference to a communicator. If there are no pending
|
|
Packit Service |
c5cf8c |
references, delete the communicator and recover all storage and
|
|
Packit Service |
c5cf8c |
context ids. This version of the function always manipulates the reference
|
|
Packit Service |
c5cf8c |
counts, even for predefined objects. */
|
|
Packit Service |
c5cf8c |
#undef FUNCNAME
|
|
Packit Service |
c5cf8c |
#define FUNCNAME MPIR_Comm_release_always
|
|
Packit Service |
c5cf8c |
#undef FCNAME
|
|
Packit Service |
c5cf8c |
#define FCNAME MPL_QUOTE(FUNCNAME)
|
|
Packit Service |
c5cf8c |
int MPIR_Comm_release_always(MPIR_Comm * comm_ptr)
|
|
Packit Service |
c5cf8c |
{
|
|
Packit Service |
c5cf8c |
int mpi_errno = MPI_SUCCESS;
|
|
Packit Service |
c5cf8c |
int in_use;
|
|
Packit Service |
c5cf8c |
MPIR_FUNC_TERSE_STATE_DECL(MPID_STATE_MPIR_COMM_RELEASE_ALWAYS);
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
MPIR_FUNC_TERSE_ENTER(MPID_STATE_MPIR_COMM_RELEASE_ALWAYS);
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
/* we want to short-circuit any optimization that avoids reference counting
|
|
Packit Service |
c5cf8c |
* predefined communicators, such as MPI_COMM_WORLD or MPI_COMM_SELF. */
|
|
Packit Service |
c5cf8c |
MPIR_Object_release_ref_always(comm_ptr, &in_use);
|
|
Packit Service |
c5cf8c |
if (!in_use) {
|
|
Packit Service |
c5cf8c |
mpi_errno = MPIR_Comm_delete_internal(comm_ptr);
|
|
Packit Service |
c5cf8c |
if (mpi_errno)
|
|
Packit Service |
c5cf8c |
MPIR_ERR_POP(mpi_errno);
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
fn_exit:
|
|
Packit Service |
c5cf8c |
MPIR_FUNC_TERSE_EXIT(MPID_STATE_MPIR_COMM_RELEASE_ALWAYS);
|
|
Packit Service |
c5cf8c |
return mpi_errno;
|
|
Packit Service |
c5cf8c |
fn_fail:
|
|
Packit Service |
c5cf8c |
goto fn_exit;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
/* Apply all known info hints in the specified info chain to the given
|
|
Packit Service |
c5cf8c |
* communicator. */
|
|
Packit Service |
c5cf8c |
#undef FUNCNAME
|
|
Packit Service |
c5cf8c |
#define FUNCNAME MPII_Comm_apply_hints
|
|
Packit Service |
c5cf8c |
#undef FCNAME
|
|
Packit Service |
c5cf8c |
#define FCNAME MPL_QUOTE(FUNCNAME)
|
|
Packit Service |
c5cf8c |
int MPII_Comm_apply_hints(MPIR_Comm * comm_ptr, MPIR_Info * info_ptr)
|
|
Packit Service |
c5cf8c |
{
|
|
Packit Service |
c5cf8c |
int mpi_errno = MPI_SUCCESS;
|
|
Packit Service |
c5cf8c |
MPIR_Info *hint = NULL;
|
|
Packit Service |
c5cf8c |
char hint_name[MPI_MAX_INFO_KEY] = { 0 };
|
|
Packit Service |
c5cf8c |
struct MPIR_Comm_hint_fn_elt *hint_fn = NULL;
|
|
Packit Service |
c5cf8c |
MPIR_FUNC_TERSE_STATE_DECL(MPID_STATE_MPIR_COMM_APPLY_HINTS);
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
MPIR_FUNC_TERSE_ENTER(MPID_STATE_MPIR_COMM_APPLY_HINTS);
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
LL_FOREACH(info_ptr, hint) {
|
|
Packit Service |
c5cf8c |
/* Have we hit the default, empty info hint? */
|
|
Packit Service |
c5cf8c |
if (hint->key == NULL)
|
|
Packit Service |
c5cf8c |
continue;
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
MPL_strncpy(hint_name, hint->key, MPI_MAX_INFO_KEY);
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
HASH_FIND_STR(MPID_hint_fns, hint_name, hint_fn);
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
/* Skip hints that MPICH doesn't recognize. */
|
|
Packit Service |
c5cf8c |
if (hint_fn) {
|
|
Packit Service |
c5cf8c |
mpi_errno = hint_fn->fn(comm_ptr, hint, hint_fn->state);
|
|
Packit Service |
c5cf8c |
if (mpi_errno)
|
|
Packit Service |
c5cf8c |
MPIR_ERR_POP(mpi_errno);
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
fn_exit:
|
|
Packit Service |
c5cf8c |
MPIR_FUNC_TERSE_EXIT(MPID_STATE_MPIR_COMM_APPLY_HINTS);
|
|
Packit Service |
c5cf8c |
return mpi_errno;
|
|
Packit Service |
c5cf8c |
fn_fail:
|
|
Packit Service |
c5cf8c |
goto fn_exit;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
#undef FUNCNAME
|
|
Packit Service |
c5cf8c |
#define FUNCNAME free_hint_handles
|
|
Packit Service |
c5cf8c |
#undef FCNAME
|
|
Packit Service |
c5cf8c |
#define FCNAME MPL_QUOTE(FUNCNAME)
|
|
Packit Service |
c5cf8c |
static int free_hint_handles(void *ignore)
|
|
Packit Service |
c5cf8c |
{
|
|
Packit Service |
c5cf8c |
int mpi_errno = MPI_SUCCESS;
|
|
Packit Service |
c5cf8c |
struct MPIR_Comm_hint_fn_elt *curr_hint = NULL, *tmp = NULL;
|
|
Packit Service |
c5cf8c |
MPIR_FUNC_TERSE_STATE_DECL(MPID_STATE_MPIR_COMM_FREE_HINT_HANDLES);
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
MPIR_FUNC_TERSE_ENTER(MPID_STATE_MPIR_COMM_FREE_HINT_HANDLES);
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
if (MPID_hint_fns) {
|
|
Packit Service |
c5cf8c |
HASH_ITER(hh, MPID_hint_fns, curr_hint, tmp) {
|
|
Packit Service |
c5cf8c |
HASH_DEL(MPID_hint_fns, curr_hint);
|
|
Packit Service |
c5cf8c |
MPL_free(curr_hint);
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
MPIR_FUNC_TERSE_EXIT(MPID_STATE_MPIR_COMM_FREE_HINT_HANDLES);
|
|
Packit Service |
c5cf8c |
return mpi_errno;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
/* The hint logic is stored in a uthash, with hint name as key and
|
|
Packit Service |
c5cf8c |
* the function responsible for applying the hint as the value. */
|
|
Packit Service |
c5cf8c |
#undef FUNCNAME
|
|
Packit Service |
c5cf8c |
#define FUNCNAME MPIR_Comm_register_hint
|
|
Packit Service |
c5cf8c |
#undef FCNAME
|
|
Packit Service |
c5cf8c |
#define FCNAME MPL_QUOTE(FUNCNAME)
|
|
Packit Service |
c5cf8c |
int MPIR_Comm_register_hint(const char *hint_key, MPIR_Comm_hint_fn_t fn, void *state)
|
|
Packit Service |
c5cf8c |
{
|
|
Packit Service |
c5cf8c |
int mpi_errno = MPI_SUCCESS;
|
|
Packit Service |
c5cf8c |
struct MPIR_Comm_hint_fn_elt *hint_elt = NULL;
|
|
Packit Service |
c5cf8c |
MPIR_FUNC_TERSE_STATE_DECL(MPID_STATE_MPIR_COMM_REGISTER_HINT);
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
MPIR_FUNC_TERSE_ENTER(MPID_STATE_MPIR_COMM_REGISTER_HINT);
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
if (MPID_hint_fns == NULL) {
|
|
Packit Service |
c5cf8c |
MPIR_Add_finalize(free_hint_handles, NULL, MPIR_FINALIZE_CALLBACK_PRIO - 1);
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
hint_elt = MPL_malloc(sizeof(struct MPIR_Comm_hint_fn_elt), MPL_MEM_COMM);
|
|
Packit Service |
c5cf8c |
MPL_strncpy(hint_elt->name, hint_key, MPI_MAX_INFO_KEY);
|
|
Packit Service |
c5cf8c |
hint_elt->state = state;
|
|
Packit Service |
c5cf8c |
hint_elt->fn = fn;
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
HASH_ADD_STR(MPID_hint_fns, name, hint_elt, MPL_MEM_COMM);
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
MPIR_FUNC_TERSE_EXIT(MPID_STATE_MPIR_COMM_REGISTER_HINT);
|
|
Packit Service |
c5cf8c |
return mpi_errno;
|
|
Packit Service |
c5cf8c |
}
|