int NBC_Comm_neighbors(MPI_Comm comm, int maxindegree, int sources[], int sourceweights[], int maxoutdegree, int destinations[], int destweights[]) { int topo, res; int index = 0; int indeg, outdeg, wgtd; res = NBC_Comm_neighbors_count(comm, &indeg, &outdeg, &wgtd); if(indeg > maxindegree && outdeg > maxoutdegree) return NBC_INVALID_PARAM; /* we want to return *all* neighbors */ 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, i, rpeer, speer; res = MPI_Cartdim_get(comm, &ndims); if (MPI_SUCCESS != res) { printf("MPI Error in MPI_Cartdim_get() (%i)\n", res); return res; } for(i = 0; i<ndims; i++) { res = MPI_Cart_shift(comm, i, 1, &rpeer, &speer); if (MPI_SUCCESS != res) { printf("MPI Error in MPI_Cart_shift() (%i)\n", res); return res; } sources[index] = destinations[index] = rpeer; index++; sources[index] = destinations[index] = speer; index++; } } break; case MPI_GRAPH: /* graph */ { int rank; MPI_Comm_rank(comm, &rank); res = MPI_Graph_neighbors(comm, rank, maxindegree, sources); if (MPI_SUCCESS != res) { printf("MPI Error in MPI_Graph_neighbors_count() (%i)\n", res); return res; } for(int i=0; i<maxindegree; i++) destinations[i] = sources[i]; } break; case MPI_DIST_GRAPH: /* dist graph */ { res = MPI_Dist_graph_neighbors(comm, maxindegree, sources, sourceweights, maxoutdegree, destinations, destweights); if (MPI_SUCCESS != res) { printf("MPI Error in MPI_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; }
int ompi_coll_libnbc_ineighbor_allgatherv(void *sbuf, int scount, MPI_Datatype stype, void *rbuf, int *rcounts, int *displs, MPI_Datatype rtype, struct ompi_communicator_t *comm, ompi_request_t ** request, struct mca_coll_base_module_2_1_0_t *module) { int rank, size, res, worldsize; MPI_Aint sndext, rcvext; NBC_Handle *handle; ompi_coll_libnbc_request_t **coll_req = (ompi_coll_libnbc_request_t**) request; ompi_coll_libnbc_module_t *libnbc_module = (ompi_coll_libnbc_module_t*) module; res = NBC_Init_handle(comm, coll_req, libnbc_module); handle = *coll_req; if(res != NBC_OK) { printf("Error in NBC_Init_handle(%i)\n", res); return res; } res = MPI_Comm_size(comm, &size); if (MPI_SUCCESS != res) { printf("MPI Error in MPI_Comm_size() (%i)\n", res); return res; } res = MPI_Comm_size(MPI_COMM_WORLD, &worldsize); if (MPI_SUCCESS != res) { printf("MPI Error in MPI_Comm_size() (%i)\n", res); return res; } res = MPI_Comm_rank(comm, &rank); if (MPI_SUCCESS != res) { printf("MPI Error in MPI_Comm_rank() (%i)\n", res); return res; } res = MPI_Type_extent(stype, &sndext); if (MPI_SUCCESS != res) { printf("MPI Error in MPI_Type_extent() (%i)\n", res); return res; } res = MPI_Type_extent(rtype, &rcvext); if (MPI_SUCCESS != res) { printf("MPI Error in MPI_Type_extent() (%i)\n", res); return res; } char inplace; NBC_Schedule *schedule; #ifdef NBC_CACHE_SCHEDULE NBC_Ineighbor_allgatherv_args *args, *found, search; #endif NBC_IN_PLACE(sbuf, rbuf, inplace); handle->tmpbuf=NULL; #ifdef NBC_CACHE_SCHEDULE /* search schedule in communicator specific tree */ search.sbuf=sbuf; search.scount=scount; search.stype=stype; search.rbuf=rbuf; search.rcount=rcount; search.rtype=rtype; found = (NBC_Ineighbor_allgatherv_args*)hb_tree_search((hb_tree*)handle->comminfo->NBC_Dict[NBC_NEIGHBOR_ALLGATHERV], &search); if(found == NULL) { #endif schedule = (NBC_Schedule*)malloc(sizeof(NBC_Schedule)); res = NBC_Sched_create(schedule); if(res != NBC_OK) { printf("Error in NBC_Sched_create, res = %i\n", res); return res; } { int indegree, outdegree, weighted, *srcs, *dsts, i; res = NBC_Comm_neighbors_count(comm, &indegree, &outdegree, &weighted); if(res != NBC_OK) return res; srcs = (int*)malloc(sizeof(int)*indegree); dsts = (int*)malloc(sizeof(int)*outdegree); res = NBC_Comm_neighbors(comm, indegree, srcs, MPI_UNWEIGHTED, outdegree, dsts, MPI_UNWEIGHTED); if(res != NBC_OK) return res; if(inplace) { /* we need an extra buffer to be deadlock-free */ int sumrcounts=0; int offset=0; for(i=0; i<indegree; ++i) sumrcounts += rcounts[i]; handle->tmpbuf = malloc(rcvext*sumrcounts); for(i = 0; i < indegree; i++) { if(srcs[i] != MPI_PROC_NULL) { res = NBC_Sched_recv((char*)0+offset, true, rcounts[i], rtype, srcs[i], schedule); if (NBC_OK != res) { printf("Error in NBC_Sched_recv() (%i)\n", res); return res; } } offset += rcounts[i]*rcvext; } for(i = 0; i < outdegree; i++) { if(dsts[i] != MPI_PROC_NULL) { res = NBC_Sched_send((char*)sbuf, false, scount, stype, dsts[i], schedule); if (NBC_OK != res) { printf("Error in NBC_Sched_send() (%i)\n", res); return res; } } } /* unpack from buffer */ offset=0; for(i = 0; i < indegree; i++) { if(srcs[i] != MPI_PROC_NULL) { res = NBC_Sched_barrier(schedule); if (NBC_OK != res) { printf("Error in NBC_Sched_barrier() (%i)\n", res); return res; } res = NBC_Sched_copy((char*)0+offset, true, rcounts[i], rtype, (char*)rbuf+displs[i]*rcvext, false, rcounts[i], rtype, schedule); if (NBC_OK != res) { printf("Error in NBC_Sched_copy() (%i)\n", res); return res; } } offset += rcounts[i]*rcvext; } } else { /* non INPLACE case */ /* simply loop over neighbors and post send/recv operations */ for(i = 0; i < indegree; i++) { if(srcs[i] != MPI_PROC_NULL) { res = NBC_Sched_recv((char*)rbuf+displs[i]*rcvext, false, rcounts[i], rtype, srcs[i], schedule); if (NBC_OK != res) { printf("Error in NBC_Sched_recv() (%i)\n", res); return res; } } } for(i = 0; i < outdegree; i++) { if(dsts[i] != MPI_PROC_NULL) { res = NBC_Sched_send((char*)sbuf, false, scount, stype, dsts[i], schedule); if (NBC_OK != res) { printf("Error in NBC_Sched_send() (%i)\n", res); return res; } } } } } res = NBC_Sched_commit(schedule); if (NBC_OK != res) { printf("Error in NBC_Sched_commit() (%i)\n", res); return res; } #ifdef NBC_CACHE_SCHEDULE /* save schedule to tree */ args = (NBC_Ineighbor_allgatherv_args*)malloc(sizeof(NBC_Ineighbor_allgatherv_args)); args->sbuf=sbuf; args->scount=scount; args->stype=stype; args->rbuf=rbuf; args->rcount=rcount; args->rtype=rtype; args->schedule=schedule; res = hb_tree_insert ((hb_tree*)handle->comminfo->NBC_Dict[NBC_NEIGHBOR_ALLGATHERV], args, args, 0); if(res != 0) printf("error in dict_insert() (%i)\n", res); /* increase number of elements for A2A */ if(++handle->comminfo->NBC_Dict_size[NBC_NEIGHBOR_ALLGATHERV] > NBC_SCHED_DICT_UPPER) { NBC_SchedCache_dictwipe((hb_tree*)handle->comminfo->NBC_Dict[NBC_NEIGHBOR_ALLGATHERV], &handle->comminfo->NBC_Dict_size[NBC_NEIGHBOR_ALLGATHERV]); } } else { /* found schedule */ schedule=found->schedule; } #endif res = NBC_Start(handle, schedule); if (NBC_OK != res) { printf("Error in NBC_Start() (%i)\n", res); return res; } return NBC_OK; }
int NBC_Ineighbor_alltoallw(void *sbuf, int *scounts, MPI_Datatype *stypes, void *rbuf, int *rcounts, MPI_Datatype *rtypes, MPI_Comm comm, NBC_Handle* handle) { int rank, size, res, worldsize, i; MPI_Aint *sndexts, *rcvexts; double t[10]; t[0] = PMPI_Wtime(); res = NBC_Init_handle(handle, comm); if(res != NBC_OK) { printf("Error in NBC_Init_handle(%i)\n", res); return res; } res = MPI_Comm_size(comm, &size); if (MPI_SUCCESS != res) { printf("MPI Error in MPI_Comm_size() (%i)\n", res); return res; } res = MPI_Comm_size(MPI_COMM_WORLD, &worldsize); if (MPI_SUCCESS != res) { printf("MPI Error in MPI_Comm_size() (%i)\n", res); return res; } res = MPI_Comm_rank(comm, &rank); if (MPI_SUCCESS != res) { printf("MPI Error in MPI_Comm_rank() (%i)\n", res); return res; } t[1] = PMPI_Wtime(); char inplace; NBC_Schedule *schedule; #ifdef NBC_CACHE_SCHEDULE NBC_Ineighbor_alltoallw_args *args, *found, search; #endif NBC_IN_PLACE(sbuf, rbuf, inplace); handle->tmpbuf=NULL; #ifdef NBC_CACHE_SCHEDULE /* search schedule in communicator specific tree */ search.sbuf=sbuf; search.scount=scount; search.stype=stype; search.rbuf=rbuf; search.rcount=rcount; search.rtype=rtype; found = (NBC_Ineighbor_alltoallw_args*)hb_tree_search((hb_tree*)handle->comminfo->NBC_Dict[NBC_NEIGHBOR_ALLTOALLW], &search); if(found == NULL) { #endif schedule = (NBC_Schedule*)malloc(sizeof(NBC_Schedule)); res = NBC_Sched_create(schedule); if(res != NBC_OK) { printf("Error in NBC_Sched_create, res = %i\n", res); return res; } { int indegree, outdegree, weighted, *srcs, *dsts, i; res = NBC_Comm_neighbors_count(comm, &indegree, &outdegree, &weighted); if(res != NBC_OK) return res; srcs = (int*)malloc(sizeof(int)*indegree); dsts = (int*)malloc(sizeof(int)*outdegree); sndexts = (MPI_Aint*)malloc(sizeof(MPI_Aint)*outdegree); for(i=0; i<outdegree; ++i) { res = MPI_Type_extent(stypes[i], &sndexts[i]); if (MPI_SUCCESS != res) { printf("MPI Error in MPI_Type_extent() (%i)\n", res); return res; } } rcvexts = (MPI_Aint*)malloc(sizeof(MPI_Aint)*indegree); for(i=0; i<indegree; ++i) { res = MPI_Type_extent(rtypes[i], &rcvexts[i]); if (MPI_SUCCESS != res) { printf("MPI Error in MPI_Type_extent() (%i)\n", res); return res; } } res = NBC_Comm_neighbors(comm, indegree, srcs, MPI_UNWEIGHTED, outdegree, dsts, MPI_UNWEIGHTED); if(res != NBC_OK) return res; if(inplace) { /* we need an extra buffer to be deadlock-free */ int sumrbytes=0; int offset=0; for(i=0; i<indegree; ++i) sumrbytes += rcounts[i]*rcvexts[i]; handle->tmpbuf = malloc(sumrbytes); for(i = 0; i < indegree; i++) { res = NBC_Sched_recv((char*)0+offset, true, rcounts[i], rtypes[i], srcs[i], schedule); if (NBC_OK != res) { printf("Error in NBC_Sched_recv() (%i)\n", res); return res; } offset += rcounts[i]*rcvexts[i]; } offset=0; for(i = 0; i < outdegree; i++) { res = NBC_Sched_send((char*)sbuf+offset, false, scounts[i], stypes[i], dsts[i], schedule); if (NBC_OK != res) { printf("Error in NBC_Sched_send() (%i)\n", res); return res; } offset += scounts[i]*sndexts[i]; } /* unpack from buffer */ offset=0; for(i = 0; i < indegree; i++) { res = NBC_Sched_barrier(schedule); if (NBC_OK != res) { printf("Error in NBC_Sched_barrier() (%i)\n", res); return res; } res = NBC_Sched_copy((char*)0+offset, true, rcounts[i], rtypes[i], (char*)rbuf+offset, false, rcounts[i], rtypes[i], schedule); if (NBC_OK != res) { printf("Error in NBC_Sched_copy() (%i)\n", res); return res; } offset += rcounts[i]*rcvexts[i]; } } else { /* non INPLACE case */ /* simply loop over neighbors and post send/recv operations */ int offset=0; for(i = 0; i < indegree; i++) { res = NBC_Sched_recv((char*)rbuf+offset, false, rcounts[i], rtypes[i], srcs[i], schedule); if (NBC_OK != res) { printf("Error in NBC_Sched_recv() (%i)\n", res); return res; } offset += rcounts[i]*rcvexts[i]; } offset = 0; for(i = 0; i < outdegree; i++) { res = NBC_Sched_send((char*)sbuf+offset, false, scounts[i], stypes[i], dsts[i], schedule); if (NBC_OK != res) { printf("Error in NBC_Sched_send() (%i)\n", res); return res; } offset += scounts[i]*sndexts[i]; } } } res = NBC_Sched_commit(schedule); if (NBC_OK != res) { printf("Error in NBC_Sched_commit() (%i)\n", res); return res; } #ifdef NBC_CACHE_SCHEDULE /* save schedule to tree */ args = (NBC_Ineighbor_alltoallw_args*)malloc(sizeof(NBC_Ineighbor_alltoallw_args)); args->sbuf=sbuf; args->scount=scount; args->stype=stype; args->rbuf=rbuf; args->rcount=rcount; args->rtype=rtype; args->schedule=schedule; res = hb_tree_insert ((hb_tree*)handle->comminfo->NBC_Dict[NBC_NEIGHBOR_ALLTOALLW], args, args, 0); if(res != 0) printf("error in dict_insert() (%i)\n", res); /* increase number of elements for A2A */ if(++handle->comminfo->NBC_Dict_size[NBC_NEIGHBOR_ALLTOALLW] > NBC_SCHED_DICT_UPPER) { NBC_SchedCache_dictwipe((hb_tree*)handle->comminfo->NBC_Dict[NBC_NEIGHBOR_ALLTOALLW], &handle->comminfo->NBC_Dict_size[NBC_NEIGHBOR_ALLTOALLW]); } } else { /* found schedule */ schedule=found->schedule; } #endif res = NBC_Start(handle, schedule); if (NBC_OK != res) { printf("Error in NBC_Start() (%i)\n", res); return res; } return NBC_OK; }
int NBC_Comm_neighbors (ompi_communicator_t *comm, int **sources, int *source_count, int **destinations, int *dest_count) { int res, indeg, outdeg; *sources = *destinations = NULL; res = NBC_Comm_neighbors_count(comm, &indeg, &outdeg); if (OMPI_SUCCESS != res) { return res; } *source_count = indeg; *dest_count = outdeg; if (indeg) { *sources = malloc (sizeof (int) * indeg); if (OPAL_UNLIKELY(NULL == *sources)) { return OMPI_ERR_OUT_OF_RESOURCE; } } else { *sources = NULL; } if (outdeg) { *destinations = malloc (sizeof (int) * outdeg); if (OPAL_UNLIKELY(NULL == *destinations)) { free (*sources); *sources = NULL; return OMPI_ERR_OUT_OF_RESOURCE; } } else { *destinations = NULL; } /* silence clang static analyzer warning about NULL-dereference */ if (0 == indeg && 0 == outdeg) { return OMPI_SUCCESS; } if (OMPI_COMM_IS_CART(comm)) { /* cartesian */ int rpeer, speer; /* silence clang static analyzer warning */ assert (indeg == outdeg); for (int dim = 0, i = 0 ; dim < comm->c_topo->mtc.cart->ndims ; ++dim) { mca_topo_base_cart_shift (comm, dim, 1, &rpeer, &speer); sources[0][i] = destinations[0][i] = rpeer; i++; sources[0][i] = destinations[0][i] = speer; i++; } } else if (OMPI_COMM_IS_GRAPH(comm)) { /* graph */ mca_topo_base_graph_neighbors (comm, ompi_comm_rank (comm), indeg, sources[0]); memcpy (destinations[0], sources[0], indeg * sizeof (int)); } else if (OMPI_COMM_IS_DIST_GRAPH(comm)) { /* dist graph */ mca_topo_base_dist_graph_neighbors (comm, indeg, sources[0], MPI_UNWEIGHTED, outdeg, destinations[0], MPI_UNWEIGHTED); } return OMPI_SUCCESS; }