|
Packit Service |
c5cf8c |
/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */
|
|
Packit Service |
c5cf8c |
/*
|
|
Packit Service |
c5cf8c |
*
|
|
Packit Service |
c5cf8c |
* (C) 2009 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 |
|
|
Packit Service |
c5cf8c |
/* -- Begin Profiling Symbol Block for routine MPI_Dist_graph_create */
|
|
Packit Service |
c5cf8c |
#if defined(HAVE_PRAGMA_WEAK)
|
|
Packit Service |
c5cf8c |
#pragma weak MPI_Dist_graph_create = PMPI_Dist_graph_create
|
|
Packit Service |
c5cf8c |
#elif defined(HAVE_PRAGMA_HP_SEC_DEF)
|
|
Packit Service |
c5cf8c |
#pragma _HP_SECONDARY_DEF PMPI_Dist_graph_create MPI_Dist_graph_create
|
|
Packit Service |
c5cf8c |
#elif defined(HAVE_PRAGMA_CRI_DUP)
|
|
Packit Service |
c5cf8c |
#pragma _CRI duplicate MPI_Dist_graph_create as PMPI_Dist_graph_create
|
|
Packit Service |
c5cf8c |
#elif defined(HAVE_WEAK_ATTRIBUTE)
|
|
Packit Service |
c5cf8c |
int MPI_Dist_graph_create(MPI_Comm comm_old, int n, const int sources[], const int degrees[],
|
|
Packit Service |
c5cf8c |
const int destinations[], const int weights[], MPI_Info info,
|
|
Packit Service |
c5cf8c |
int reorder, MPI_Comm * comm_dist_graph)
|
|
Packit Service |
c5cf8c |
__attribute__ ((weak, alias("PMPI_Dist_graph_create")));
|
|
Packit Service |
c5cf8c |
#endif
|
|
Packit Service |
c5cf8c |
/* -- End Profiling Symbol Block */
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
/* Define MPICH_MPI_FROM_PMPI if weak symbols are not supported to build
|
|
Packit Service |
c5cf8c |
the MPI routines */
|
|
Packit Service |
c5cf8c |
#ifndef MPICH_MPI_FROM_PMPI
|
|
Packit Service |
c5cf8c |
#undef MPI_Dist_graph_create
|
|
Packit Service |
c5cf8c |
#define MPI_Dist_graph_create PMPI_Dist_graph_create
|
|
Packit Service |
c5cf8c |
/* any utility functions should go here, usually prefixed with PMPI_LOCAL to
|
|
Packit Service |
c5cf8c |
* correctly handle weak symbols and the profiling interface */
|
|
Packit Service |
c5cf8c |
#endif
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
#undef FUNCNAME
|
|
Packit Service |
c5cf8c |
#define FUNCNAME MPI_Dist_graph_create
|
|
Packit Service |
c5cf8c |
#undef FCNAME
|
|
Packit Service |
c5cf8c |
#define FCNAME MPL_QUOTE(FUNCNAME)
|
|
Packit Service |
c5cf8c |
/*@
|
|
Packit Service |
c5cf8c |
MPI_Dist_graph_create - MPI_DIST_GRAPH_CREATE returns a handle to a new
|
|
Packit Service |
c5cf8c |
communicator to which the distributed graph topology information is
|
|
Packit Service |
c5cf8c |
attached.
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
Input Parameters:
|
|
Packit Service |
c5cf8c |
+ comm_old - input communicator (handle)
|
|
Packit Service |
c5cf8c |
. n - number of source nodes for which this process specifies edges
|
|
Packit Service |
c5cf8c |
(non-negative integer)
|
|
Packit Service |
c5cf8c |
. sources - array containing the n source nodes for which this process
|
|
Packit Service |
c5cf8c |
specifies edges (array of non-negative integers)
|
|
Packit Service |
c5cf8c |
. degrees - array specifying the number of destinations for each source node
|
|
Packit Service |
c5cf8c |
in the source node array (array of non-negative integers)
|
|
Packit Service |
c5cf8c |
. destinations - destination nodes for the source nodes in the source node
|
|
Packit Service |
c5cf8c |
array (array of non-negative integers)
|
|
Packit Service |
c5cf8c |
. weights - weights for source to destination edges (array of non-negative
|
|
Packit Service |
c5cf8c |
integers or MPI_UNWEIGHTED)
|
|
Packit Service |
c5cf8c |
. info - hints on optimization and interpretation of weights (handle)
|
|
Packit Service |
c5cf8c |
- reorder - the process may be reordered (true) or not (false) (logical)
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
Output Parameters:
|
|
Packit Service |
c5cf8c |
. comm_dist_graph - communicator with distributed graph topology added (handle)
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
.N ThreadSafe
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
.N Fortran
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
.N Errors
|
|
Packit Service |
c5cf8c |
.N MPI_SUCCESS
|
|
Packit Service |
c5cf8c |
.N MPI_ERR_ARG
|
|
Packit Service |
c5cf8c |
.N MPI_ERR_OTHER
|
|
Packit Service |
c5cf8c |
@*/
|
|
Packit Service |
c5cf8c |
int MPI_Dist_graph_create(MPI_Comm comm_old, int n, const int sources[],
|
|
Packit Service |
c5cf8c |
const int degrees[], const int destinations[],
|
|
Packit Service |
c5cf8c |
const int weights[],
|
|
Packit Service |
c5cf8c |
MPI_Info info, int reorder, MPI_Comm * comm_dist_graph)
|
|
Packit Service |
c5cf8c |
{
|
|
Packit Service |
c5cf8c |
int mpi_errno = MPI_SUCCESS;
|
|
Packit Service |
c5cf8c |
MPIR_Comm *comm_ptr = NULL;
|
|
Packit Service |
c5cf8c |
MPIR_Comm *comm_dist_graph_ptr = NULL;
|
|
Packit Service |
c5cf8c |
MPIR_Request **reqs = NULL;
|
|
Packit Service |
c5cf8c |
MPIR_Topology *topo_ptr = NULL;
|
|
Packit Service |
c5cf8c |
MPII_Dist_graph_topology *dist_graph_ptr = NULL;
|
|
Packit Service |
c5cf8c |
int i;
|
|
Packit Service |
c5cf8c |
int j;
|
|
Packit Service |
c5cf8c |
int idx;
|
|
Packit Service |
c5cf8c |
int comm_size = 0;
|
|
Packit Service |
c5cf8c |
int in_capacity;
|
|
Packit Service |
c5cf8c |
int out_capacity;
|
|
Packit Service |
c5cf8c |
int **rout = NULL;
|
|
Packit Service |
c5cf8c |
int **rin = NULL;
|
|
Packit Service |
c5cf8c |
int *rin_sizes;
|
|
Packit Service |
c5cf8c |
int *rout_sizes;
|
|
Packit Service |
c5cf8c |
int *rin_idx;
|
|
Packit Service |
c5cf8c |
int *rout_idx;
|
|
Packit Service |
c5cf8c |
int *rs;
|
|
Packit Service |
c5cf8c |
int in_out_peers[2] = { -1, -1 };
|
|
Packit Service |
c5cf8c |
MPIR_Errflag_t errflag = MPIR_ERR_NONE;
|
|
Packit Service |
c5cf8c |
MPIR_CHKLMEM_DECL(9);
|
|
Packit Service |
c5cf8c |
MPIR_CHKPMEM_DECL(1);
|
|
Packit Service |
c5cf8c |
MPIR_FUNC_TERSE_STATE_DECL(MPID_STATE_MPI_DIST_GRAPH_CREATE);
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
MPIR_ERRTEST_INITIALIZED_ORDIE();
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
MPID_THREAD_CS_ENTER(GLOBAL, MPIR_THREAD_GLOBAL_ALLFUNC_MUTEX);
|
|
Packit Service |
c5cf8c |
MPIR_FUNC_TERSE_ENTER(MPID_STATE_MPI_DIST_GRAPH_CREATE);
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
/* Validate parameters, especially handles needing to be converted */
|
|
Packit Service |
c5cf8c |
#ifdef HAVE_ERROR_CHECKING
|
|
Packit Service |
c5cf8c |
{
|
|
Packit Service |
c5cf8c |
MPID_BEGIN_ERROR_CHECKS;
|
|
Packit Service |
c5cf8c |
{
|
|
Packit Service |
c5cf8c |
MPIR_ERRTEST_COMM(comm_old, mpi_errno);
|
|
Packit Service |
c5cf8c |
MPIR_ERRTEST_INFO_OR_NULL(info, mpi_errno);
|
|
Packit Service |
c5cf8c |
if (mpi_errno != MPI_SUCCESS)
|
|
Packit Service |
c5cf8c |
goto fn_fail;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
MPID_END_ERROR_CHECKS;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
#endif
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
/* Convert MPI object handles to object pointers */
|
|
Packit Service |
c5cf8c |
MPIR_Comm_get_ptr(comm_old, comm_ptr);
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
/* Validate parameters and objects (post conversion) */
|
|
Packit Service |
c5cf8c |
#ifdef HAVE_ERROR_CHECKING
|
|
Packit Service |
c5cf8c |
{
|
|
Packit Service |
c5cf8c |
MPID_BEGIN_ERROR_CHECKS;
|
|
Packit Service |
c5cf8c |
{
|
|
Packit Service |
c5cf8c |
/* Validate comm_ptr */
|
|
Packit Service |
c5cf8c |
MPIR_Comm_valid_ptr(comm_ptr, mpi_errno, FALSE);
|
|
Packit Service |
c5cf8c |
/* If comm_ptr is not valid, it will be reset to null */
|
|
Packit Service |
c5cf8c |
if (comm_ptr) {
|
|
Packit Service |
c5cf8c |
MPIR_ERRTEST_COMM_INTRA(comm_ptr, mpi_errno);
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
MPIR_ERRTEST_ARGNEG(n, "n", mpi_errno);
|
|
Packit Service |
c5cf8c |
if (n > 0) {
|
|
Packit Service |
c5cf8c |
int have_degrees = 0;
|
|
Packit Service |
c5cf8c |
MPIR_ERRTEST_ARGNULL(sources, "sources", mpi_errno);
|
|
Packit Service |
c5cf8c |
MPIR_ERRTEST_ARGNULL(degrees, "degrees", mpi_errno);
|
|
Packit Service |
c5cf8c |
for (i = 0; i < n; ++i) {
|
|
Packit Service |
c5cf8c |
if (degrees[i]) {
|
|
Packit Service |
c5cf8c |
have_degrees = 1;
|
|
Packit Service |
c5cf8c |
break;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
if (have_degrees) {
|
|
Packit Service |
c5cf8c |
MPIR_ERRTEST_ARGNULL(destinations, "destinations", mpi_errno);
|
|
Packit Service |
c5cf8c |
if (weights != MPI_UNWEIGHTED)
|
|
Packit Service |
c5cf8c |
MPIR_ERRTEST_ARGNULL(weights, "weights", mpi_errno);
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
if (mpi_errno != MPI_SUCCESS)
|
|
Packit Service |
c5cf8c |
goto fn_fail;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
MPID_END_ERROR_CHECKS;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
#endif /* HAVE_ERROR_CHECKING */
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
/* ... body of routine ... */
|
|
Packit Service |
c5cf8c |
/* Implementation based on Torsten Hoefler's reference implementation
|
|
Packit Service |
c5cf8c |
* attached to MPI-2.2 ticket #33. */
|
|
Packit Service |
c5cf8c |
*comm_dist_graph = MPI_COMM_NULL;
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
comm_size = comm_ptr->local_size;
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
/* following the spirit of the old topo interface, attributes do not
|
|
Packit Service |
c5cf8c |
* propagate to the new communicator (see MPI-2.1 pp. 243 line 11) */
|
|
Packit Service |
c5cf8c |
mpi_errno = MPII_Comm_copy(comm_ptr, comm_size, &comm_dist_graph_ptr);
|
|
Packit Service |
c5cf8c |
if (mpi_errno)
|
|
Packit Service |
c5cf8c |
MPIR_ERR_POP(mpi_errno);
|
|
Packit Service |
c5cf8c |
MPIR_Assert(comm_dist_graph_ptr != NULL);
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
/* rin is an array of size comm_size containing pointers to arrays of
|
|
Packit Service |
c5cf8c |
* rin_sizes[x]. rin[x] is locally known number of edges into this process
|
|
Packit Service |
c5cf8c |
* from rank x.
|
|
Packit Service |
c5cf8c |
*
|
|
Packit Service |
c5cf8c |
* rout is an array of comm_size containing pointers to arrays of
|
|
Packit Service |
c5cf8c |
* rout_sizes[x]. rout[x] is the locally known number of edges out of this
|
|
Packit Service |
c5cf8c |
* process to rank x. */
|
|
Packit Service |
c5cf8c |
MPIR_CHKLMEM_MALLOC(rout, int **, comm_size * sizeof(int *), mpi_errno, "rout", MPL_MEM_COMM);
|
|
Packit Service |
c5cf8c |
MPIR_CHKLMEM_MALLOC(rin, int **, comm_size * sizeof(int *), mpi_errno, "rin", MPL_MEM_COMM);
|
|
Packit Service |
c5cf8c |
MPIR_CHKLMEM_MALLOC(rin_sizes, int *, comm_size * sizeof(int), mpi_errno, "rin_sizes",
|
|
Packit Service |
c5cf8c |
MPL_MEM_COMM);
|
|
Packit Service |
c5cf8c |
MPIR_CHKLMEM_MALLOC(rout_sizes, int *, comm_size * sizeof(int), mpi_errno, "rout_sizes",
|
|
Packit Service |
c5cf8c |
MPL_MEM_COMM);
|
|
Packit Service |
c5cf8c |
MPIR_CHKLMEM_MALLOC(rin_idx, int *, comm_size * sizeof(int), mpi_errno, "rin_idx",
|
|
Packit Service |
c5cf8c |
MPL_MEM_COMM);
|
|
Packit Service |
c5cf8c |
MPIR_CHKLMEM_MALLOC(rout_idx, int *, comm_size * sizeof(int), mpi_errno, "rout_idx",
|
|
Packit Service |
c5cf8c |
MPL_MEM_COMM);
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
memset(rout, 0, comm_size * sizeof(int *));
|
|
Packit Service |
c5cf8c |
memset(rin, 0, comm_size * sizeof(int *));
|
|
Packit Service |
c5cf8c |
memset(rin_sizes, 0, comm_size * sizeof(int));
|
|
Packit Service |
c5cf8c |
memset(rout_sizes, 0, comm_size * sizeof(int));
|
|
Packit Service |
c5cf8c |
memset(rin_idx, 0, comm_size * sizeof(int));
|
|
Packit Service |
c5cf8c |
memset(rout_idx, 0, comm_size * sizeof(int));
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
/* compute array sizes */
|
|
Packit Service |
c5cf8c |
idx = 0;
|
|
Packit Service |
c5cf8c |
for (i = 0; i < n; ++i) {
|
|
Packit Service |
c5cf8c |
MPIR_Assert(sources[i] < comm_size);
|
|
Packit Service |
c5cf8c |
for (j = 0; j < degrees[i]; ++j) {
|
|
Packit Service |
c5cf8c |
MPIR_Assert(destinations[idx] < comm_size);
|
|
Packit Service |
c5cf8c |
/* rout_sizes[i] is twice as long as the number of edges to be
|
|
Packit Service |
c5cf8c |
* sent to rank i by this process */
|
|
Packit Service |
c5cf8c |
rout_sizes[sources[i]] += 2;
|
|
Packit Service |
c5cf8c |
rin_sizes[destinations[idx]] += 2;
|
|
Packit Service |
c5cf8c |
++idx;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
/* allocate arrays */
|
|
Packit Service |
c5cf8c |
for (i = 0; i < comm_size; ++i) {
|
|
Packit Service |
c5cf8c |
/* can't use CHKLMEM macros b/c we are in a loop */
|
|
Packit Service |
c5cf8c |
if (rin_sizes[i]) {
|
|
Packit Service |
c5cf8c |
rin[i] = MPL_malloc(rin_sizes[i] * sizeof(int), MPL_MEM_COMM);
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
if (rout_sizes[i]) {
|
|
Packit Service |
c5cf8c |
rout[i] = MPL_malloc(rout_sizes[i] * sizeof(int), MPL_MEM_COMM);
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
/* populate arrays */
|
|
Packit Service |
c5cf8c |
idx = 0;
|
|
Packit Service |
c5cf8c |
for (i = 0; i < n; ++i) {
|
|
Packit Service |
c5cf8c |
/* TODO add this assert as proper error checking above */
|
|
Packit Service |
c5cf8c |
int s_rank = sources[i];
|
|
Packit Service |
c5cf8c |
MPIR_Assert(s_rank < comm_size);
|
|
Packit Service |
c5cf8c |
MPIR_Assert(s_rank >= 0);
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
for (j = 0; j < degrees[i]; ++j) {
|
|
Packit Service |
c5cf8c |
int d_rank = destinations[idx];
|
|
Packit Service |
c5cf8c |
int weight = (weights == MPI_UNWEIGHTED ? 0 : weights[idx]);
|
|
Packit Service |
c5cf8c |
/* TODO add this assert as proper error checking above */
|
|
Packit Service |
c5cf8c |
MPIR_Assert(d_rank < comm_size);
|
|
Packit Service |
c5cf8c |
MPIR_Assert(d_rank >= 0);
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
/* XXX DJG what about self-edges? do we need to drop one of these
|
|
Packit Service |
c5cf8c |
* cases when there is a self-edge to avoid double-counting? */
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
/* rout[s][2*x] is the value of d for the j'th edge between (s,d)
|
|
Packit Service |
c5cf8c |
* with weight rout[s][2*x+1], where x is the current end of the
|
|
Packit Service |
c5cf8c |
* outgoing edge list for s. x==(rout_idx[s]/2) */
|
|
Packit Service |
c5cf8c |
rout[s_rank][rout_idx[s_rank]++] = d_rank;
|
|
Packit Service |
c5cf8c |
rout[s_rank][rout_idx[s_rank]++] = weight;
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
/* rin[d][2*x] is the value of s for the j'th edge between (s,d)
|
|
Packit Service |
c5cf8c |
* with weight rout[d][2*x+1], where x is the current end of the
|
|
Packit Service |
c5cf8c |
* incoming edge list for d. x==(rin_idx[d]/2) */
|
|
Packit Service |
c5cf8c |
rin[d_rank][rin_idx[d_rank]++] = s_rank;
|
|
Packit Service |
c5cf8c |
rin[d_rank][rin_idx[d_rank]++] = weight;
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
++idx;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
for (i = 0; i < comm_size; ++i) {
|
|
Packit Service |
c5cf8c |
/* sanity check that all arrays are fully populated */
|
|
Packit Service |
c5cf8c |
MPIR_Assert(rin_idx[i] == rin_sizes[i]);
|
|
Packit Service |
c5cf8c |
MPIR_Assert(rout_idx[i] == rout_sizes[i]);
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
MPIR_CHKLMEM_MALLOC(rs, int *, 2 * comm_size * sizeof(int), mpi_errno, "red-scat source buffer",
|
|
Packit Service |
c5cf8c |
MPL_MEM_COMM);
|
|
Packit Service |
c5cf8c |
for (i = 0; i < comm_size; ++i) {
|
|
Packit Service |
c5cf8c |
rs[2 * i] = (rin_sizes[i] ? 1 : 0);
|
|
Packit Service |
c5cf8c |
rs[2 * i + 1] = (rout_sizes[i] ? 1 : 0);
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
/* compute the number of peers I will recv from */
|
|
Packit Service |
c5cf8c |
mpi_errno =
|
|
Packit Service |
c5cf8c |
MPIR_Reduce_scatter_block(rs, in_out_peers, 2, MPI_INT, MPI_SUM, comm_ptr, &errflag);
|
|
Packit Service |
c5cf8c |
if (mpi_errno)
|
|
Packit Service |
c5cf8c |
MPIR_ERR_POP(mpi_errno);
|
|
Packit Service |
c5cf8c |
MPIR_ERR_CHKANDJUMP(errflag, mpi_errno, MPI_ERR_OTHER, "**coll_fail");
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
MPIR_Assert(in_out_peers[0] <= comm_size && in_out_peers[0] >= 0);
|
|
Packit Service |
c5cf8c |
MPIR_Assert(in_out_peers[1] <= comm_size && in_out_peers[1] >= 0);
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
idx = 0;
|
|
Packit Service |
c5cf8c |
/* must be 2*comm_size requests because we will possibly send inbound and
|
|
Packit Service |
c5cf8c |
* outbound edges to everyone in our communicator */
|
|
Packit Service |
c5cf8c |
MPIR_CHKLMEM_MALLOC(reqs, MPIR_Request **, 2 * comm_size * sizeof(MPIR_Request *), mpi_errno,
|
|
Packit Service |
c5cf8c |
"temp request array", MPL_MEM_COMM);
|
|
Packit Service |
c5cf8c |
for (i = 0; i < comm_size; ++i) {
|
|
Packit Service |
c5cf8c |
if (rin_sizes[i]) {
|
|
Packit Service |
c5cf8c |
/* send edges where i is a destination to process i */
|
|
Packit Service |
c5cf8c |
mpi_errno =
|
|
Packit Service |
c5cf8c |
MPIC_Isend(&rin[i][0], rin_sizes[i], MPI_INT, i, MPIR_TOPO_A_TAG, comm_ptr,
|
|
Packit Service |
c5cf8c |
&reqs[idx++], &errflag);
|
|
Packit Service |
c5cf8c |
if (mpi_errno)
|
|
Packit Service |
c5cf8c |
MPIR_ERR_POP(mpi_errno);
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
if (rout_sizes[i]) {
|
|
Packit Service |
c5cf8c |
/* send edges where i is a source to process i */
|
|
Packit Service |
c5cf8c |
mpi_errno =
|
|
Packit Service |
c5cf8c |
MPIC_Isend(&rout[i][0], rout_sizes[i], MPI_INT, i, MPIR_TOPO_B_TAG, comm_ptr,
|
|
Packit Service |
c5cf8c |
&reqs[idx++], &errflag);
|
|
Packit Service |
c5cf8c |
if (mpi_errno)
|
|
Packit Service |
c5cf8c |
MPIR_ERR_POP(mpi_errno);
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
MPIR_Assert(idx <= (2 * comm_size));
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
/* Create the topology structure */
|
|
Packit Service |
c5cf8c |
MPIR_CHKPMEM_MALLOC(topo_ptr, MPIR_Topology *, sizeof(MPIR_Topology), mpi_errno, "topo_ptr",
|
|
Packit Service |
c5cf8c |
MPL_MEM_COMM);
|
|
Packit Service |
c5cf8c |
topo_ptr->kind = MPI_DIST_GRAPH;
|
|
Packit Service |
c5cf8c |
dist_graph_ptr = &topo_ptr->topo.dist_graph;
|
|
Packit Service |
c5cf8c |
dist_graph_ptr->indegree = 0;
|
|
Packit Service |
c5cf8c |
dist_graph_ptr->in = NULL;
|
|
Packit Service |
c5cf8c |
dist_graph_ptr->in_weights = NULL;
|
|
Packit Service |
c5cf8c |
dist_graph_ptr->outdegree = 0;
|
|
Packit Service |
c5cf8c |
dist_graph_ptr->out = NULL;
|
|
Packit Service |
c5cf8c |
dist_graph_ptr->out_weights = NULL;
|
|
Packit Service |
c5cf8c |
dist_graph_ptr->is_weighted = (weights != MPI_UNWEIGHTED);
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
/* can't use CHKPMEM macros for this b/c we need to realloc */
|
|
Packit Service |
c5cf8c |
in_capacity = 10; /* arbitrary */
|
|
Packit Service |
c5cf8c |
dist_graph_ptr->in = MPL_malloc(in_capacity * sizeof(int), MPL_MEM_COMM);
|
|
Packit Service |
c5cf8c |
if (dist_graph_ptr->is_weighted) {
|
|
Packit Service |
c5cf8c |
dist_graph_ptr->in_weights = MPL_malloc(in_capacity * sizeof(int), MPL_MEM_COMM);
|
|
Packit Service |
c5cf8c |
MPIR_Assert(dist_graph_ptr->in_weights != NULL);
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
out_capacity = 10; /* arbitrary */
|
|
Packit Service |
c5cf8c |
dist_graph_ptr->out = MPL_malloc(out_capacity * sizeof(int), MPL_MEM_COMM);
|
|
Packit Service |
c5cf8c |
if (dist_graph_ptr->is_weighted) {
|
|
Packit Service |
c5cf8c |
dist_graph_ptr->out_weights = MPL_malloc(out_capacity * sizeof(int), MPL_MEM_COMM);
|
|
Packit Service |
c5cf8c |
MPIR_Assert(dist_graph_ptr->out_weights);
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
for (i = 0; i < in_out_peers[0]; ++i) {
|
|
Packit Service |
c5cf8c |
MPI_Status status;
|
|
Packit Service |
c5cf8c |
MPI_Aint count;
|
|
Packit Service |
c5cf8c |
int *buf;
|
|
Packit Service |
c5cf8c |
/* receive inbound edges */
|
|
Packit Service |
c5cf8c |
mpi_errno = MPIC_Probe(MPI_ANY_SOURCE, MPIR_TOPO_A_TAG, comm_old, &status);
|
|
Packit Service |
c5cf8c |
if (mpi_errno)
|
|
Packit Service |
c5cf8c |
MPIR_ERR_POP(mpi_errno);
|
|
Packit Service |
c5cf8c |
MPIR_Get_count_impl(&status, MPI_INT, &count);
|
|
Packit Service |
c5cf8c |
/* can't use CHKLMEM macros b/c we are in a loop */
|
|
Packit Service |
c5cf8c |
/* FIXME: Why not - there is only one allocated at a time. Is it only
|
|
Packit Service |
c5cf8c |
* that there is no defined macro to pop and free an item? */
|
|
Packit Service |
c5cf8c |
buf = MPL_malloc(count * sizeof(int), MPL_MEM_COMM);
|
|
Packit Service |
c5cf8c |
MPIR_ERR_CHKANDJUMP(!buf, mpi_errno, MPI_ERR_OTHER, "**nomem");
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
mpi_errno =
|
|
Packit Service |
c5cf8c |
MPIC_Recv(buf, count, MPI_INT, MPI_ANY_SOURCE, MPIR_TOPO_A_TAG, comm_ptr,
|
|
Packit Service |
c5cf8c |
MPI_STATUS_IGNORE, &errflag);
|
|
Packit Service |
c5cf8c |
/* FIXME: buf is never freed on error! */
|
|
Packit Service |
c5cf8c |
if (mpi_errno)
|
|
Packit Service |
c5cf8c |
MPIR_ERR_POP(mpi_errno);
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
for (j = 0; j < count / 2; ++j) {
|
|
Packit Service |
c5cf8c |
int deg = dist_graph_ptr->indegree++;
|
|
Packit Service |
c5cf8c |
if (deg >= in_capacity) {
|
|
Packit Service |
c5cf8c |
in_capacity *= 2;
|
|
Packit Service |
c5cf8c |
/* FIXME: buf is never freed on error! */
|
|
Packit Service |
c5cf8c |
MPIR_REALLOC_ORJUMP(dist_graph_ptr->in, in_capacity * sizeof(int), MPL_MEM_COMM,
|
|
Packit Service |
c5cf8c |
mpi_errno);
|
|
Packit Service |
c5cf8c |
if (dist_graph_ptr->is_weighted)
|
|
Packit Service |
c5cf8c |
/* FIXME: buf is never freed on error! */
|
|
Packit Service |
c5cf8c |
MPIR_REALLOC_ORJUMP(dist_graph_ptr->in_weights, in_capacity * sizeof(int),
|
|
Packit Service |
c5cf8c |
MPL_MEM_COMM, mpi_errno);
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
dist_graph_ptr->in[deg] = buf[2 * j];
|
|
Packit Service |
c5cf8c |
if (dist_graph_ptr->is_weighted)
|
|
Packit Service |
c5cf8c |
dist_graph_ptr->in_weights[deg] = buf[2 * j + 1];
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
MPL_free(buf);
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
for (i = 0; i < in_out_peers[1]; ++i) {
|
|
Packit Service |
c5cf8c |
MPI_Status status;
|
|
Packit Service |
c5cf8c |
MPI_Aint count;
|
|
Packit Service |
c5cf8c |
int *buf;
|
|
Packit Service |
c5cf8c |
/* receive outbound edges */
|
|
Packit Service |
c5cf8c |
mpi_errno = MPIC_Probe(MPI_ANY_SOURCE, MPIR_TOPO_B_TAG, comm_old, &status);
|
|
Packit Service |
c5cf8c |
if (mpi_errno)
|
|
Packit Service |
c5cf8c |
MPIR_ERR_POP(mpi_errno);
|
|
Packit Service |
c5cf8c |
MPIR_Get_count_impl(&status, MPI_INT, &count);
|
|
Packit Service |
c5cf8c |
/* can't use CHKLMEM macros b/c we are in a loop */
|
|
Packit Service |
c5cf8c |
/* Why not? */
|
|
Packit Service |
c5cf8c |
buf = MPL_malloc(count * sizeof(int), MPL_MEM_COMM);
|
|
Packit Service |
c5cf8c |
MPIR_ERR_CHKANDJUMP(!buf, mpi_errno, MPI_ERR_OTHER, "**nomem");
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
mpi_errno =
|
|
Packit Service |
c5cf8c |
MPIC_Recv(buf, count, MPI_INT, MPI_ANY_SOURCE, MPIR_TOPO_B_TAG, comm_ptr,
|
|
Packit Service |
c5cf8c |
MPI_STATUS_IGNORE, &errflag);
|
|
Packit Service |
c5cf8c |
/* FIXME: buf is never freed on error! */
|
|
Packit Service |
c5cf8c |
if (mpi_errno)
|
|
Packit Service |
c5cf8c |
MPIR_ERR_POP(mpi_errno);
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
for (j = 0; j < count / 2; ++j) {
|
|
Packit Service |
c5cf8c |
int deg = dist_graph_ptr->outdegree++;
|
|
Packit Service |
c5cf8c |
if (deg >= out_capacity) {
|
|
Packit Service |
c5cf8c |
out_capacity *= 2;
|
|
Packit Service |
c5cf8c |
/* FIXME: buf is never freed on error! */
|
|
Packit Service |
c5cf8c |
MPIR_REALLOC_ORJUMP(dist_graph_ptr->out, out_capacity * sizeof(int), MPL_MEM_COMM,
|
|
Packit Service |
c5cf8c |
mpi_errno);
|
|
Packit Service |
c5cf8c |
if (dist_graph_ptr->is_weighted)
|
|
Packit Service |
c5cf8c |
/* FIXME: buf is never freed on error! */
|
|
Packit Service |
c5cf8c |
MPIR_REALLOC_ORJUMP(dist_graph_ptr->out_weights, out_capacity * sizeof(int),
|
|
Packit Service |
c5cf8c |
MPL_MEM_COMM, mpi_errno);
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
dist_graph_ptr->out[deg] = buf[2 * j];
|
|
Packit Service |
c5cf8c |
if (dist_graph_ptr->is_weighted)
|
|
Packit Service |
c5cf8c |
dist_graph_ptr->out_weights[deg] = buf[2 * j + 1];
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
MPL_free(buf);
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
mpi_errno = MPIC_Waitall(idx, reqs, MPI_STATUSES_IGNORE, &errflag);
|
|
Packit Service |
c5cf8c |
if (mpi_errno)
|
|
Packit Service |
c5cf8c |
MPIR_ERR_POP(mpi_errno);
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
/* remove any excess memory allocation */
|
|
Packit Service |
c5cf8c |
MPIR_REALLOC_ORJUMP(dist_graph_ptr->in, dist_graph_ptr->indegree * sizeof(int), MPL_MEM_COMM,
|
|
Packit Service |
c5cf8c |
mpi_errno);
|
|
Packit Service |
c5cf8c |
MPIR_REALLOC_ORJUMP(dist_graph_ptr->out, dist_graph_ptr->outdegree * sizeof(int), MPL_MEM_COMM,
|
|
Packit Service |
c5cf8c |
mpi_errno);
|
|
Packit Service |
c5cf8c |
if (dist_graph_ptr->is_weighted) {
|
|
Packit Service |
c5cf8c |
MPIR_REALLOC_ORJUMP(dist_graph_ptr->in_weights, dist_graph_ptr->indegree * sizeof(int),
|
|
Packit Service |
c5cf8c |
MPL_MEM_COMM, mpi_errno);
|
|
Packit Service |
c5cf8c |
MPIR_REALLOC_ORJUMP(dist_graph_ptr->out_weights, dist_graph_ptr->outdegree * sizeof(int),
|
|
Packit Service |
c5cf8c |
MPL_MEM_COMM, mpi_errno);
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
mpi_errno = MPIR_Topology_put(comm_dist_graph_ptr, topo_ptr);
|
|
Packit Service |
c5cf8c |
if (mpi_errno)
|
|
Packit Service |
c5cf8c |
MPIR_ERR_POP(mpi_errno);
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
MPIR_CHKPMEM_COMMIT();
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
MPIR_OBJ_PUBLISH_HANDLE(*comm_dist_graph, comm_dist_graph_ptr->handle);
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
/* ... end of body of routine ... */
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
fn_exit:
|
|
Packit Service |
c5cf8c |
for (i = 0; i < comm_size; ++i) {
|
|
Packit Service |
c5cf8c |
if (rin[i])
|
|
Packit Service |
c5cf8c |
MPL_free(rin[i]);
|
|
Packit Service |
c5cf8c |
if (rout[i])
|
|
Packit Service |
c5cf8c |
MPL_free(rout[i]);
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
MPIR_CHKLMEM_FREEALL();
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
MPIR_FUNC_TERSE_EXIT(MPID_STATE_MPI_DIST_GRAPH_CREATE);
|
|
Packit Service |
c5cf8c |
MPID_THREAD_CS_EXIT(GLOBAL, MPIR_THREAD_GLOBAL_ALLFUNC_MUTEX);
|
|
Packit Service |
c5cf8c |
return mpi_errno;
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
/* --BEGIN ERROR HANDLING-- */
|
|
Packit Service |
c5cf8c |
fn_fail:
|
|
Packit Service |
c5cf8c |
if (dist_graph_ptr && dist_graph_ptr->in)
|
|
Packit Service |
c5cf8c |
MPL_free(dist_graph_ptr->in);
|
|
Packit Service |
c5cf8c |
if (dist_graph_ptr && dist_graph_ptr->in_weights)
|
|
Packit Service |
c5cf8c |
MPL_free(dist_graph_ptr->in_weights);
|
|
Packit Service |
c5cf8c |
if (dist_graph_ptr && dist_graph_ptr->out)
|
|
Packit Service |
c5cf8c |
MPL_free(dist_graph_ptr->out);
|
|
Packit Service |
c5cf8c |
if (dist_graph_ptr && dist_graph_ptr->out_weights)
|
|
Packit Service |
c5cf8c |
MPL_free(dist_graph_ptr->out_weights);
|
|
Packit Service |
c5cf8c |
MPIR_CHKPMEM_REAP();
|
|
Packit Service |
c5cf8c |
#ifdef HAVE_ERROR_CHECKING
|
|
Packit Service |
c5cf8c |
mpi_errno =
|
|
Packit Service |
c5cf8c |
MPIR_Err_create_code(mpi_errno, MPIR_ERR_RECOVERABLE, FCNAME, __LINE__, MPI_ERR_OTHER,
|
|
Packit Service |
c5cf8c |
"**mpi_dist_graph_create",
|
|
Packit Service |
c5cf8c |
"**mpi_dist_graph_create %C %d %p %p %p %p %I %d %p", comm_old, n,
|
|
Packit Service |
c5cf8c |
sources, degrees, destinations, weights, info, reorder,
|
|
Packit Service |
c5cf8c |
comm_dist_graph);
|
|
Packit Service |
c5cf8c |
#endif
|
|
Packit Service |
c5cf8c |
mpi_errno = MPIR_Err_return_comm(comm_ptr, FCNAME, mpi_errno);
|
|
Packit Service |
c5cf8c |
goto fn_exit;
|
|
Packit Service |
c5cf8c |
/* --END ERROR HANDLING-- */
|
|
Packit Service |
c5cf8c |
}
|