-: 0:Source:/home/MPI/testing/mpich2/mpich2/src/mpi/topo/dist_gr_create.c
-: 0:Graph:dist_gr_create.gcno
-: 0:Data:dist_gr_create.gcda
-: 0:Runs:4
-: 0:Programs:1
-: 1:/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */
-: 2:/*
-: 3: *
-: 4: * (C) 2009 by Argonne National Laboratory.
-: 5: * See COPYRIGHT in top-level directory.
-: 6: */
-: 7:
-: 8:#include "mpiimpl.h"
-: 9:#include "topo.h"
-: 10:
-: 11:/* -- Begin Profiling Symbol Block for routine MPI_Dist_graph_create */
-: 12:#if defined(HAVE_PRAGMA_WEAK)
-: 13:#pragma weak MPI_Dist_graph_create = PMPI_Dist_graph_create
-: 14:#elif defined(HAVE_PRAGMA_HP_SEC_DEF)
-: 15:#pragma _HP_SECONDARY_DEF PMPI_Dist_graph_create MPI_Dist_graph_create
-: 16:#elif defined(HAVE_PRAGMA_CRI_DUP)
-: 17:#pragma _CRI duplicate MPI_Dist_graph_create as PMPI_Dist_graph_create
-: 18:#endif
-: 19:/* -- End Profiling Symbol Block */
-: 20:
-: 21:/* Define MPICH_MPI_FROM_PMPI if weak symbols are not supported to build
-: 22: the MPI routines */
-: 23:#ifndef MPICH_MPI_FROM_PMPI
-: 24:#undef MPI_Dist_graph_create
-: 25:#define MPI_Dist_graph_create PMPI_Dist_graph_create
-: 26:/* any utility functions should go here, usually prefixed with PMPI_LOCAL to
-: 27: * correctly handle weak symbols and the profiling interface */
-: 28:#endif
-: 29:
-: 30:#undef FUNCNAME
-: 31:#define FUNCNAME MPI_Dist_graph_create
-: 32:#undef FCNAME
-: 33:#define FCNAME MPIU_QUOTE(FUNCNAME)
-: 34:/*@
-: 35:MPI_Dist_graph_create - MPI_DIST_GRAPH_CREATE returns a handle to a new
-: 36:communicator to which the distributed graph topology information is
-: 37:attached.
-: 38:
-: 39:Input Parameters:
-: 40:+ comm_old - input communicator (handle)
-: 41:. n - number of source nodes for which this process specifies edges (non-negative integer)
-: 42:. sources - array containing the n source nodes for which this process specifies edges (array of non-negative integers)
-: 43:. degrees - array specifying the number of destinations for each source node in the source node array (array of non-negative integers)
-: 44:. destinations - destination nodes for the source nodes in the source node array (array of non-negative integers)
-: 45:. weights - weights for source to destination edges (array of non-negative integers)
-: 46:. info - hints on optimization and interpretation of weights (handle)
-: 47:- reorder - the process may be reordered (true) or not (false) (logical)
-: 48:
-: 49:Output Parameter:
-: 50:. comm_dist_graph - communicator with distributed graph topology added (handle)
-: 51:
-: 52:.N ThreadSafe
-: 53:
-: 54:.N Fortran
-: 55:
-: 56:.N Errors
-: 57:.N MPI_SUCCESS
-: 58:@*/
-: 59:int MPI_Dist_graph_create(MPI_Comm comm_old, int n, int sources[],
-: 60: int degrees[], int destinations[], int weights[],
-: 61: MPI_Info info, int reorder, MPI_Comm *comm_dist_graph)
320: 62:{
320: 63: int mpi_errno = MPI_SUCCESS;
320: 64: MPID_Comm *comm_ptr = NULL;
320: 65: MPID_Comm *comm_dist_graph_ptr = NULL;
320: 66: MPID_Info *info_ptr = NULL;
320: 67: MPI_Request *reqs = NULL;
320: 68: MPIR_Topology *topo_ptr = NULL;
320: 69: MPIR_Dist_graph_topology *dist_graph_ptr = NULL;
-: 70: int i;
-: 71: int j;
-: 72: int index;
320: 73: int comm_size = 0;
-: 74: int in_capacity;
-: 75: int out_capacity;
320: 76: int **rout = NULL;
320: 77: int **rin = NULL;
-: 78: int *rin_sizes;
-: 79: int *rout_sizes;
-: 80: int *rin_idx;
-: 81: int *rout_idx;
-: 82: int *rs;
320: 83: int in_out_peers[2] = {-1, -1};
320: 84: MPIU_CHKLMEM_DECL(9);
320: 85: MPIU_CHKPMEM_DECL(1);
320: 86: MPIU_THREADPRIV_DECL;
-: 87: MPID_MPI_STATE_DECL(MPID_STATE_MPI_DIST_GRAPH_CREATE);
-: 88:
320: 89: MPIR_ERRTEST_INITIALIZED_ORDIE();
-: 90:
320: 91: MPIU_THREAD_CS_ENTER(ALLFUNC,);
-: 92: MPID_MPI_FUNC_ENTER(MPID_STATE_MPI_DIST_GRAPH_CREATE);
-: 93:
320: 94: MPIU_THREADPRIV_GET;
320: 95: MPIR_Nest_incr();
-: 96:
-: 97: /* Validate parameters, especially handles needing to be converted */
|
-: 98:# ifdef HAVE_ERROR_CHECKING
-: 99: {
-: 100: MPID_BEGIN_ERROR_CHECKS;
-: 101: {
320: 102: MPIR_ERRTEST_COMM(comm_old, mpi_errno);
320: 103: MPIR_ERRTEST_INFO_OR_NULL(info, mpi_errno);
320: 104: if (mpi_errno != MPI_SUCCESS) goto fn_fail;
-: 105: }
-: 106: MPID_END_ERROR_CHECKS;
-: 107: }
-: 108:# endif
-: 109:
-: 110: /* Convert MPI object handles to object pointers */
|
320: 111: MPID_Comm_get_ptr(comm_old, comm_ptr);
320: 112: MPID_Info_get_ptr(info, info_ptr);
-: 113:
-: 114: /* Validate parameters and objects (post conversion) */
|
-: 115:# ifdef HAVE_ERROR_CHECKING
-: 116: {
-: 117: MPID_BEGIN_ERROR_CHECKS;
-: 118: {
-: 119: /* Validate comm_ptr */
320: 120: MPID_Comm_valid_ptr(comm_ptr, mpi_errno);
-: 121: /* If comm_ptr is not valid, it will be reset to null */
320: 122: if (comm_ptr) {
320: 123: MPIR_ERRTEST_COMM_INTRA(comm_ptr, mpi_errno);
-: 124: }
-: 125:
320: 126: MPIR_ERRTEST_ARGNEG(n, "n", mpi_errno);
320: 127: if (n > 0) {
160: 128: int have_degrees = 0;
160: 129: MPIR_ERRTEST_ARGNULL(sources, "sources", mpi_errno);
160: 130: MPIR_ERRTEST_ARGNULL(degrees, "degrees", mpi_errno);
174: 131: for (i = 0; i < n; ++i) {
160: 132: if (degrees[i]) {
146: 133: have_degrees = 1;
146: 134: break;
-: 135: }
-: 136: }
160: 137: if (have_degrees) {
146: 138: MPIR_ERRTEST_ARGNULL(destinations, "destinations", mpi_errno);
-: 139: /* in practice this check is currently silly, since
-: 140: * MPI_UNWEIGHTED==NULL */
146: 141: if (weights != MPI_UNWEIGHTED)
146: 142: MPIR_ERRTEST_ARGNULL(weights, "weights", mpi_errno);
-: 143: }
-: 144: }
-: 145:
320: 146: if (mpi_errno != MPI_SUCCESS) goto fn_fail;
-: 147: }
-: 148: MPID_END_ERROR_CHECKS;
-: 149: }
-: 150:# endif /* HAVE_ERROR_CHECKING */
-: 151:
-: 152:
-: 153: /* ... body of routine ... */
-: 154: /* Implementation based on Torsten Hoefler's reference implementation
-: 155: * attached to MPI-2.2 ticket #33. */
|
320: 156: *comm_dist_graph = MPI_COMM_NULL;
-: 157:
320: 158: comm_size = comm_ptr->local_size;
-: 159:
-: 160: /* following the spirit of the old topo interface, attributes do not
-: 161: * propagate to the new communicator (see MPI-2.1 pp. 243 line 11) */
320: 162: mpi_errno = MPIR_Comm_copy(comm_ptr, comm_size, &comm_dist_graph_ptr);
|
320: 163: if (mpi_errno) MPIU_ERR_POP(mpi_errno);
|
320: 164: MPIU_Assert(comm_dist_graph_ptr != NULL);
-: 165:
-: 166: /* rin is an array of size comm_size containing pointers to arrays of
-: 167: * rin_sizes[x]. rin[x] is locally known number of edges into this process
-: 168: * from rank x.
-: 169: *
-: 170: * rout is an array of comm_size containing pointers to arrays of
-: 171: * rout_sizes[x]. rout[x] is the locally known number of edges out of this
-: 172: * process to rank x. */
320: 173: MPIU_CHKLMEM_MALLOC(rout, int **, comm_size*sizeof(int*), mpi_errno, "rout");
320: 174: MPIU_CHKLMEM_MALLOC(rin, int **, comm_size*sizeof(int*), mpi_errno, "rin");
320: 175: MPIU_CHKLMEM_MALLOC(rin_sizes, int *, comm_size*sizeof(int), mpi_errno, "rin_sizes");
320: 176: MPIU_CHKLMEM_MALLOC(rout_sizes, int *, comm_size*sizeof(int), mpi_errno, "rout_sizes");
320: 177: MPIU_CHKLMEM_MALLOC(rin_idx, int *, comm_size*sizeof(int), mpi_errno, "rin_idx");
320: 178: MPIU_CHKLMEM_MALLOC(rout_idx, int *, comm_size*sizeof(int), mpi_errno, "rout_idx");
-: 179:
320: 180: memset(rout, 0, comm_size*sizeof(int*));
320: 181: memset(rin, 0, comm_size*sizeof(int*));
320: 182: memset(rin_sizes, 0, comm_size*sizeof(int));
320: 183: memset(rout_sizes, 0, comm_size*sizeof(int));
320: 184: memset(rin_idx, 0, comm_size*sizeof(int));
320: 185: memset(rout_idx, 0, comm_size*sizeof(int));
-: 186:
-: 187: /* compute array sizes */
320: 188: index = 0;
748: 189: for (i = 0; i < n; ++i) {
428: 190: MPIU_Assert(sources[i] < comm_size);
950: 191: for (j = 0; j < degrees[i]; ++j) {
522: 192: MPIU_Assert(destinations[index] < comm_size);
-: 193: /* rout_sizes[i] is twice as long as the number of edges to be
-: 194: * sent to rank i by this process */
522: 195: rout_sizes[sources[i]] += 2;
522: 196: rin_sizes[destinations[index]] += 2;
522: 197: ++index;
-: 198: }
-: 199: }
-: 200:
-: 201: /* allocate arrays */
1600: 202: for (i = 0; i < comm_size; ++i) {
-: 203: /* can't use CHKLMEM macros b/c we are in a loop */
1280: 204: if (rin_sizes[i]) {
298: 205: rin[i] = MPIU_Malloc(rin_sizes[i] * sizeof(int));
-: 206: }
1280: 207: if (rout_sizes[i]) {
306: 208: rout[i] = MPIU_Malloc(rout_sizes[i] * sizeof(int));
-: 209: }
-: 210: }
-: 211:
-: 212: /* populate arrays */
320: 213: index = 0;
748: 214: for (i = 0; i < n; ++i) {
-: 215: /* TODO add this assert as proper error checking above */
428: 216: int s_rank = sources[i];
428: 217: MPIU_Assert(s_rank < comm_size);
428: 218: MPIU_Assert(s_rank >= 0);
-: 219:
950: 220: for (j = 0; j < degrees[i]; ++j) {
522: 221: int d_rank = destinations[index];
522: 222: int weight = (weights == MPI_UNWEIGHTED ? 0 : weights[index]);
-: 223: /* TODO add this assert as proper error checking above */
522: 224: MPIU_Assert(d_rank < comm_size);
522: 225: MPIU_Assert(d_rank >= 0);
-: 226:
-: 227: /* XXX DJG what about self-edges? do we need to drop one of these
-: 228: * cases when there is a self-edge to avoid double-counting? */
-: 229:
-: 230: /* rout[s][2*x] is the value of d for the j'th edge between (s,d)
-: 231: * with weight rout[s][2*x+1], where x is the current end of the
-: 232: * outgoing edge list for s. x==(rout_idx[s]/2) */
522: 233: rout[s_rank][rout_idx[s_rank]++] = d_rank;
522: 234: rout[s_rank][rout_idx[s_rank]++] = weight;
-: 235:
-: 236: /* rin[d][2*x] is the value of s for the j'th edge between (s,d)
-: 237: * with weight rout[d][2*x+1], where x is the current end of the
-: 238: * incoming edge list for d. x==(rin_idx[d]/2) */
522: 239: rin[d_rank][rin_idx[d_rank]++] = s_rank;
522: 240: rin[d_rank][rin_idx[d_rank]++] = weight;
-: 241:
522: 242: ++index;
-: 243: }
-: 244: }
-: 245:
1600: 246: for (i = 0; i < comm_size; ++i) {
-: 247: /* sanity check that all arrays are fully populated*/
1280: 248: MPIU_Assert(rin_idx[i] == rin_sizes[i]);
1280: 249: MPIU_Assert(rout_idx[i] == rout_sizes[i]);
-: 250: }
-: 251:
320: 252: MPIU_CHKLMEM_MALLOC(rs, int *, 2*comm_size*sizeof(int), mpi_errno, "red-scat source buffer");
1600: 253: for (i = 0; i < comm_size; ++i) {
1280: 254: rs[2*i] = (rin_sizes[i] ? 1 : 0);
1280: 255: rs[2*i+1] = (rout_sizes[i] ? 1 : 0);
-: 256: }
-: 257:
-: 258: /* compute the number of peers I will recv from */
320: 259: mpi_errno = NMPI_Reduce_scatter_block(rs, in_out_peers, 2, MPI_INT, MPI_SUM, comm_old);
|
320: 260: if (mpi_errno) MPIU_ERR_POP(mpi_errno);
-: 261:
|
320: 262: MPIU_Assert(in_out_peers[0] <= comm_size && in_out_peers[0] >= 0);
320: 263: MPIU_Assert(in_out_peers[1] <= comm_size && in_out_peers[1] >= 0);
-: 264:
320: 265: index = 0;
-: 266: /* must be 2*comm_size requests because we will possibly send inbound and
-: 267: * outbound edges to everyone in our communicator */
320: 268: MPIU_CHKLMEM_MALLOC(reqs, MPI_Request *, 2*comm_size*sizeof(MPI_Request), mpi_errno, "temp request array");
1600: 269: for (i = 0; i < comm_size; ++i) {
1280: 270: if (rin_sizes[i]) {
-: 271: /* send edges where i is a destination to process i */
298: 272: NMPI_Isend(&rin[i][0], rin_sizes[i], MPI_INT, i, MPIR_TOPO_A_TAG, comm_old, &reqs[index++]);
-: 273: }
1280: 274: if (rout_sizes[i]) {
-: 275: /* send edges where i is a source to process i */
306: 276: NMPI_Isend(&rout[i][0], rout_sizes[i], MPI_INT, i, MPIR_TOPO_B_TAG, comm_old, &reqs[index++]);
-: 277: }
-: 278: }
320: 279: MPIU_Assert(index <= (2 * comm_size));
-: 280:
-: 281: /* Create the topology structure */
320: 282: MPIU_CHKPMEM_MALLOC(topo_ptr, MPIR_Topology *, sizeof(MPIR_Topology), mpi_errno, "topo_ptr");
320: 283: topo_ptr->kind = MPI_DIST_GRAPH;
320: 284: dist_graph_ptr = &topo_ptr->topo.dist_graph;
320: 285: dist_graph_ptr->indegree = 0;
320: 286: dist_graph_ptr->in = NULL;
320: 287: dist_graph_ptr->in_weights = NULL;
320: 288: dist_graph_ptr->outdegree = 0;
320: 289: dist_graph_ptr->out = NULL;
320: 290: dist_graph_ptr->out_weights = NULL;
-: 291:
-: 292: /* can't use CHKPMEM macros for this b/c we need to realloc */
320: 293: in_capacity = 10; /* arbitrary */
320: 294: dist_graph_ptr->in = MPIU_Malloc(in_capacity*sizeof(int));
320: 295: if (weights != MPI_UNWEIGHTED)
320: 296: dist_graph_ptr->in_weights = MPIU_Malloc(in_capacity*sizeof(int));
320: 297: out_capacity = 10; /* arbitrary */
320: 298: dist_graph_ptr->out = MPIU_Malloc(out_capacity*sizeof(int));
320: 299: if (weights != MPI_UNWEIGHTED)
320: 300: dist_graph_ptr->out_weights = MPIU_Malloc(out_capacity*sizeof(int));
-: 301:
618: 302: for (i = 0; i < in_out_peers[0]; ++i) {
-: 303: MPI_Status status;
-: 304: int count;
-: 305: int *buf;
-: 306: /* receive inbound edges */
298: 307: mpi_errno = NMPI_Probe(MPI_ANY_SOURCE, MPIR_TOPO_A_TAG, comm_old, &status);
|
298: 308: if (mpi_errno) MPIU_ERR_POP(mpi_errno);
|
298: 309: mpi_errno = NMPI_Get_count(&status, MPI_INT, &count);
|
298: 310: if (mpi_errno) MPIU_ERR_POP(mpi_errno);
-: 311: /* can't use CHKLMEM macros b/c we are in a loop */
|
298: 312: buf = MPIU_Malloc(count*sizeof(int));
298: 313: MPIU_ERR_CHKANDJUMP(!buf, mpi_errno, MPIR_ERR_RECOVERABLE, "**nomem");
-: 314:
298: 315: mpi_errno = NMPI_Recv(buf, count, MPI_INT, MPI_ANY_SOURCE, MPIR_TOPO_A_TAG, comm_old, MPI_STATUS_IGNORE);
-: 316:
820: 317: for (j = 0; j < count/2; ++j) {
522: 318: int deg = dist_graph_ptr->indegree++;
522: 319: if (deg >= in_capacity) {
|
#####: 320: in_capacity *= 2;
#####: 321: MPIU_REALLOC_ORJUMP(dist_graph_ptr->in, in_capacity*sizeof(int), mpi_errno);
#####: 322: if (weights != MPI_UNWEIGHTED)
#####: 323: MPIU_REALLOC_ORJUMP(dist_graph_ptr->in_weights, in_capacity*sizeof(int), mpi_errno);
-: 324: }
|
522: 325: dist_graph_ptr->in[deg] = buf[2*j];
522: 326: if (weights != MPI_UNWEIGHTED)
522: 327: dist_graph_ptr->in_weights[deg] = buf[2*j+1];
-: 328: }
298: 329: MPIU_Free(buf);
-: 330: }
-: 331:
626: 332: for (i = 0; i < in_out_peers[1]; ++i) {
-: 333: MPI_Status status;
-: 334: int count;
-: 335: int *buf;
-: 336: /* receive outbound edges */
306: 337: mpi_errno = NMPI_Probe(MPI_ANY_SOURCE, MPIR_TOPO_B_TAG, comm_old, &status);
|
306: 338: if (mpi_errno) MPIU_ERR_POP(mpi_errno);
|
306: 339: mpi_errno = NMPI_Get_count(&status, MPI_INT, &count);
|
306: 340: if (mpi_errno) MPIU_ERR_POP(mpi_errno);
-: 341: /* can't use CHKLMEM macros b/c we are in a loop */
|
306: 342: buf = MPIU_Malloc(count*sizeof(int));
306: 343: MPIU_ERR_CHKANDJUMP(!buf, mpi_errno, MPIR_ERR_RECOVERABLE, "**nomem");
-: 344:
306: 345: mpi_errno = NMPI_Recv(buf, count, MPI_INT, MPI_ANY_SOURCE, MPIR_TOPO_B_TAG, comm_old, MPI_STATUS_IGNORE);
-: 346:
828: 347: for (j = 0; j < count/2; ++j) {
522: 348: int deg = dist_graph_ptr->outdegree++;
522: 349: if (deg >= out_capacity) {
|
#####: 350: out_capacity *= 2;
#####: 351: MPIU_REALLOC_ORJUMP(dist_graph_ptr->out, out_capacity*sizeof(int), mpi_errno);
#####: 352: if (weights != MPI_UNWEIGHTED)
#####: 353: MPIU_REALLOC_ORJUMP(dist_graph_ptr->out_weights, out_capacity*sizeof(int), mpi_errno);
-: 354: }
|
522: 355: dist_graph_ptr->out[deg] = buf[2*j];
522: 356: if (weights != MPI_UNWEIGHTED)
522: 357: dist_graph_ptr->out_weights[deg] = buf[2*j+1];
-: 358: }
306: 359: MPIU_Free(buf);
-: 360: }
-: 361:
320: 362: mpi_errno = NMPI_Waitall(index, reqs, MPI_STATUSES_IGNORE);
|
320: 363: if (mpi_errno) MPIU_ERR_POP(mpi_errno);
-: 364:
-: 365: /* remove any excess memory allocation */
|
320: 366: MPIU_REALLOC_ORJUMP(dist_graph_ptr->in, dist_graph_ptr->indegree*sizeof(int), mpi_errno);
320: 367: MPIU_REALLOC_ORJUMP(dist_graph_ptr->out, dist_graph_ptr->outdegree*sizeof(int), mpi_errno);
320: 368: if (weights != MPI_UNWEIGHTED) {
320: 369: MPIU_REALLOC_ORJUMP(dist_graph_ptr->in_weights, dist_graph_ptr->indegree*sizeof(int), mpi_errno);
320: 370: MPIU_REALLOC_ORJUMP(dist_graph_ptr->out_weights, dist_graph_ptr->outdegree*sizeof(int), mpi_errno);
-: 371: }
-: 372:
320: 373: mpi_errno = MPIR_Topology_put(comm_dist_graph_ptr, topo_ptr);
|
320: 374: if (mpi_errno) MPIU_ERR_POP(mpi_errno);
-: 375:
|
320: 376: MPIU_CHKPMEM_COMMIT();
320: 377: *comm_dist_graph = comm_dist_graph_ptr->handle;
-: 378: /* ... end of body of routine ... */
-: 379:
320: 380: fn_exit:
1600: 381: for (i = 0; i < comm_size; ++i) {
1280: 382: if (rin[i])
298: 383: MPIU_Free(rin[i]);
1280: 384: if (rout[i])
306: 385: MPIU_Free(rout[i]);
-: 386: }
-: 387:
2560: 388: MPIU_CHKLMEM_FREEALL();
-: 389:
320: 390: MPIR_Nest_decr();
|
-: 391: MPID_MPI_FUNC_EXIT(MPID_STATE_MPI_DIST_GRAPH_CREATE);
|
320: 392: MPIU_THREAD_CS_EXIT(ALLFUNC,);
320: 393: return mpi_errno;
-: 394:
|
#####: 395: fn_fail:
|
#####: 396: if (dist_graph_ptr && dist_graph_ptr->in)
#####: 397: MPIU_Free(dist_graph_ptr->in);
#####: 398: if (dist_graph_ptr && dist_graph_ptr->in_weights)
#####: 399: MPIU_Free(dist_graph_ptr->in_weights);
#####: 400: if (dist_graph_ptr && dist_graph_ptr->out)
#####: 401: MPIU_Free(dist_graph_ptr->out);
#####: 402: if (dist_graph_ptr && dist_graph_ptr->out_weights)
#####: 403: MPIU_Free(dist_graph_ptr->out_weights);
#####: 404: MPIU_CHKPMEM_REAP();
|
-: 405: /* --BEGIN ERROR HANDLING-- */
#####: 406: mpi_errno = MPIR_Err_create_code(
-: 407: mpi_errno, MPIR_ERR_RECOVERABLE, FCNAME, __LINE__, MPI_ERR_OTHER,
-: 408: "**mpi_dist_graph_create", "**mpi_dist_graph_create %C %d %p %p %p %p %I %d %p",
-: 409: comm_old, n, sources, degrees, destinations, weights, info, reorder, comm_dist_graph);
#####: 410: mpi_errno = MPIR_Err_return_comm(comm_ptr, FCNAME, mpi_errno);
#####: 411: goto fn_exit;
-: 412: /* --END ERROR HANDLING-- */
-: 413:}
-: 414:
|