diff options
| author | Tor Aamodt <[email protected]> | 2010-07-15 18:09:46 -0800 |
|---|---|---|
| committer | Tor Aamodt <[email protected]> | 2010-07-15 18:09:46 -0800 |
| commit | 69f2911e04ffb1b19eef1fafb8c040af271f656e (patch) | |
| tree | 231d3b6bdc3a202f7c255bfcf7bf2c36e32cee9e /benchmarks/CUDA/DG/3rdParty/ParMetis-3.1/METISLib/kwayvolrefine.c | |
creating branch for adding support for CUDA 3.x and Fermi
[git-p4: depot-paths = "//depot/gpgpu_sim_research/fermi/distribution/": change = 6829]
Diffstat (limited to 'benchmarks/CUDA/DG/3rdParty/ParMetis-3.1/METISLib/kwayvolrefine.c')
| -rw-r--r-- | benchmarks/CUDA/DG/3rdParty/ParMetis-3.1/METISLib/kwayvolrefine.c | 468 |
1 files changed, 468 insertions, 0 deletions
diff --git a/benchmarks/CUDA/DG/3rdParty/ParMetis-3.1/METISLib/kwayvolrefine.c b/benchmarks/CUDA/DG/3rdParty/ParMetis-3.1/METISLib/kwayvolrefine.c new file mode 100644 index 0000000..7cf248d --- /dev/null +++ b/benchmarks/CUDA/DG/3rdParty/ParMetis-3.1/METISLib/kwayvolrefine.c @@ -0,0 +1,468 @@ +/* + * Copyright 1997, Regents of the University of Minnesota + * + * kwayvolrefine.c + * + * This file contains the driving routines for multilevel k-way refinement + * + * Started 7/28/97 + * George + * + * $Id: kwayvolrefine.c,v 1.1 2003/07/16 15:55:05 karypis Exp $ + */ + +#include <metis.h> + + +/************************************************************************* +* This function is the entry point of refinement +**************************************************************************/ +void RefineVolKWay(CtrlType *ctrl, GraphType *orggraph, GraphType *graph, int nparts, + float *tpwgts, float ubfactor) +{ + int i, nlevels; + GraphType *ptr; + + IFSET(ctrl->dbglvl, DBG_TIME, starttimer(ctrl->UncoarsenTmr)); + + /* Take care any non-contiguity */ + IFSET(ctrl->dbglvl, DBG_TIME, starttimer(ctrl->AuxTmr1)); + if (ctrl->RType == RTYPE_KWAYRANDOM_MCONN) { + ComputeVolKWayPartitionParams(ctrl, graph, nparts); + EliminateVolComponents(ctrl, graph, nparts, tpwgts, 1.25); + EliminateVolSubDomainEdges(ctrl, graph, nparts, tpwgts); + EliminateVolComponents(ctrl, graph, nparts, tpwgts, 1.25); + } + IFSET(ctrl->dbglvl, DBG_TIME, stoptimer(ctrl->AuxTmr1)); + + + /* Determine how many levels are there */ + for (ptr=graph, nlevels=0; ptr!=orggraph; ptr=ptr->finer, nlevels++); + + /* Compute the parameters of the coarsest graph */ + ComputeVolKWayPartitionParams(ctrl, graph, nparts); + + for (i=0; ;i++) { + /*PrintSubDomainGraph(graph, nparts, graph->where);*/ + MALLOC_CHECK(NULL); + IFSET(ctrl->dbglvl, DBG_TIME, starttimer(ctrl->RefTmr)); + + if (2*i >= nlevels && !IsBalanced(graph->pwgts, nparts, tpwgts, 1.04*ubfactor)) { + ComputeVolKWayBalanceBoundary(ctrl, graph, nparts); + switch (ctrl->RType) { + case RTYPE_KWAYRANDOM: + Greedy_KWayVolBalance(ctrl, graph, nparts, tpwgts, ubfactor, 1); + break; + case RTYPE_KWAYRANDOM_MCONN: + Greedy_KWayVolBalanceMConn(ctrl, graph, nparts, tpwgts, ubfactor, 1); + break; + } + ComputeVolKWayBoundary(ctrl, graph, nparts); + } + + switch (ctrl->RType) { + case RTYPE_KWAYRANDOM: + Random_KWayVolRefine(ctrl, graph, nparts, tpwgts, ubfactor, 10, 1); + break; + case RTYPE_KWAYRANDOM_MCONN: + Random_KWayVolRefineMConn(ctrl, graph, nparts, tpwgts, ubfactor, 10, 1); + break; + } + IFSET(ctrl->dbglvl, DBG_TIME, stoptimer(ctrl->RefTmr)); + + if (graph == orggraph) + break; + + GKfree(&graph->gdata, LTERM); /* Deallocate the graph related arrays */ + + graph = graph->finer; + + IFSET(ctrl->dbglvl, DBG_TIME, starttimer(ctrl->ProjectTmr)); + ProjectVolKWayPartition(ctrl, graph, nparts); + IFSET(ctrl->dbglvl, DBG_TIME, stoptimer(ctrl->ProjectTmr)); + } + + if (!IsBalanced(graph->pwgts, nparts, tpwgts, ubfactor)) { + ComputeVolKWayBalanceBoundary(ctrl, graph, nparts); + switch (ctrl->RType) { + case RTYPE_KWAYRANDOM: + Greedy_KWayVolBalance(ctrl, graph, nparts, tpwgts, ubfactor, 8); + Random_KWayVolRefine(ctrl, graph, nparts, tpwgts, ubfactor, 10, 0); + break; + case RTYPE_KWAYRANDOM_MCONN: + Greedy_KWayVolBalanceMConn(ctrl, graph, nparts, tpwgts, ubfactor, 8); + Random_KWayVolRefineMConn(ctrl, graph, nparts, tpwgts, ubfactor, 10, 0); + break; + } + } + + EliminateVolComponents(ctrl, graph, nparts, tpwgts, ubfactor); + + IFSET(ctrl->dbglvl, DBG_TIME, stoptimer(ctrl->UncoarsenTmr)); +} + + + +/************************************************************************* +* This function allocates memory for k-way edge refinement +**************************************************************************/ +void AllocateVolKWayPartitionMemory(CtrlType *ctrl, GraphType *graph, int nparts) +{ + int nvtxs, pad64; + + nvtxs = graph->nvtxs; + + pad64 = (3*nvtxs+nparts)%2; + + graph->rdata = idxmalloc(3*nvtxs+nparts+(sizeof(VRInfoType)/sizeof(idxtype))*nvtxs+pad64, "AllocateVolKWayPartitionMemory: rdata"); + graph->pwgts = graph->rdata; + graph->where = graph->rdata + nparts; + graph->bndptr = graph->rdata + nvtxs + nparts; + graph->bndind = graph->rdata + 2*nvtxs + nparts; + graph->vrinfo = (VRInfoType *)(graph->rdata + 3*nvtxs+nparts + pad64); + +} + + + +/************************************************************************* +* This function computes the initial id/ed +**************************************************************************/ +void ComputeVolKWayPartitionParams(CtrlType *ctrl, GraphType *graph, int nparts) +{ + int i, ii, j, k, kk, l, nvtxs, nbnd, mincut, minvol, me, other, pid; + idxtype *xadj, *vwgt, *adjncy, *adjwgt, *pwgts, *where; + VRInfoType *rinfo, *myrinfo, *orinfo; + VEDegreeType *myedegrees, *oedegrees; + + nvtxs = graph->nvtxs; + xadj = graph->xadj; + vwgt = graph->vwgt; + adjncy = graph->adjncy; + adjwgt = graph->adjwgt; + + where = graph->where; + pwgts = idxset(nparts, 0, graph->pwgts); + rinfo = graph->vrinfo; + +starttimer(ctrl->AuxTmr1); + + /*------------------------------------------------------------ + / Compute now the id/ed degrees + /------------------------------------------------------------*/ + ctrl->wspace.cdegree = 0; + mincut = 0; + for (i=0; i<nvtxs; i++) { + me = where[i]; + pwgts[me] += vwgt[i]; + + myrinfo = rinfo+i; + myrinfo->id = myrinfo->ed = myrinfo->nid = myrinfo->ndegrees = 0; + myrinfo->edegrees = NULL; + + for (j=xadj[i]; j<xadj[i+1]; j++) { + if (me == where[adjncy[j]]) { + myrinfo->id += adjwgt[j]; + myrinfo->nid++; + } + } + myrinfo->ed = graph->adjwgtsum[i] - myrinfo->id; + + mincut += myrinfo->ed; + + /* Time to compute the particular external degrees */ + if (myrinfo->ed > 0) { + myedegrees = myrinfo->edegrees = ctrl->wspace.vedegrees+ctrl->wspace.cdegree; + ctrl->wspace.cdegree += xadj[i+1]-xadj[i]; + + for (j=xadj[i]; j<xadj[i+1]; j++) { + other = where[adjncy[j]]; + if (me != other) { + for (k=0; k<myrinfo->ndegrees; k++) { + if (myedegrees[k].pid == other) { + myedegrees[k].ed += adjwgt[j]; + myedegrees[k].ned++; + break; + } + } + if (k == myrinfo->ndegrees) { + myedegrees[myrinfo->ndegrees].gv = 0; + myedegrees[myrinfo->ndegrees].pid = other; + myedegrees[myrinfo->ndegrees].ed = adjwgt[j]; + myedegrees[myrinfo->ndegrees++].ned = 1; + } + } + } + + ASSERT(myrinfo->ndegrees <= xadj[i+1]-xadj[i]); + } + } + graph->mincut = mincut/2; + +stoptimer(ctrl->AuxTmr1); + + ComputeKWayVolGains(ctrl, graph, nparts); + +} + + + +/************************************************************************* +* This function computes the initial id/ed +**************************************************************************/ +void ComputeKWayVolGains(CtrlType *ctrl, GraphType *graph, int nparts) +{ + int i, ii, j, k, kk, l, nvtxs, me, other, pid, myndegrees; + idxtype *xadj, *vsize, *adjncy, *adjwgt, *where, *bndind, *bndptr, *ophtable; + VRInfoType *rinfo, *myrinfo, *orinfo; + VEDegreeType *myedegrees, *oedegrees; + + nvtxs = graph->nvtxs; + xadj = graph->xadj; + vsize = graph->vsize; + adjncy = graph->adjncy; + adjwgt = graph->adjwgt; + + where = graph->where; + bndind = graph->bndind; + bndptr = idxset(nvtxs, -1, graph->bndptr); + rinfo = graph->vrinfo; + +starttimer(ctrl->AuxTmr2); + + ophtable = idxset(nparts, -1, idxwspacemalloc(ctrl, nparts)); + + /*------------------------------------------------------------ + / Compute now the iv/ev degrees + /------------------------------------------------------------*/ + graph->minvol = graph->nbnd = 0; + for (i=0; i<nvtxs; i++) { + myrinfo = rinfo+i; + myrinfo->gv = -MAXIDX; + + if (myrinfo->ndegrees > 0) { + me = where[i]; + myedegrees = myrinfo->edegrees; + myndegrees = myrinfo->ndegrees; + + graph->minvol += myndegrees*vsize[i]; + + for (j=xadj[i]; j<xadj[i+1]; j++) { + ii = adjncy[j]; + other = where[ii]; + orinfo = rinfo+ii; + oedegrees = orinfo->edegrees; + + for (k=0; k<orinfo->ndegrees; k++) + ophtable[oedegrees[k].pid] = k; + ophtable[other] = 1; /* this is to simplify coding */ + + if (me == other) { + /* Find which domains 'i' is connected and 'ii' is not and update their gain */ + for (k=0; k<myndegrees; k++) { + if (ophtable[myedegrees[k].pid] == -1) + myedegrees[k].gv -= vsize[ii]; + } + } + else { + ASSERT(ophtable[me] != -1); + + if (oedegrees[ophtable[me]].ned == 1) { /* I'm the only connection of 'ii' in 'me' */ + /* Increase the gains for all the common domains between 'i' and 'ii' */ + for (k=0; k<myndegrees; k++) { + if (ophtable[myedegrees[k].pid] != -1) + myedegrees[k].gv += vsize[ii]; + } + } + else { + /* Find which domains 'i' is connected and 'ii' is not and update their gain */ + for (k=0; k<myndegrees; k++) { + if (ophtable[myedegrees[k].pid] == -1) + myedegrees[k].gv -= vsize[ii]; + } + } + } + + for (kk=0; kk<orinfo->ndegrees; kk++) + ophtable[oedegrees[kk].pid] = -1; + ophtable[other] = -1; + } + + /* Compute the max vgain */ + for (k=0; k<myndegrees; k++) { + if (myedegrees[k].gv > myrinfo->gv) + myrinfo->gv = myedegrees[k].gv; + } + } + + if (myrinfo->ed > 0 && myrinfo->id == 0) + myrinfo->gv += vsize[i]; + + if (myrinfo->gv >= 0 || myrinfo->ed-myrinfo->id >= 0) + BNDInsert(graph->nbnd, bndind, bndptr, i); + } + +stoptimer(ctrl->AuxTmr2); + + idxwspacefree(ctrl, nparts); + +} + + + +/************************************************************************* +* This function projects a partition, and at the same time computes the +* parameters for refinement. +**************************************************************************/ +void ProjectVolKWayPartition(CtrlType *ctrl, GraphType *graph, int nparts) +{ + int i, j, k, nvtxs, me, other, istart, iend, ndegrees; + idxtype *xadj, *adjncy, *adjwgt, *adjwgtsum; + idxtype *cmap, *where; + idxtype *cwhere; + GraphType *cgraph; + VRInfoType *crinfo, *rinfo, *myrinfo; + VEDegreeType *myedegrees; + idxtype *htable; + + cgraph = graph->coarser; + cwhere = cgraph->where; + crinfo = cgraph->vrinfo; + + nvtxs = graph->nvtxs; + cmap = graph->cmap; + xadj = graph->xadj; + adjncy = graph->adjncy; + adjwgt = graph->adjwgt; + adjwgtsum = graph->adjwgtsum; + + AllocateVolKWayPartitionMemory(ctrl, graph, nparts); + where = graph->where; + rinfo = graph->vrinfo; + + /* Go through and project partition and compute id/ed for the nodes */ + for (i=0; i<nvtxs; i++) { + k = cmap[i]; + where[i] = cwhere[k]; + cmap[i] = crinfo[k].ed; /* For optimization */ + } + + htable = idxset(nparts, -1, idxwspacemalloc(ctrl, nparts)); + + ctrl->wspace.cdegree = 0; + for (i=0; i<nvtxs; i++) { + me = where[i]; + + myrinfo = rinfo+i; + myrinfo->id = myrinfo->ed = myrinfo->nid = myrinfo->ndegrees = 0; + myrinfo->edegrees = NULL; + + myrinfo->id = adjwgtsum[i]; + myrinfo->nid = xadj[i+1]-xadj[i]; + + if (cmap[i] > 0) { /* If it is an interface node. Note cmap[i] = crinfo[cmap[i]].ed */ + istart = xadj[i]; + iend = xadj[i+1]; + + myedegrees = myrinfo->edegrees = ctrl->wspace.vedegrees+ctrl->wspace.cdegree; + ctrl->wspace.cdegree += iend-istart; + + ndegrees = 0; + for (j=istart; j<iend; j++) { + other = where[adjncy[j]]; + if (me != other) { + myrinfo->ed += adjwgt[j]; + myrinfo->nid--; + if ((k = htable[other]) == -1) { + htable[other] = ndegrees; + myedegrees[ndegrees].gv = 0; + myedegrees[ndegrees].pid = other; + myedegrees[ndegrees].ed = adjwgt[j]; + myedegrees[ndegrees++].ned = 1; + } + else { + myedegrees[k].ed += adjwgt[j]; + myedegrees[k].ned++; + } + } + } + myrinfo->id -= myrinfo->ed; + + /* Remove space for edegrees if it was interior */ + if (myrinfo->ed == 0) { + myrinfo->edegrees = NULL; + ctrl->wspace.cdegree -= iend-istart; + } + else { + myrinfo->ndegrees = ndegrees; + + for (j=0; j<ndegrees; j++) + htable[myedegrees[j].pid] = -1; + } + } + } + + ComputeKWayVolGains(ctrl, graph, nparts); + + idxcopy(nparts, cgraph->pwgts, graph->pwgts); + graph->mincut = cgraph->mincut; + + FreeGraph(graph->coarser); + graph->coarser = NULL; + + idxwspacefree(ctrl, nparts); + +} + + + +/************************************************************************* +* This function computes the boundary definition for balancing +**************************************************************************/ +void ComputeVolKWayBoundary(CtrlType *ctrl, GraphType *graph, int nparts) +{ + int i, nvtxs, nbnd; + idxtype *bndind, *bndptr; + + nvtxs = graph->nvtxs; + bndind = graph->bndind; + bndptr = idxset(nvtxs, -1, graph->bndptr); + + + /*------------------------------------------------------------ + / Compute the new boundary + /------------------------------------------------------------*/ + nbnd = 0; + for (i=0; i<nvtxs; i++) { + if (graph->vrinfo[i].gv >=0 || graph->vrinfo[i].ed-graph->vrinfo[i].id >= 0) + BNDInsert(nbnd, bndind, bndptr, i); + } + + graph->nbnd = nbnd; +} + +/************************************************************************* +* This function computes the boundary definition for balancing +**************************************************************************/ +void ComputeVolKWayBalanceBoundary(CtrlType *ctrl, GraphType *graph, int nparts) +{ + int i, nvtxs, nbnd; + idxtype *bndind, *bndptr; + + nvtxs = graph->nvtxs; + bndind = graph->bndind; + bndptr = idxset(nvtxs, -1, graph->bndptr); + + + /*------------------------------------------------------------ + / Compute the new boundary + /------------------------------------------------------------*/ + nbnd = 0; + for (i=0; i<nvtxs; i++) { + if (graph->vrinfo[i].ed > 0) + BNDInsert(nbnd, bndind, bndptr, i); + } + + graph->nbnd = nbnd; +} + |
