/* * 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,v 1.3 2003/07/31 16:23:30 karypis Exp $ * */ #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. **************************************************************************/ GraphType *Moc_MoveGraph(CtrlType *ctrl, GraphType *graph, WorkSpaceType *wspace) { int h, i, ii, j, jj, nvtxs, ncon, nparts; idxtype *xadj, *vwgt, *adjncy, *adjwgt, *mvtxdist; idxtype *where, *newlabel, *lpwgts, *gpwgts; idxtype *sgraph, *rgraph; KeyValueType *sinfo, *rinfo; GraphType *mgraph; nparts = ctrl->nparts; ASSERT(ctrl, nparts == ctrl->npes); nvtxs = graph->nvtxs; ncon = graph->ncon; xadj = graph->xadj; vwgt = graph->vwgt; adjncy = graph->adjncy; adjwgt = graph->adjwgt; where = graph->where; mvtxdist = idxmalloc(nparts+1, "MoveGraph: mvtxdist"); /* Let's do a prefix scan to determine the labeling of the nodes given */ lpwgts = wspace->pv1; gpwgts = wspace->pv2; sinfo = wspace->pepairs1; rinfo = wspace->pepairs2; for (i=0; icomm); MPI_Allreduce((void *)lpwgts, (void *)mvtxdist, nparts, IDX_DATATYPE, MPI_SUM, ctrl->comm); MAKECSR(i, nparts, mvtxdist); /* gpwgts[i] will store the label of the first vertex for each domain in each processor */ for (i=0; inrecv, "MoveGraph: newlabel"); for (i=0; iindices, newlabel+nvtxs); /* Now lets tell everybody what and from where he will get it. Assume nparts == npes */ MPI_Alltoall((void *)sinfo, 2, IDX_DATATYPE, (void *)rinfo, 2, IDX_DATATYPE, ctrl->comm); /* 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 (i=0; i wspace->maxcore) { /* Adjust core memory, incase the graph was originally very memory unbalanced */ free(wspace->core); wspace->maxcore = lpwgts[nparts]+4*gpwgts[nparts]; /* In spirit of the 8*nedges */ wspace->core = idxmalloc(wspace->maxcore, "Moc_MoveGraph: wspace->core"); } sgraph = wspace->core; rgraph = wspace->core + lpwgts[nparts]; /* Issue the receives first */ for (i=0; i 0) MPI_Irecv((void *)(rgraph+gpwgts[i]), gpwgts[i+1]-gpwgts[i], IDX_DATATYPE, i, 1, ctrl->comm, ctrl->rreq+i); else ASSERT(ctrl, gpwgts[i+1]-gpwgts[i] == 0); } /* Assemble the graph to be sent and send it */ for (i=0; i0; i--) lpwgts[i] = lpwgts[i-1]; lpwgts[0] = 0; for (i=0; i 0) MPI_Isend((void *)(sgraph+lpwgts[i]), lpwgts[i+1]-lpwgts[i], IDX_DATATYPE, i, 1, ctrl->comm, ctrl->sreq+i); else ASSERT(ctrl, lpwgts[i+1]-lpwgts[i] == 0); } /* #ifdef DMALLOC ASSERT(ctrl, dmalloc_verify(NULL) == DMALLOC_VERIFY_NOERROR); #endif */ /* Wait for the send/recv to finish */ for (i=0; i 0) MPI_Wait(ctrl->sreq+i, &ctrl->status); } for (i=0; i 0) MPI_Wait(ctrl->rreq+i, &ctrl->status); } /* OK, now go and put the graph into GraphType Format */ mgraph = CreateGraph(); 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 = idxmalloc(nvtxs+1, "MMG: mgraph->xadj"); vwgt = mgraph->vwgt = idxmalloc(nvtxs*ncon, "MMG: mgraph->vwgt"); adjncy = mgraph->adjncy = idxmalloc(mgraph->nedges, "MMG: mgraph->adjncy"); adjwgt = mgraph->adjwgt = idxmalloc(mgraph->nedges, "MMG: mgraph->adjwgt"); mgraph->vtxdist = mvtxdist; for (jj=ii=i=0; inedges, (ctrl, "%d %d\n", jj, mgraph->nedges)); ASSERTP(ctrl, ii == gpwgts[nparts], (ctrl, "%d %d %d %d %d\n", ii, gpwgts[nparts], jj, mgraph->nedges, nvtxs)); free(newlabel); #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 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(CtrlType *ctrl, GraphType *graph, idxtype *info, idxtype *minfo, WorkSpaceType *wspace) { int i, nvtxs, nparts; idxtype *where, *auxinfo, *sinfo, *rinfo; nparts = ctrl->npes; nvtxs = graph->nvtxs; where = graph->where; sinfo = wspace->pv1; rinfo = wspace->pv2; /* Find out in rinfo how many entries are received per partition */ idxset(nparts, 0, rinfo); for (i=0; icomm); MAKECSR(i, nparts, sinfo); MAKECSR(i, nparts, rinfo); /* allocate memory for auxinfo */ auxinfo = idxmalloc(rinfo[nparts], "ProjectInfoBack: auxinfo"); /*----------------------------------------------------------------- * Now, go and send back the minfo -----------------------------------------------------------------*/ for (i=0; i 0) MPI_Irecv((void *)(auxinfo+rinfo[i]), rinfo[i+1]-rinfo[i], IDX_DATATYPE, i, 1, ctrl->comm, ctrl->rreq+i); } for (i=0; i 0) MPI_Isend((void *)(minfo+sinfo[i]), sinfo[i+1]-sinfo[i], IDX_DATATYPE, i, 1, ctrl->comm, ctrl->sreq+i); } /* Wait for the send/recv to finish */ for (i=0; i 0) MPI_Wait(ctrl->rreq+i, &ctrl->status); } for (i=0; i 0) MPI_Wait(ctrl->sreq+i, &ctrl->status); } /* 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 = idxmalloc(nparts+1, "MoveGraph: mvtxdist"); /* Let's do a prefix scan to determine the labeling of the nodes given */ lpwgts = wspace->pv1; gpwgts = wspace->pv2; /* Here we care about the count and not total weight (diff since graph may be weighted */ idxset(nparts, 0, lpwgts); for (i=0; icomm); MPI_Allreduce((void *)lpwgts, (void *)mvtxdist, nparts, IDX_DATATYPE, 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