/* * Copyright 1997, Regents of the University of Minnesota * * mmove.c * * This file contains functions that move the graph given a partition * * Started 11/22/96 * George * * $Id: move.c 10657 2011-08-03 14:34:35Z karypis $ * */ #include /*************************************************************************/ /*! This function moves the graph, and returns a new graph. This routine can be called with or without performing refinement. In the latter case it allocates and computes lpwgts itself. */ /*************************************************************************/ graph_t *MoveGraph(ctrl_t *ctrl, graph_t *graph) { idx_t h, i, ii, j, jj, nvtxs, ncon, npes, nsnbrs, nrnbrs; idx_t *xadj, *vwgt, *adjncy, *adjwgt, *mvtxdist; idx_t *where, *newlabel, *lpwgts, *gpwgts; idx_t *sgraph, *rgraph; ikv_t *sinfo, *rinfo; graph_t *mgraph; WCOREPUSH; /* this routine only works when nparts <= npes */ PASSERT(ctrl, ctrl->nparts <= ctrl->npes); npes = ctrl->npes; nvtxs = graph->nvtxs; ncon = graph->ncon; xadj = graph->xadj; vwgt = graph->vwgt; adjncy = graph->adjncy; adjwgt = graph->adjwgt; where = graph->where; mvtxdist = imalloc(npes+1, "MoveGraph: mvtxdist"); /* Let's do a prefix scan to determine the labeling of the nodes given */ lpwgts = iwspacemalloc(ctrl, npes+1); gpwgts = iwspacemalloc(ctrl, npes+1); sinfo = ikvwspacemalloc(ctrl, npes); rinfo = ikvwspacemalloc(ctrl, npes); for (i=0; icomm); gkMPI_Allreduce((void *)lpwgts, (void *)mvtxdist, npes, IDX_T, MPI_SUM, ctrl->comm); MAKECSR(i, npes, mvtxdist); /* gpwgts[i] will store the label of the first vertex for each domain in each processor */ for (i=0; inrecv); for (i=0; icomm); /* Use lpwgts and gpwgts as pointers to where data will be received and send */ lpwgts[0] = 0; /* Send part */ gpwgts[0] = 0; /* Received part */ for (nsnbrs=nrnbrs=0, i=0; i 0) nrnbrs++; if (sinfo[i].key > 0) nsnbrs++; } /* Update the max # of sreq/rreq/statuses */ CommUpdateNnbrs(ctrl, gk_max(nsnbrs, nrnbrs)); rgraph = iwspacemalloc(ctrl, gpwgts[npes]); WCOREPUSH; /* for freeing the send part early */ sgraph = iwspacemalloc(ctrl, lpwgts[npes]); /* Issue the receives first */ for (j=0, i=0; i 0) gkMPI_Irecv((void *)(rgraph+gpwgts[i]), gpwgts[i+1]-gpwgts[i], IDX_T, i, 1, ctrl->comm, ctrl->rreq+j++); else PASSERT(ctrl, gpwgts[i+1]-gpwgts[i] == 0); } /* Assemble the graph to be sent and send it */ for (i=0; i= 0 && where[i] < npes); ii = lpwgts[where[i]]; sgraph[ii++] = xadj[i+1]-xadj[i]; for (h=0; h 0) gkMPI_Isend((void *)(sgraph+lpwgts[i]), lpwgts[i+1]-lpwgts[i], IDX_T, i, 1, ctrl->comm, ctrl->sreq+j++); else PASSERT(ctrl, lpwgts[i+1]-lpwgts[i] == 0); } /* Wait for the send/recv to finish */ gkMPI_Waitall(nrnbrs, ctrl->rreq, ctrl->statuses); gkMPI_Waitall(nsnbrs, ctrl->sreq, ctrl->statuses); WCOREPOP; /* frees sgraph */ /* OK, now go and put the graph into graph_t Format */ mgraph = CreateGraph(); mgraph->vtxdist = mvtxdist; mgraph->gnvtxs = graph->gnvtxs; mgraph->ncon = ncon; mgraph->level = 0; mgraph->nvtxs = mgraph->nedges = 0; for (i=0; invtxs += rinfo[i].key; mgraph->nedges += rinfo[i].val; } nvtxs = mgraph->nvtxs; xadj = mgraph->xadj = imalloc(nvtxs+1, "MMG: mgraph->xadj"); vwgt = mgraph->vwgt = imalloc(nvtxs*ncon, "MMG: mgraph->vwgt"); adjncy = mgraph->adjncy = imalloc(mgraph->nedges, "MMG: mgraph->adjncy"); adjwgt = mgraph->adjwgt = imalloc(mgraph->nedges, "MMG: mgraph->adjwgt"); for (jj=ii=i=0; inedges); PASSERT(ctrl, ii == gpwgts[npes]); PASSERTP(ctrl, jj == mgraph->nedges, (ctrl, "%"PRIDX" %"PRIDX"\n", jj, mgraph->nedges)); PASSERTP(ctrl, ii == gpwgts[npes], (ctrl, "%"PRIDX" %"PRIDX" %"PRIDX" %"PRIDX" %"PRIDX"\n", ii, gpwgts[npes], jj, mgraph->nedges, nvtxs)); #ifdef DEBUG IFSET(ctrl->dbglvl, DBG_INFO, rprintf(ctrl, "Checking moved graph...\n")); CheckMGraph(ctrl, mgraph); IFSET(ctrl->dbglvl, DBG_INFO, rprintf(ctrl, "Moved graph is consistent.\n")); #endif WCOREPOP; return mgraph; } /************************************************************************* * This function is used to transfer information from the moved graph * back to the original graph. The information is transfered from array * minfo to array info. The routine assumes that graph->where is left intact * and it is used to get the inverse mapping information. * The routine assumes that graph->where corresponds to a npes-way partition. **************************************************************************/ void ProjectInfoBack(ctrl_t *ctrl, graph_t *graph, idx_t *info, idx_t *minfo) { idx_t i, nvtxs, nparts, nrecvs, nsends; idx_t *where, *auxinfo, *sinfo, *rinfo; WCOREPUSH; nparts = ctrl->npes; nvtxs = graph->nvtxs; where = graph->where; sinfo = iwspacemalloc(ctrl, nparts+1); rinfo = iwspacemalloc(ctrl, nparts+1); /* Find out in rinfo how many entries are received per partition */ iset(nparts, 0, rinfo); for (i=0; icomm); MAKECSR(i, nparts, sinfo); MAKECSR(i, nparts, rinfo); /* allocate memory for auxinfo */ auxinfo = iwspacemalloc(ctrl, rinfo[nparts]); /*----------------------------------------------------------------- * Now, go and send back the minfo -----------------------------------------------------------------*/ for (nrecvs=0, i=0; i 0) gkMPI_Irecv((void *)(auxinfo+rinfo[i]), rinfo[i+1]-rinfo[i], IDX_T, i, 1, ctrl->comm, ctrl->rreq+nrecvs++); } for (nsends=0, i=0; i 0) gkMPI_Isend((void *)(minfo+sinfo[i]), sinfo[i+1]-sinfo[i], IDX_T, i, 1, ctrl->comm, ctrl->sreq+nsends++); } PASSERT(ctrl, nrecvs <= ctrl->ncommpes); PASSERT(ctrl, nsends <= ctrl->ncommpes); /* Wait for the send/recv to finish */ gkMPI_Waitall(nrecvs, ctrl->rreq, ctrl->statuses); gkMPI_Waitall(nsends, ctrl->sreq, ctrl->statuses); /* Scatter the info received in auxinfo back to info. */ for (i=0; inparts; nvtxs = graph->nvtxs; xadj = graph->xadj; adjncy = graph->adjncy; adjwgt = graph->adjwgt; where = graph->where; mvtxdist = iwspacemalloc(ctrl, nparts+1); lpwgts = iwspacemalloc(ctrl, nparts+1); gpwgts = iwspacemalloc(ctrl, nparts+1); /* Here we care about the count and not total weight (diff since graph may be weighted */ iset(nparts, 0, lpwgts); for (i=0; icomm); gkMPI_Allreduce((void *)lpwgts, (void *)mvtxdist, nparts, IDX_T, MPI_SUM, ctrl->comm); MAKECSR(i, nparts, mvtxdist); for (i=0; invtxs; xadj = graph->xadj; adjncy = graph->adjncy; vtxdist = graph->vtxdist; firstvtx = vtxdist[ctrl->mype]; lastvtx = vtxdist[ctrl->mype+1]; for (i=0; i= firstvtx && adjncy[j] < lastvtx) { k = adjncy[j]-firstvtx; for (jj=xadj[k]; jj