diff options
Diffstat (limited to 'benchmarks/CUDA/DG/3rdParty/ParMetis-3.1/ParMETISLib/move.c')
| -rw-r--r-- | benchmarks/CUDA/DG/3rdParty/ParMetis-3.1/ParMETISLib/move.c | 338 |
1 files changed, 338 insertions, 0 deletions
diff --git a/benchmarks/CUDA/DG/3rdParty/ParMetis-3.1/ParMETISLib/move.c b/benchmarks/CUDA/DG/3rdParty/ParMetis-3.1/ParMETISLib/move.c new file mode 100644 index 0000000..06a8e5c --- /dev/null +++ b/benchmarks/CUDA/DG/3rdParty/ParMetis-3.1/ParMETISLib/move.c @@ -0,0 +1,338 @@ +/* + * 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 <parmetislib.h> + +/************************************************************************* +* 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; i<nparts; i++) + sinfo[i].key = sinfo[i].val = 0; + + for (i=0; i<nvtxs; i++) { + sinfo[where[i]].key++; + sinfo[where[i]].val += xadj[i+1]-xadj[i]; + } + for (i=0; i<nparts; i++) + lpwgts[i] = sinfo[i].key; + + MPI_Scan((void *)lpwgts, (void *)gpwgts, nparts, IDX_DATATYPE, MPI_SUM, ctrl->comm); + 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; i<nparts; i++) + /* We were interested in an exclusive Scan */ + gpwgts[i] = mvtxdist[i] + gpwgts[i] - lpwgts[i]; + + newlabel = idxmalloc(nvtxs+graph->nrecv, "MoveGraph: newlabel"); + + for (i=0; i<nvtxs; i++) + newlabel[i] = gpwgts[where[i]]++; + + /* OK, now send the newlabel info to processors storing adjacent interface nodes */ + CommInterfaceData(ctrl, graph, newlabel, wspace->indices, 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<nparts; i++) { + lpwgts[i+1] = lpwgts[i] + (1+ncon)*sinfo[i].key + 2*sinfo[i].val; + gpwgts[i+1] = gpwgts[i] + (1+ncon)*rinfo[i].key + 2*rinfo[i].val; + } + + + if (lpwgts[nparts]+gpwgts[nparts] > 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<nparts; i++) { + if (rinfo[i].key > 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; i<nvtxs; i++) { + ii = lpwgts[where[i]]; + sgraph[ii++] = xadj[i+1]-xadj[i]; + for (h=0; h<ncon; h++) + sgraph[ii++] = vwgt[i*ncon+h]; + for (j=xadj[i]; j<xadj[i+1]; j++) { + sgraph[ii++] = newlabel[adjncy[j]]; + sgraph[ii++] = adjwgt[j]; + } + lpwgts[where[i]] = ii; + } + + for (i=nparts; i>0; i--) + lpwgts[i] = lpwgts[i-1]; + lpwgts[0] = 0; + + for (i=0; i<nparts; i++) { + if (sinfo[i].key > 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<nparts; i++) { + if (sinfo[i].key > 0) + MPI_Wait(ctrl->sreq+i, &ctrl->status); + } + for (i=0; i<nparts; i++) { + if (rinfo[i].key > 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; i<nparts; i++) { + mgraph->nvtxs += 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; i<nvtxs; i++) { + xadj[i] = rgraph[ii++]; + for (h=0; h<ncon; h++) + vwgt[i*ncon+h] = rgraph[ii++]; + for (j=0; j<xadj[i]; j++) { + adjncy[jj] = rgraph[ii++]; + adjwgt[jj++] = rgraph[ii++]; + } + } + MAKECSR(i, nvtxs, xadj); + + ASSERTP(ctrl, jj == mgraph->nedges, (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; i<nvtxs; i++) + rinfo[where[i]]++; + + /* The rinfo are transposed and become the sinfo for the back-projection */ + MPI_Alltoall((void *)rinfo, 1, IDX_DATATYPE, (void *)sinfo, 1, IDX_DATATYPE, ctrl->comm); + + 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<nparts; i++) { + if (rinfo[i+1]-rinfo[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<nparts; i++) { + if (sinfo[i+1]-sinfo[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<nparts; i++) { + if (rinfo[i+1]-rinfo[i] > 0) + MPI_Wait(ctrl->rreq+i, &ctrl->status); + } + for (i=0; i<nparts; i++) { + if (sinfo[i+1]-sinfo[i] > 0) + MPI_Wait(ctrl->sreq+i, &ctrl->status); + } + + /* Scatter the info received in auxinfo back to info. */ + for (i=0; i<nvtxs; i++) + info[i] = auxinfo[rinfo[where[i]]++]; + + free(auxinfo); +} + + + +/************************************************************************* +* This function is used to convert a partition vector to a permutation +* vector. +**************************************************************************/ +void FindVtxPerm(CtrlType *ctrl, GraphType *graph, idxtype *perm, WorkSpaceType *wspace) +{ + int i, nvtxs, nparts; + idxtype *xadj, *adjncy, *adjwgt, *mvtxdist; + idxtype *where, *lpwgts, *gpwgts; + + nparts = ctrl->nparts; + + 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; i<nvtxs; i++) + lpwgts[where[i]]++; + + MPI_Scan((void *)lpwgts, (void *)gpwgts, nparts, IDX_DATATYPE, MPI_SUM, ctrl->comm); + MPI_Allreduce((void *)lpwgts, (void *)mvtxdist, nparts, IDX_DATATYPE, MPI_SUM, ctrl->comm); + + MAKECSR(i, nparts, mvtxdist); + + for (i=0; i<nparts; i++) + gpwgts[i] = mvtxdist[i] + gpwgts[i] - lpwgts[i]; /* We were interested in an exclusive Scan */ + + for (i=0; i<nvtxs; i++) + perm[i] = gpwgts[where[i]]++; + + free(mvtxdist); + +} + + + + +/************************************************************************* +* This function quickly performs a check on the consistency of moved graph. +**************************************************************************/ +void CheckMGraph(CtrlType *ctrl, GraphType *graph) +{ + int i, j, jj, k, nvtxs, firstvtx, lastvtx; + idxtype *xadj, *adjncy, *vtxdist; + + + nvtxs = graph->nvtxs; + xadj = graph->xadj; + adjncy = graph->adjncy; + vtxdist = graph->vtxdist; + + firstvtx = vtxdist[ctrl->mype]; + lastvtx = vtxdist[ctrl->mype+1]; + + for (i=0; i<nvtxs; i++) { + for (j=xadj[i]; j<xadj[i+1]; j++) { + ASSERT(ctrl, firstvtx+i != adjncy[j]); + if (adjncy[j] >= firstvtx && adjncy[j] < lastvtx) { + k = adjncy[j]-firstvtx; + for (jj=xadj[k]; jj<xadj[k+1]; jj++) { + if (adjncy[jj] == firstvtx+i) + break; + } + if (jj == xadj[k+1]) + myprintf(ctrl, "(%d %d) but not (%d %d)\n", firstvtx+i, k, k, firstvtx+i); + } + } + } +} + + + |
