|
Packit Service |
c5cf8c |
/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */
|
|
Packit Service |
c5cf8c |
/*
|
|
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 |
#include "mpiimpl.h"
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
static int unweighted_dummy = 0x46618;
|
|
Packit Service |
c5cf8c |
static int weights_empty_dummy = 0x022284;
|
|
Packit Service |
c5cf8c |
/* cannot ==NULL, would be ambiguous */
|
|
Packit Service |
c5cf8c |
int *const MPI_UNWEIGHTED = &unweighted_dummy;
|
|
Packit Service |
c5cf8c |
int *const MPI_WEIGHTS_EMPTY = &weights_empty_dummy;
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
/* Keyval for topology information */
|
|
Packit Service |
c5cf8c |
static int MPIR_Topology_keyval = MPI_KEYVAL_INVALID;
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
/* Local functions */
|
|
Packit Service |
c5cf8c |
static int MPIR_Topology_copy_fn(MPI_Comm, int, void *, void *, void *, int *);
|
|
Packit Service |
c5cf8c |
static int MPIR_Topology_delete_fn(MPI_Comm, int, void *, void *);
|
|
Packit Service |
c5cf8c |
static int MPIR_Topology_finalize(void *);
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
/*
|
|
Packit Service |
c5cf8c |
Return a poiner to the topology structure on a communicator.
|
|
Packit Service |
c5cf8c |
Returns null if no topology structure is defined
|
|
Packit Service |
c5cf8c |
*/
|
|
Packit Service |
c5cf8c |
MPIR_Topology *MPIR_Topology_get(MPIR_Comm * comm_ptr)
|
|
Packit Service |
c5cf8c |
{
|
|
Packit Service |
c5cf8c |
int mpi_errno = MPI_SUCCESS;
|
|
Packit Service |
c5cf8c |
MPIR_Topology *topo_ptr;
|
|
Packit Service |
c5cf8c |
int flag;
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
if (MPIR_Topology_keyval == MPI_KEYVAL_INVALID) {
|
|
Packit Service |
c5cf8c |
return 0;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
mpi_errno = MPII_Comm_get_attr(comm_ptr->handle, MPIR_Topology_keyval,
|
|
Packit Service |
c5cf8c |
&topo_ptr, &flag, MPIR_ATTR_PTR);
|
|
Packit Service |
c5cf8c |
if (mpi_errno)
|
|
Packit Service |
c5cf8c |
return NULL;
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
if (flag)
|
|
Packit Service |
c5cf8c |
return topo_ptr;
|
|
Packit Service |
c5cf8c |
return NULL;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
#undef FUNCNAME
|
|
Packit Service |
c5cf8c |
#define FUNCNAME MPIR_Topology_put
|
|
Packit Service |
c5cf8c |
#undef FCNAME
|
|
Packit Service |
c5cf8c |
#define FCNAME MPL_QUOTE(FUNCNAME)
|
|
Packit Service |
c5cf8c |
int MPIR_Topology_put(MPIR_Comm * comm_ptr, MPIR_Topology * topo_ptr)
|
|
Packit Service |
c5cf8c |
{
|
|
Packit Service |
c5cf8c |
int mpi_errno = MPI_SUCCESS;
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
MPIR_Assert(comm_ptr != NULL);
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
if (MPIR_Topology_keyval == MPI_KEYVAL_INVALID) {
|
|
Packit Service |
c5cf8c |
/* Create a new keyval */
|
|
Packit Service |
c5cf8c |
/* FIXME - thread safe code needs a thread lock here, followed
|
|
Packit Service |
c5cf8c |
* by another test on the keyval to see if a different thread
|
|
Packit Service |
c5cf8c |
* got there first */
|
|
Packit Service |
c5cf8c |
mpi_errno = MPIR_Comm_create_keyval_impl(MPIR_Topology_copy_fn,
|
|
Packit Service |
c5cf8c |
MPIR_Topology_delete_fn, &MPIR_Topology_keyval, 0);
|
|
Packit Service |
c5cf8c |
/* Register the finalize handler */
|
|
Packit Service |
c5cf8c |
if (mpi_errno)
|
|
Packit Service |
c5cf8c |
MPIR_ERR_POP(mpi_errno);
|
|
Packit Service |
c5cf8c |
MPIR_Add_finalize(MPIR_Topology_finalize, (void *) 0, MPIR_FINALIZE_CALLBACK_PRIO - 1);
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
mpi_errno = MPIR_Comm_set_attr_impl(comm_ptr, MPIR_Topology_keyval, topo_ptr, MPIR_ATTR_PTR);
|
|
Packit Service |
c5cf8c |
if (mpi_errno)
|
|
Packit Service |
c5cf8c |
MPIR_ERR_POP(mpi_errno);
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
fn_exit:
|
|
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 |
/* Ignore p */
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
static int MPIR_Topology_finalize(void *p ATTRIBUTE((unused)))
|
|
Packit Service |
c5cf8c |
{
|
|
Packit Service |
c5cf8c |
MPL_UNREFERENCED_ARG(p);
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
if (MPIR_Topology_keyval != MPI_KEYVAL_INVALID) {
|
|
Packit Service |
c5cf8c |
/* Just in case */
|
|
Packit Service |
c5cf8c |
MPIR_Comm_free_keyval_impl(MPIR_Topology_keyval);
|
|
Packit Service |
c5cf8c |
MPIR_Topology_keyval = MPI_KEYVAL_INVALID;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
return 0;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
static int *MPIR_Copy_array(int n, const int a[], int *err)
|
|
Packit Service |
c5cf8c |
{
|
|
Packit Service |
c5cf8c |
int *new_p;
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
/* the copy of NULL is NULL */
|
|
Packit Service |
c5cf8c |
if (a == NULL) {
|
|
Packit Service |
c5cf8c |
MPIR_Assert(n == 0);
|
|
Packit Service |
c5cf8c |
return NULL;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
new_p = (int *) MPL_malloc(n * sizeof(int), MPL_MEM_OTHER);
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
/* --BEGIN ERROR HANDLING-- */
|
|
Packit Service |
c5cf8c |
if (!new_p) {
|
|
Packit Service |
c5cf8c |
*err = MPI_ERR_OTHER;
|
|
Packit Service |
c5cf8c |
return 0;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
/* --END ERROR HANDLING-- */
|
|
Packit Service |
c5cf8c |
MPIR_Memcpy(new_p, a, n * sizeof(int));
|
|
Packit Service |
c5cf8c |
return new_p;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
/* The keyval copy and delete functions must handle copying and deleting
|
|
Packit Service |
c5cf8c |
the associated topology structures
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
We can reduce the number of allocations by making a single allocation
|
|
Packit Service |
c5cf8c |
of enough integers for all fields (including the ones in the structure)
|
|
Packit Service |
c5cf8c |
and freeing the single object later.
|
|
Packit Service |
c5cf8c |
*/
|
|
Packit Service |
c5cf8c |
#undef FUNCNAME
|
|
Packit Service |
c5cf8c |
#define FUNCNAME MPIR_Topology_copy_fn
|
|
Packit Service |
c5cf8c |
#undef FCNAME
|
|
Packit Service |
c5cf8c |
#define FCNAME MPL_QUOTE(FUNCNAME)
|
|
Packit Service |
c5cf8c |
static int MPIR_Topology_copy_fn(MPI_Comm comm ATTRIBUTE((unused)),
|
|
Packit Service |
c5cf8c |
int keyval ATTRIBUTE((unused)),
|
|
Packit Service |
c5cf8c |
void *extra_data ATTRIBUTE((unused)),
|
|
Packit Service |
c5cf8c |
void *attr_in, void *attr_out, int *flag)
|
|
Packit Service |
c5cf8c |
{
|
|
Packit Service |
c5cf8c |
MPIR_Topology *old_topology = (MPIR_Topology *) attr_in;
|
|
Packit Service |
c5cf8c |
MPIR_Topology *copy_topology = NULL;
|
|
Packit Service |
c5cf8c |
MPIR_CHKPMEM_DECL(5);
|
|
Packit Service |
c5cf8c |
int mpi_errno = 0;
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
MPL_UNREFERENCED_ARG(comm);
|
|
Packit Service |
c5cf8c |
MPL_UNREFERENCED_ARG(keyval);
|
|
Packit Service |
c5cf8c |
MPL_UNREFERENCED_ARG(extra_data);
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
*flag = 0;
|
|
Packit Service |
c5cf8c |
*(void **) attr_out = NULL;
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
MPIR_CHKPMEM_MALLOC(copy_topology, MPIR_Topology *, sizeof(MPIR_Topology), mpi_errno,
|
|
Packit Service |
c5cf8c |
"copy_topology", MPL_MEM_OTHER);
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
MPL_VG_MEM_INIT(copy_topology, sizeof(MPIR_Topology));
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
/* simplify copying and error handling */
|
|
Packit Service |
c5cf8c |
#define MPIR_ARRAY_COPY_HELPER(kind_,array_field_,count_field_) \
|
|
Packit Service |
c5cf8c |
do { \
|
|
Packit Service |
c5cf8c |
copy_topology->topo.kind_.array_field_ = \
|
|
Packit Service |
c5cf8c |
MPIR_Copy_array(old_topology->topo.kind_.count_field_, \
|
|
Packit Service |
c5cf8c |
old_topology->topo.kind_.array_field_, \
|
|
Packit Service |
c5cf8c |
&mpi_errno); \
|
|
Packit Service |
c5cf8c |
if (mpi_errno) MPIR_ERR_POP(mpi_errno); \
|
|
Packit Service |
c5cf8c |
MPIR_CHKPMEM_REGISTER(copy_topology->topo.kind_.array_field_); \
|
|
Packit Service |
c5cf8c |
} while (0)
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
copy_topology->kind = old_topology->kind;
|
|
Packit Service |
c5cf8c |
if (old_topology->kind == MPI_CART) {
|
|
Packit Service |
c5cf8c |
copy_topology->topo.cart.ndims = old_topology->topo.cart.ndims;
|
|
Packit Service |
c5cf8c |
copy_topology->topo.cart.nnodes = old_topology->topo.cart.nnodes;
|
|
Packit Service |
c5cf8c |
MPIR_ARRAY_COPY_HELPER(cart, dims, ndims);
|
|
Packit Service |
c5cf8c |
MPIR_ARRAY_COPY_HELPER(cart, periodic, ndims);
|
|
Packit Service |
c5cf8c |
MPIR_ARRAY_COPY_HELPER(cart, position, ndims);
|
|
Packit Service |
c5cf8c |
} else if (old_topology->kind == MPI_GRAPH) {
|
|
Packit Service |
c5cf8c |
copy_topology->topo.graph.nnodes = old_topology->topo.graph.nnodes;
|
|
Packit Service |
c5cf8c |
copy_topology->topo.graph.nedges = old_topology->topo.graph.nedges;
|
|
Packit Service |
c5cf8c |
MPIR_ARRAY_COPY_HELPER(graph, index, nnodes);
|
|
Packit Service |
c5cf8c |
MPIR_ARRAY_COPY_HELPER(graph, edges, nedges);
|
|
Packit Service |
c5cf8c |
} else if (old_topology->kind == MPI_DIST_GRAPH) {
|
|
Packit Service |
c5cf8c |
copy_topology->topo.dist_graph.indegree = old_topology->topo.dist_graph.indegree;
|
|
Packit Service |
c5cf8c |
copy_topology->topo.dist_graph.outdegree = old_topology->topo.dist_graph.outdegree;
|
|
Packit Service |
c5cf8c |
MPIR_ARRAY_COPY_HELPER(dist_graph, in, indegree);
|
|
Packit Service |
c5cf8c |
MPIR_ARRAY_COPY_HELPER(dist_graph, in_weights, indegree);
|
|
Packit Service |
c5cf8c |
MPIR_ARRAY_COPY_HELPER(dist_graph, out, outdegree);
|
|
Packit Service |
c5cf8c |
MPIR_ARRAY_COPY_HELPER(dist_graph, out_weights, outdegree);
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
/* --BEGIN ERROR HANDLING-- */
|
|
Packit Service |
c5cf8c |
else {
|
|
Packit Service |
c5cf8c |
/* Unknown topology */
|
|
Packit Service |
c5cf8c |
return MPI_ERR_TOPOLOGY;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
/* --END ERROR HANDLING-- */
|
|
Packit Service |
c5cf8c |
#undef MPIR_ARRAY_COPY_HELPER
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
*(void **) attr_out = (void *) copy_topology;
|
|
Packit Service |
c5cf8c |
*flag = 1;
|
|
Packit Service |
c5cf8c |
MPIR_CHKPMEM_COMMIT();
|
|
Packit Service |
c5cf8c |
fn_exit:
|
|
Packit Service |
c5cf8c |
/* Return mpi_errno in case one of the copy array functions failed */
|
|
Packit Service |
c5cf8c |
return mpi_errno;
|
|
Packit Service |
c5cf8c |
fn_fail:
|
|
Packit Service |
c5cf8c |
/* --BEGIN ERROR HANDLING-- */
|
|
Packit Service |
c5cf8c |
MPIR_CHKPMEM_REAP();
|
|
Packit Service |
c5cf8c |
goto fn_exit;
|
|
Packit Service |
c5cf8c |
/* --END ERROR HANDLING-- */
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
#undef FUNCNAME
|
|
Packit Service |
c5cf8c |
#define FUNCNAME MPIR_Topology_delete_fn
|
|
Packit Service |
c5cf8c |
#undef FCNAME
|
|
Packit Service |
c5cf8c |
#define FCNAME MPL_QUOTE(FUNCNAME)
|
|
Packit Service |
c5cf8c |
static int MPIR_Topology_delete_fn(MPI_Comm comm ATTRIBUTE((unused)),
|
|
Packit Service |
c5cf8c |
int keyval ATTRIBUTE((unused)),
|
|
Packit Service |
c5cf8c |
void *attr_val, void *extra_data ATTRIBUTE((unused)))
|
|
Packit Service |
c5cf8c |
{
|
|
Packit Service |
c5cf8c |
MPIR_Topology *topology = (MPIR_Topology *) attr_val;
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
MPL_UNREFERENCED_ARG(comm);
|
|
Packit Service |
c5cf8c |
MPL_UNREFERENCED_ARG(keyval);
|
|
Packit Service |
c5cf8c |
MPL_UNREFERENCED_ARG(extra_data);
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
/* FIXME - free the attribute data structure */
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
if (topology->kind == MPI_CART) {
|
|
Packit Service |
c5cf8c |
MPL_free(topology->topo.cart.dims);
|
|
Packit Service |
c5cf8c |
MPL_free(topology->topo.cart.periodic);
|
|
Packit Service |
c5cf8c |
MPL_free(topology->topo.cart.position);
|
|
Packit Service |
c5cf8c |
MPL_free(topology);
|
|
Packit Service |
c5cf8c |
} else if (topology->kind == MPI_GRAPH) {
|
|
Packit Service |
c5cf8c |
MPL_free(topology->topo.graph.index);
|
|
Packit Service |
c5cf8c |
MPL_free(topology->topo.graph.edges);
|
|
Packit Service |
c5cf8c |
MPL_free(topology);
|
|
Packit Service |
c5cf8c |
} else if (topology->kind == MPI_DIST_GRAPH) {
|
|
Packit Service |
c5cf8c |
MPL_free(topology->topo.dist_graph.in);
|
|
Packit Service |
c5cf8c |
MPL_free(topology->topo.dist_graph.out);
|
|
Packit Service |
c5cf8c |
if (topology->topo.dist_graph.in_weights)
|
|
Packit Service |
c5cf8c |
MPL_free(topology->topo.dist_graph.in_weights);
|
|
Packit Service |
c5cf8c |
if (topology->topo.dist_graph.out_weights)
|
|
Packit Service |
c5cf8c |
MPL_free(topology->topo.dist_graph.out_weights);
|
|
Packit Service |
c5cf8c |
MPL_free(topology);
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
/* --BEGIN ERROR HANDLING-- */
|
|
Packit Service |
c5cf8c |
else {
|
|
Packit Service |
c5cf8c |
return MPI_ERR_TOPOLOGY;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
/* --END ERROR HANDLING-- */
|
|
Packit Service |
c5cf8c |
return MPI_SUCCESS;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
/* the next two routines implement the following behavior (quoted from Section
|
|
Packit Service |
c5cf8c |
* 7.6 of the MPI-3.0 standard):
|
|
Packit Service |
c5cf8c |
*
|
|
Packit Service |
c5cf8c |
* For a distributed graph topology, created with MPI_DIST_GRAPH_CREATE, the
|
|
Packit Service |
c5cf8c |
* sequence of neighbors in the send and receive buffers at each process
|
|
Packit Service |
c5cf8c |
* is defined as the sequence returned by MPI_DIST_GRAPH_NEIGHBORS for
|
|
Packit Service |
c5cf8c |
* destinations and sources, respectively. For a general graph topology,
|
|
Packit Service |
c5cf8c |
* created with MPI_GRAPH_CREATE, the order of neighbors in the send and
|
|
Packit Service |
c5cf8c |
* receive buffers is defined as the sequence of neighbors as returned by
|
|
Packit Service |
c5cf8c |
* MPI_GRAPH_NEIGHBORS. Note that general graph topologies should generally
|
|
Packit Service |
c5cf8c |
* be replaced by the distributed graph topologies.
|
|
Packit Service |
c5cf8c |
*
|
|
Packit Service |
c5cf8c |
* For a Cartesian topology, created with MPI_CART_CREATE, the sequence of
|
|
Packit Service |
c5cf8c |
* neighbors in the send and receive buffers at each process is defined by
|
|
Packit Service |
c5cf8c |
* order of the dimensions, first the neighbor in the negative direction and
|
|
Packit Service |
c5cf8c |
* then in the positive direction with displacement 1. The numbers of
|
|
Packit Service |
c5cf8c |
* sources and destinations in the communication routines are 2*ndims with
|
|
Packit Service |
c5cf8c |
* ndims defined in MPI_CART_CREATE. If a neighbor does not exist, i.e., at
|
|
Packit Service |
c5cf8c |
* the border of a Cartesian topology in the case of a non-periodic virtual
|
|
Packit Service |
c5cf8c |
* grid dimension (i.e., periods[...]==false), then this neighbor is defined
|
|
Packit Service |
c5cf8c |
* to be MPI_PROC_NULL.
|
|
Packit Service |
c5cf8c |
*/
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
#undef FUNCNAME
|
|
Packit Service |
c5cf8c |
#define FUNCNAME MPIR_Topo_canon_nhb_count
|
|
Packit Service |
c5cf8c |
#undef FCNAME
|
|
Packit Service |
c5cf8c |
#define FCNAME MPL_QUOTE(FUNCNAME)
|
|
Packit Service |
c5cf8c |
int MPIR_Topo_canon_nhb_count(MPIR_Comm * comm_ptr, int *indegree, int *outdegree, int *weighted)
|
|
Packit Service |
c5cf8c |
{
|
|
Packit Service |
c5cf8c |
int mpi_errno = MPI_SUCCESS;
|
|
Packit Service |
c5cf8c |
MPIR_Topology *topo_ptr;
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
topo_ptr = MPIR_Topology_get(comm_ptr);
|
|
Packit Service |
c5cf8c |
MPIR_ERR_CHKANDJUMP(!topo_ptr, mpi_errno, MPI_ERR_TOPOLOGY, "**notopology");
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
/* TODO consider dispatching via a vtable instead of doing if/else */
|
|
Packit Service |
c5cf8c |
if (topo_ptr->kind == MPI_DIST_GRAPH) {
|
|
Packit Service |
c5cf8c |
mpi_errno = MPIR_Dist_graph_neighbors_count_impl(comm_ptr, indegree, outdegree, weighted);
|
|
Packit Service |
c5cf8c |
if (mpi_errno)
|
|
Packit Service |
c5cf8c |
MPIR_ERR_POP(mpi_errno);
|
|
Packit Service |
c5cf8c |
} else if (topo_ptr->kind == MPI_GRAPH) {
|
|
Packit Service |
c5cf8c |
int nneighbors = 0;
|
|
Packit Service |
c5cf8c |
mpi_errno = MPIR_Graph_neighbors_count_impl(comm_ptr, comm_ptr->rank, &nneighbors);
|
|
Packit Service |
c5cf8c |
if (mpi_errno)
|
|
Packit Service |
c5cf8c |
MPIR_ERR_POP(mpi_errno);
|
|
Packit Service |
c5cf8c |
*indegree = *outdegree = nneighbors;
|
|
Packit Service |
c5cf8c |
*weighted = FALSE;
|
|
Packit Service |
c5cf8c |
} else if (topo_ptr->kind == MPI_CART) {
|
|
Packit Service |
c5cf8c |
*indegree = 2 * topo_ptr->topo.cart.ndims;
|
|
Packit Service |
c5cf8c |
*outdegree = 2 * topo_ptr->topo.cart.ndims;
|
|
Packit Service |
c5cf8c |
*weighted = FALSE;
|
|
Packit Service |
c5cf8c |
} else {
|
|
Packit Service |
c5cf8c |
MPIR_Assert(FALSE);
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
fn_exit:
|
|
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 MPIR_Topo_canon_nhb
|
|
Packit Service |
c5cf8c |
#undef FCNAME
|
|
Packit Service |
c5cf8c |
#define FCNAME MPL_QUOTE(FUNCNAME)
|
|
Packit Service |
c5cf8c |
int MPIR_Topo_canon_nhb(MPIR_Comm * comm_ptr,
|
|
Packit Service |
c5cf8c |
int indegree, int sources[], int inweights[],
|
|
Packit Service |
c5cf8c |
int outdegree, int dests[], int outweights[])
|
|
Packit Service |
c5cf8c |
{
|
|
Packit Service |
c5cf8c |
int mpi_errno = MPI_SUCCESS;
|
|
Packit Service |
c5cf8c |
MPIR_Topology *topo_ptr;
|
|
Packit Service |
c5cf8c |
MPIR_FUNC_TERSE_STATE_DECL(MPID_STATE_MPIR_TOPO_CANON_NHB);
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
MPIR_FUNC_TERSE_ENTER(MPID_STATE_MPIR_TOPO_CANON_NHB);
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
topo_ptr = MPIR_Topology_get(comm_ptr);
|
|
Packit Service |
c5cf8c |
MPIR_ERR_CHKANDJUMP(!topo_ptr, mpi_errno, MPI_ERR_TOPOLOGY, "**notopology");
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
/* TODO consider dispatching via a vtable instead of doing if/else */
|
|
Packit Service |
c5cf8c |
if (topo_ptr->kind == MPI_DIST_GRAPH) {
|
|
Packit Service |
c5cf8c |
mpi_errno = MPIR_Dist_graph_neighbors_impl(comm_ptr,
|
|
Packit Service |
c5cf8c |
indegree, sources, inweights,
|
|
Packit Service |
c5cf8c |
outdegree, dests, outweights);
|
|
Packit Service |
c5cf8c |
if (mpi_errno)
|
|
Packit Service |
c5cf8c |
MPIR_ERR_POP(mpi_errno);
|
|
Packit Service |
c5cf8c |
} else if (topo_ptr->kind == MPI_GRAPH) {
|
|
Packit Service |
c5cf8c |
MPIR_Assert(indegree == outdegree);
|
|
Packit Service |
c5cf8c |
mpi_errno = MPIR_Graph_neighbors_impl(comm_ptr, comm_ptr->rank, indegree, sources);
|
|
Packit Service |
c5cf8c |
if (mpi_errno)
|
|
Packit Service |
c5cf8c |
MPIR_ERR_POP(mpi_errno);
|
|
Packit Service |
c5cf8c |
MPIR_Memcpy(dests, sources, outdegree * sizeof(*dests));
|
|
Packit Service |
c5cf8c |
/* ignore inweights/outweights */
|
|
Packit Service |
c5cf8c |
} else if (topo_ptr->kind == MPI_CART) {
|
|
Packit Service |
c5cf8c |
int d;
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
MPIR_Assert(indegree == outdegree);
|
|
Packit Service |
c5cf8c |
MPIR_Assert(indegree == 2 * topo_ptr->topo.cart.ndims);
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
for (d = 0; d < topo_ptr->topo.cart.ndims; ++d) {
|
|
Packit Service |
c5cf8c |
mpi_errno = MPIR_Cart_shift_impl(comm_ptr, d, 1, &sources[2 * d], &sources[2 * d + 1]);
|
|
Packit Service |
c5cf8c |
if (mpi_errno)
|
|
Packit Service |
c5cf8c |
MPIR_ERR_POP(mpi_errno);
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
dests[2 * d] = sources[2 * d];
|
|
Packit Service |
c5cf8c |
dests[2 * d + 1] = sources[2 * d + 1];
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
/* ignore inweights/outweights */
|
|
Packit Service |
c5cf8c |
} else {
|
|
Packit Service |
c5cf8c |
MPIR_Assert(FALSE);
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
#ifdef MPL_USE_DBG_LOGGING
|
|
Packit Service |
c5cf8c |
{
|
|
Packit Service |
c5cf8c |
int i;
|
|
Packit Service |
c5cf8c |
MPL_DBG_MSG_FMT(MPIR_DBG_PT2PT, VERBOSE,
|
|
Packit Service |
c5cf8c |
(MPL_DBG_FDEST, "canonical neighbors for comm=0x%x comm_ptr=%p",
|
|
Packit Service |
c5cf8c |
comm_ptr->handle, comm_ptr));
|
|
Packit Service |
c5cf8c |
for (i = 0; i < outdegree; ++i) {
|
|
Packit Service |
c5cf8c |
MPL_DBG_MSG_FMT(MPIR_DBG_PT2PT, VERBOSE,
|
|
Packit Service |
c5cf8c |
(MPL_DBG_FDEST, "%d/%d: to %d", i, outdegree, dests[i]));
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
for (i = 0; i < indegree; ++i) {
|
|
Packit Service |
c5cf8c |
MPL_DBG_MSG_FMT(MPIR_DBG_PT2PT, VERBOSE,
|
|
Packit Service |
c5cf8c |
(MPL_DBG_FDEST, "%d/%d: from %d", i, indegree, sources[i]));
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
#endif
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
fn_exit:
|
|
Packit Service |
c5cf8c |
MPIR_FUNC_TERSE_EXIT(MPID_STATE_MPIR_TOPO_CANON_NHB);
|
|
Packit Service |
c5cf8c |
return mpi_errno;
|
|
Packit Service |
c5cf8c |
fn_fail:
|
|
Packit Service |
c5cf8c |
goto fn_exit;
|
|
Packit Service |
c5cf8c |
}
|