int ompi_comm_neighbors_count(MPI_Comm comm, int *indegree, int *outdegree, int *weighted) { int res; if (OMPI_COMM_IS_CART(comm)) { int ndims; res = MPI_Cartdim_get(comm, &ndims) ; if (MPI_SUCCESS != res) { return res; } /* outdegree is always 2*ndims because we need to iterate over empty buffers for MPI_PROC_NULL */ *outdegree = *indegree = 2*ndims; *weighted = 0; } else if (OMPI_COMM_IS_GRAPH(comm)) { int rank, nneighbors; rank = ompi_comm_rank ((ompi_communicator_t *) comm); res = MPI_Graph_neighbors_count(comm, rank, &nneighbors); if (MPI_SUCCESS != res) { return res; } *outdegree = *indegree = nneighbors; *weighted = 0; } else if (OMPI_COMM_IS_DIST_GRAPH(comm)) { res = MPI_Dist_graph_neighbors_count(comm, indegree, outdegree, weighted); } else { return MPI_ERR_ARG; } return MPI_SUCCESS; }
Comm::Comm(MPI_Comm impl) : impl_(impl) { int topo_type; CALL(MPI_Topo_test(impl, &topo_type)); if (topo_type == MPI_DIST_GRAPH) { int nin, nout, is_weighted; CALL(MPI_Dist_graph_neighbors_count(impl, &nin, &nout, &is_weighted)); HostWrite<I32> sources(nin); HostWrite<I32> destinations(nout); CALL(MPI_Dist_graph_neighbors(impl, nin, sources.data(), OMEGA_H_MPI_UNWEIGHTED, nout, destinations.data(), OMEGA_H_MPI_UNWEIGHTED)); srcs_ = sources.write(); dsts_ = destinations.write(); host_srcs_ = HostRead<I32>(srcs_); host_dsts_ = HostRead<I32>(dsts_); } }
int NBC_Comm_neighbors_count(MPI_Comm comm, int *indegree, int *outdegree, int *weighted) { int topo, res; res = MPI_Topo_test(comm, &topo); if (MPI_SUCCESS != res) { printf("MPI Error in MPI_Topo_test() (%i)\n", res); return res; } switch(topo) { case MPI_CART: /* cartesian */ { int ndims; res = MPI_Cartdim_get(comm, &ndims) ; if (MPI_SUCCESS != res) { printf("MPI Error in MPI_Cartdim_get() (%i)\n", res); return res; } /* outdegree is always 2*ndims because we need to iterate over empty buffers for MPI_PROC_NULL */ *outdegree = *indegree = 2*ndims; *weighted = 0; } break; case MPI_GRAPH: /* graph */ { int rank, nneighbors; MPI_Comm_rank(comm, &rank); res = MPI_Graph_neighbors_count(comm, rank, &nneighbors); if (MPI_SUCCESS != res) { printf("MPI Error in MPI_Graph_neighbors_count() (%i)\n", res); return res; } *outdegree = *indegree = nneighbors; *weighted = 0; } break; case MPI_DIST_GRAPH: /* graph */ { res = MPI_Dist_graph_neighbors_count(comm, indegree, outdegree, weighted); if (MPI_SUCCESS != res) { printf("MPI Error in MPI_Dist_graph_neighbors_count() (%i)\n", res); return res; } } break; case MPI_UNDEFINED: return NBC_INVALID_TOPOLOGY_COMM; break; default: return NBC_INVALID_PARAM; break; } return NBC_OK; }
void ompi_dist_graph_neighbors_count_f(MPI_Fint *comm, MPI_Fint *inneighbors, MPI_Fint *outneighbors, ompi_fortran_logical_t *weighted, MPI_Fint *ierr) { MPI_Comm c_comm; OMPI_SINGLE_NAME_DECL(inneighbors); OMPI_SINGLE_NAME_DECL(outneighbors); OMPI_LOGICAL_NAME_DECL(weighted); c_comm = MPI_Comm_f2c(*comm); *ierr = OMPI_INT_2_FINT(MPI_Dist_graph_neighbors_count(c_comm, OMPI_SINGLE_NAME_CONVERT(inneighbors), OMPI_SINGLE_NAME_CONVERT(outneighbors), OMPI_LOGICAL_SINGLE_NAME_CONVERT(weighted))); OMPI_SINGLE_INT_2_LOGICAL(weighted); if (OMPI_SUCCESS == OMPI_FINT_2_INT(*ierr)) { OMPI_SINGLE_INT_2_FINT(inneighbors); OMPI_SINGLE_INT_2_FINT(outneighbors); } }
JNIEXPORT jobject JNICALL Java_mpi_GraphComm_getDistGraphNeighbors( JNIEnv *env, jobject jthis, jlong comm) { int inDegree, outDegree, weighted; int rc = MPI_Dist_graph_neighbors_count( (MPI_Comm)comm, &inDegree, &outDegree, &weighted); if(ompi_java_exceptionCheck(env, rc)) return NULL; jintArray sources = (*env)->NewIntArray(env, inDegree), srcWeights = (*env)->NewIntArray(env, inDegree), destinations = (*env)->NewIntArray(env, outDegree), destWeights = (*env)->NewIntArray(env, outDegree); jint *jSources, *jSrcWeights, *jDestinations, *jDestWeights; int *cSources, *cSrcWeights, *cDestinations, *cDestWeights; ompi_java_getIntArray(env, sources, &jSources, &cSources); ompi_java_getIntArray(env, srcWeights, &jSrcWeights, &cSrcWeights); ompi_java_getIntArray(env, destinations, &jDestinations, &cDestinations); ompi_java_getIntArray(env, destWeights, &jDestWeights, &cDestWeights); rc = MPI_Dist_graph_neighbors((MPI_Comm)comm, inDegree, cSources, cSrcWeights, outDegree, cDestinations, cDestWeights); ompi_java_exceptionCheck(env, rc); ompi_java_releaseIntArray(env, sources, jSources, cSources); ompi_java_releaseIntArray(env, srcWeights, jSrcWeights, cSrcWeights); ompi_java_releaseIntArray(env, destinations, jDestinations, cDestinations); ompi_java_releaseIntArray(env, destWeights, jDestWeights, cDestWeights); return (*env)->NewObject(env, ompi_java.DistGraphNeighborsClass, ompi_java.DistGraphNeighborsInit, sources, srcWeights, destinations, destWeights, weighted ? JNI_TRUE : JNI_FALSE); }
static int create_proclists_from_mpi_comm_topology(MPI_Comm comm, int rank, int *nsend_procs, int **send_procs, int *nrecv_procs, int **recv_procs) { int status; int n, i; MPI_Topo_test(comm, &status); switch (status) { case MPI_CART: MPI_Cartdim_get(comm, &n); *nsend_procs = *nrecv_procs = 2 * n; *send_procs = *recv_procs = z_alloc(2 * n, sizeof(int)); for (i = 0; i < n; ++i) MPI_Cart_shift(comm, i, -1, &(*send_procs)[2 * i + 1], &(*send_procs)[2 * i + 0]); break; case MPI_GRAPH: MPI_Graph_neighbors_count(comm, rank, &n); *nsend_procs = *nrecv_procs = n; *send_procs = *recv_procs = z_alloc(n, sizeof(int)); MPI_Graph_neighbors(comm, rank, n, *send_procs); break; #if MPI_VERSION >= 2 && MPI_SUBVERSION >= 2 case MPI_DIST_GRAPH: MPI_Dist_graph_neighbors_count(comm, nrecv_procs, nsend_procs, &n); *send_procs = z_alloc(*nsend_procs + *nrecv_procs, sizeof(int)); *recv_procs = *send_procs + *nsend_procs; MPI_Dist_graph_neighbors(comm, *nrecv_procs, *recv_procs, MPI_UNWEIGHTED, *nsend_procs, *send_procs, MPI_UNWEIGHTED); break; #endif default: return 0; } return 1; }
static int verify_comm(MPI_Comm comm) { int local_errs = 0; int i, j; int indegree, outdegree, weighted; int *sources, *sweights, *destinations, *dweights; int use_dup; int topo_type = MPI_UNDEFINED; MPI_Comm dupcomm = MPI_COMM_NULL; sources = (int *) malloc(size * sizeof(int)); sweights = (int *) malloc(size * sizeof(int)); destinations = (int *) malloc(size * sizeof(int)); dweights = (int *) malloc(size * sizeof(int)); for (use_dup = 0; use_dup <= 1; ++use_dup) { if (!use_dup) { MPI_Dist_graph_neighbors_count(comm, &indegree, &outdegree, &weighted); } else { MPI_Comm_dup(comm, &dupcomm); comm = dupcomm; /* caller retains original comm value */ } MPI_Topo_test(comm, &topo_type); if (topo_type != MPI_DIST_GRAPH) { fprintf(stderr, "topo_type != MPI_DIST_GRAPH\n"); ++local_errs; } j = 0; for (i = 0; i < size; i++) if (layout[i][rank]) j++; if (j != indegree) { fprintf(stderr, "indegree does not match, expected=%d got=%d, layout='%s'\n", indegree, j, graph_layout_name); ++local_errs; } j = 0; for (i = 0; i < size; i++) if (layout[rank][i]) j++; if (j != outdegree) { fprintf(stderr, "outdegree does not match, expected=%d got=%d, layout='%s'\n", outdegree, j, graph_layout_name); ++local_errs; } if ((indegree || outdegree) && (weighted == 0)) { fprintf(stderr, "MPI_Dist_graph_neighbors_count thinks the graph is not weighted\n"); ++local_errs; } MPI_Dist_graph_neighbors(comm, indegree, sources, sweights, outdegree, destinations, dweights); /* For each incoming and outgoing edge in the matrix, search if * the query function listed it in the sources. */ for (i = 0; i < size; i++) { if (layout[i][rank]) { for (j = 0; j < indegree; j++) { assert(sources[j] >= 0); assert(sources[j] < size); if (sources[j] == i) break; } if (j == indegree) { fprintf(stderr, "no edge from %d to %d specified\n", i, rank); ++local_errs; } else { if (sweights[j] != layout[i][rank]) { fprintf(stderr, "incorrect weight for edge (%d,%d): %d instead of %d\n", i, rank, sweights[j], layout[i][rank]); ++local_errs; } } } if (layout[rank][i]) { for (j = 0; j < outdegree; j++) { assert(destinations[j] >= 0); assert(destinations[j] < size); if (destinations[j] == i) break; } if (j == outdegree) { fprintf(stderr, "no edge from %d to %d specified\n", rank, i); ++local_errs; } else { if (dweights[j] != layout[rank][i]) { fprintf(stderr, "incorrect weight for edge (%d,%d): %d instead of %d\n", rank, i, dweights[j], layout[rank][i]); ++local_errs; } } } } /* For each incoming and outgoing edge in the sources, we should * have an entry in the matrix */ for (i = 0; i < indegree; i++) { if (layout[sources[i]][rank] != sweights[i]) { fprintf(stderr, "edge (%d,%d) has a weight %d instead of %d\n", i, rank, sweights[i], layout[sources[i]][rank]); ++local_errs; } } for (i = 0; i < outdegree; i++) { if (layout[rank][destinations[i]] != dweights[i]) { fprintf(stderr, "edge (%d,%d) has a weight %d instead of %d\n", rank, i, dweights[i], layout[rank][destinations[i]]); ++local_errs; } } } if (dupcomm != MPI_COMM_NULL) MPI_Comm_free(&dupcomm); return local_errs; }
int main(int argc, char *argv[]) { int errs = 0; int i, j, k, p; int indegree, outdegree, reorder; int check_indegree, check_outdegree, check_weighted; int *sources, *sweights, *destinations, *dweights, *degrees; MPI_Comm comm; MTest_Init(&argc, &argv); MPI_Comm_size(MPI_COMM_WORLD, &size); MPI_Comm_rank(MPI_COMM_WORLD, &rank); #if MTEST_HAVE_MIN_MPI_VERSION(2,2) layout = (int **) malloc(size * sizeof(int *)); assert(layout); for (i = 0; i < size; i++) { layout[i] = (int *) malloc(size * sizeof(int)); assert(layout[i]); } /* alloc size*size ints to handle the all-on-one-process case */ sources = (int *) malloc(size * size * sizeof(int)); sweights = (int *) malloc(size * size * sizeof(int)); destinations = (int *) malloc(size * size * sizeof(int)); dweights = (int *) malloc(size * size * sizeof(int)); degrees = (int *) malloc(size * size * sizeof(int)); for (i = 0; i < NUM_GRAPHS; i++) { create_graph_layout(i); if (rank == 0) { MTestPrintfMsg( 1, "using graph layout '%s'\n", graph_layout_name ); } /* MPI_Dist_graph_create_adjacent */ if (rank == 0) { MTestPrintfMsg( 1, "testing MPI_Dist_graph_create_adjacent\n" ); } indegree = 0; k = 0; for (j = 0; j < size; j++) { if (layout[j][rank]) { indegree++; sources[k] = j; sweights[k++] = layout[j][rank]; } } outdegree = 0; k = 0; for (j = 0; j < size; j++) { if (layout[rank][j]) { outdegree++; destinations[k] = j; dweights[k++] = layout[rank][j]; } } for (reorder = 0; reorder <= 1; reorder++) { MPI_Dist_graph_create_adjacent(MPI_COMM_WORLD, indegree, sources, sweights, outdegree, destinations, dweights, MPI_INFO_NULL, reorder, &comm); MPI_Barrier(comm); errs += verify_comm(comm); MPI_Comm_free(&comm); } /* a weak check that passing MPI_UNWEIGHTED doesn't cause * create_adjacent to explode */ MPI_Dist_graph_create_adjacent(MPI_COMM_WORLD, indegree, sources, MPI_UNWEIGHTED, outdegree, destinations, MPI_UNWEIGHTED, MPI_INFO_NULL, reorder, &comm); MPI_Barrier(comm); /* intentionally no verify here, weights won't match */ MPI_Comm_free(&comm); /* MPI_Dist_graph_create() where each process specifies its * outgoing edges */ if (rank == 0) { MTestPrintfMsg( 1, "testing MPI_Dist_graph_create w/ outgoing only\n" ); } sources[0] = rank; k = 0; for (j = 0; j < size; j++) { if (layout[rank][j]) { destinations[k] = j; dweights[k++] = layout[rank][j]; } } degrees[0] = k; for (reorder = 0; reorder <= 1; reorder++) { MPI_Dist_graph_create(MPI_COMM_WORLD, 1, sources, degrees, destinations, dweights, MPI_INFO_NULL, reorder, &comm); MPI_Barrier(comm); errs += verify_comm(comm); MPI_Comm_free(&comm); } /* MPI_Dist_graph_create() where each process specifies its * incoming edges */ if (rank == 0) { MTestPrintfMsg( 1, "testing MPI_Dist_graph_create w/ incoming only\n" ); } k = 0; for (j = 0; j < size; j++) { if (layout[j][rank]) { sources[k] = j; sweights[k] = layout[j][rank]; degrees[k] = 1; destinations[k++] = rank; } } for (reorder = 0; reorder <= 1; reorder++) { MPI_Dist_graph_create(MPI_COMM_WORLD, k, sources, degrees, destinations, sweights, MPI_INFO_NULL, reorder, &comm); MPI_Barrier(comm); errs += verify_comm(comm); MPI_Comm_free(&comm); } /* MPI_Dist_graph_create() where rank 0 specifies the entire * graph */ if (rank == 0) { MTestPrintfMsg( 1, "testing MPI_Dist_graph_create w/ rank 0 specifies only\n" ); } p = 0; for (j = 0; j < size; j++) { for (k = 0; k < size; k++) { if (layout[j][k]) { sources[p] = j; sweights[p] = layout[j][k]; degrees[p] = 1; destinations[p++] = k; } } } for (reorder = 0; reorder <= 1; reorder++) { MPI_Dist_graph_create(MPI_COMM_WORLD, (rank == 0) ? p : 0, sources, degrees, destinations, sweights, MPI_INFO_NULL, reorder, &comm); MPI_Barrier(comm); errs += verify_comm(comm); MPI_Comm_free(&comm); } /* MPI_Dist_graph_create() where rank 0 specifies the entire * graph and all other ranks pass NULL. Can catch implementation * problems when MPI_UNWEIGHTED==NULL. */ if (rank == 0) { MTestPrintfMsg( 1, "testing MPI_Dist_graph_create w/ rank 0 specifies only -- NULLs\n"); } p = 0; for (j = 0; j < size; j++) { for (k = 0; k < size; k++) { if (layout[j][k]) { sources[p] = j; sweights[p] = layout[j][k]; degrees[p] = 1; destinations[p++] = k; } } } for (reorder = 0; reorder <= 1; reorder++) { if (rank == 0) { MPI_Dist_graph_create(MPI_COMM_WORLD, p, sources, degrees, destinations, sweights, MPI_INFO_NULL, reorder, &comm); } else { MPI_Dist_graph_create(MPI_COMM_WORLD, 0, NULL, NULL, NULL, NULL, MPI_INFO_NULL, reorder, &comm); } MPI_Barrier(comm); errs += verify_comm(comm); MPI_Comm_free(&comm); } } /* now tests that don't depend on the layout[][] array */ /* The MPI-2.2 standard recommends implementations set * MPI_UNWEIGHTED==NULL, but this leads to an ambiguity. The draft * MPI-3.0 standard specifically recommends _not_ setting it equal * to NULL. */ if (MPI_UNWEIGHTED == NULL) { fprintf(stderr, "MPI_UNWEIGHTED should not be NULL\n"); ++errs; } /* MPI_Dist_graph_create() with no graph */ if (rank == 0) { MTestPrintfMsg( 1, "testing MPI_Dist_graph_create w/ no graph\n" ); } for (reorder = 0; reorder <= 1; reorder++) { MPI_Dist_graph_create(MPI_COMM_WORLD, 0, sources, degrees, destinations, sweights, MPI_INFO_NULL, reorder, &comm); MPI_Dist_graph_neighbors_count(comm, &check_indegree, &check_outdegree, &check_weighted); if (!check_weighted) { fprintf(stderr, "expected weighted == TRUE for the \"no graph\" case\n"); ++errs; } MPI_Comm_free(&comm); } /* MPI_Dist_graph_create() with no graph -- passing MPI_WEIGHTS_EMPTY instead */ /* NOTE that MPI_WEIGHTS_EMPTY was added in MPI-3 and does not appear before then. This part of the test thus requires a check on the MPI major version */ #if MPI_VERSION >= 3 if (rank == 0) { MTestPrintfMsg( 1, "testing MPI_Dist_graph_create w/ no graph\n" ); } for (reorder = 0; reorder <= 1; reorder++) { MPI_Dist_graph_create(MPI_COMM_WORLD, 0, sources, degrees, destinations, MPI_WEIGHTS_EMPTY, MPI_INFO_NULL, reorder, &comm); MPI_Dist_graph_neighbors_count(comm, &check_indegree, &check_outdegree, &check_weighted); if (!check_weighted) { fprintf(stderr, "expected weighted == TRUE for the \"no graph -- MPI_WEIGHTS_EMPTY\" case\n"); ++errs; } MPI_Comm_free(&comm); } #endif /* MPI_Dist_graph_create() with no graph -- passing NULLs instead */ if (rank == 0) { MTestPrintfMsg( 1, "testing MPI_Dist_graph_create w/ no graph -- NULLs\n" ); } for (reorder = 0; reorder <= 1; reorder++) { MPI_Dist_graph_create(MPI_COMM_WORLD, 0, NULL, NULL, NULL, NULL, MPI_INFO_NULL, reorder, &comm); MPI_Dist_graph_neighbors_count(comm, &check_indegree, &check_outdegree, &check_weighted); /* ambiguous if they are equal, only check when they are distinct values. */ if (MPI_UNWEIGHTED != NULL) { if (!check_weighted) { fprintf(stderr, "expected weighted == TRUE for the \"no graph -- NULLs\" case\n"); ++errs; } } MPI_Comm_free(&comm); } /* MPI_Dist_graph_create() with no graph -- passing NULLs+MPI_UNWEIGHTED instead */ if (rank == 0) { MTestPrintfMsg( 1, "testing MPI_Dist_graph_create w/ no graph -- NULLs+MPI_UNWEIGHTED\n" ); } for (reorder = 0; reorder <= 1; reorder++) { MPI_Dist_graph_create(MPI_COMM_WORLD, 0, NULL, NULL, NULL, MPI_UNWEIGHTED, MPI_INFO_NULL, reorder, &comm); MPI_Dist_graph_neighbors_count(comm, &check_indegree, &check_outdegree, &check_weighted); /* ambiguous if they are equal, only check when they are distinct values. */ if (MPI_UNWEIGHTED != NULL) { if (check_weighted) { fprintf(stderr, "expected weighted == FALSE for the \"no graph -- NULLs+MPI_UNWEIGHTED\" case\n"); ++errs; } } MPI_Comm_free(&comm); } /* MPI_Dist_graph_create_adjacent() with no graph */ if (rank == 0) { MTestPrintfMsg( 1, "testing MPI_Dist_graph_create_adjacent w/ no graph\n" ); } for (reorder = 0; reorder <= 1; reorder++) { MPI_Dist_graph_create_adjacent(MPI_COMM_WORLD, 0, sources, sweights, 0, destinations, dweights, MPI_INFO_NULL, reorder, &comm); MPI_Dist_graph_neighbors_count(comm, &check_indegree, &check_outdegree, &check_weighted); if (!check_weighted) { fprintf(stderr, "expected weighted == TRUE for the \"no graph\" case\n"); ++errs; } MPI_Comm_free(&comm); } /* MPI_Dist_graph_create_adjacent() with no graph -- passing MPI_WEIGHTS_EMPTY instead */ /* NOTE that MPI_WEIGHTS_EMPTY was added in MPI-3 and does not appear before then. This part of the test thus requires a check on the MPI major version */ #if MPI_VERSION >= 3 if (rank == 0) { MTestPrintfMsg( 1, "testing MPI_Dist_graph_create_adjacent w/ no graph -- MPI_WEIGHTS_EMPTY\n" ); } for (reorder = 0; reorder <= 1; reorder++) { MPI_Dist_graph_create_adjacent(MPI_COMM_WORLD, 0, sources, MPI_WEIGHTS_EMPTY, 0, destinations, MPI_WEIGHTS_EMPTY, MPI_INFO_NULL, reorder, &comm); MPI_Dist_graph_neighbors_count(comm, &check_indegree, &check_outdegree, &check_weighted); if (!check_weighted) { fprintf(stderr, "expected weighted == TRUE for the \"no graph -- MPI_WEIGHTS_EMPTY\" case\n"); ++errs; } MPI_Comm_free(&comm); } #endif /* MPI_Dist_graph_create_adjacent() with no graph -- passing NULLs instead */ if (rank == 0) { MTestPrintfMsg( 1, "testing MPI_Dist_graph_create_adjacent w/ no graph -- NULLs\n" ); } for (reorder = 0; reorder <= 1; reorder++) { MPI_Dist_graph_create_adjacent(MPI_COMM_WORLD, 0, NULL, NULL, 0, NULL, NULL, MPI_INFO_NULL, reorder, &comm); MPI_Dist_graph_neighbors_count(comm, &check_indegree, &check_outdegree, &check_weighted); /* ambiguous if they are equal, only check when they are distinct values. */ if (MPI_UNWEIGHTED != NULL) { if (!check_weighted) { fprintf(stderr, "expected weighted == TRUE for the \"no graph -- NULLs\" case\n"); ++errs; } } MPI_Comm_free(&comm); } /* MPI_Dist_graph_create_adjacent() with no graph -- passing NULLs+MPI_UNWEIGHTED instead */ if (rank == 0) { MTestPrintfMsg( 1, "testing MPI_Dist_graph_create_adjacent w/ no graph -- NULLs+MPI_UNWEIGHTED\n"); } for (reorder = 0; reorder <= 1; reorder++) { MPI_Dist_graph_create_adjacent(MPI_COMM_WORLD, 0, NULL, MPI_UNWEIGHTED, 0, NULL, MPI_UNWEIGHTED, MPI_INFO_NULL, reorder, &comm); MPI_Dist_graph_neighbors_count(comm, &check_indegree, &check_outdegree, &check_weighted); /* ambiguous if they are equal, only check when they are distinct values. */ if (MPI_UNWEIGHTED != NULL) { if (check_weighted) { fprintf(stderr, "expected weighted == FALSE for the \"no graph -- NULLs+MPI_UNWEIGHTED\" case\n"); ++errs; } } MPI_Comm_free(&comm); } for (i = 0; i < size; i++) free(layout[i]); free(layout); #endif MTest_Finalize(errs); MPI_Finalize(); return 0; }