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/ParMETISLib/lmatch.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/ParMETISLib/lmatch.c')
| -rw-r--r-- | benchmarks/CUDA/DG/3rdParty/ParMetis-3.1/ParMETISLib/lmatch.c | 364 |
1 files changed, 364 insertions, 0 deletions
diff --git a/benchmarks/CUDA/DG/3rdParty/ParMetis-3.1/ParMETISLib/lmatch.c b/benchmarks/CUDA/DG/3rdParty/ParMetis-3.1/ParMETISLib/lmatch.c new file mode 100644 index 0000000..d8601ef --- /dev/null +++ b/benchmarks/CUDA/DG/3rdParty/ParMetis-3.1/ParMETISLib/lmatch.c @@ -0,0 +1,364 @@ +/* + * Copyright 1997, Regents of the University of Minnesota + * + * coarsen.c + * + * This file contains code that finds a matching and performs the coarsening + * + * Started 2/22/96 + * George + * + * $Id: lmatch.c,v 1.2 2003/07/21 17:18:50 karypis Exp $ + * + */ + +#include <parmetislib.h> + + +/************************************************************************* +* This function finds a HEM matching between local vertices only +**************************************************************************/ +void Mc_LocalMatch_HEM(CtrlType *ctrl, GraphType *graph, WorkSpaceType *wspace) +{ + int h, i, ii, j, k; + int nvtxs, ncon, cnvtxs, firstvtx, maxi, maxidx, edge; + idxtype *xadj, *ladjncy, *adjwgt, *vtxdist, *home, *myhome, *shome, *rhome; + idxtype *perm, *match; + float maxnvwgt, *nvwgt; + + graph->match_type = MATCH_LOCAL; + maxnvwgt = 1.0/((float)(ctrl->nparts)*MAXVWGT_FACTOR); + + IFSET(ctrl->dbglvl, DBG_TIME, MPI_Barrier(ctrl->comm)); + IFSET(ctrl->dbglvl, DBG_TIME, starttimer(ctrl->MatchTmr)); + + nvtxs = graph->nvtxs; + ncon = graph->ncon; + xadj = graph->xadj; + nvwgt = graph->nvwgt; + ladjncy = graph->adjncy; + adjwgt = graph->adjwgt; + home = graph->home; + + vtxdist = graph->vtxdist; + firstvtx = vtxdist[ctrl->mype]; + + match = graph->match = idxmalloc(nvtxs+graph->nrecv, "HEM_Match: match"); + myhome = idxsmalloc(nvtxs+graph->nrecv, UNMATCHED, "HEM_Match: myhome"); + + idxset(nvtxs, UNMATCHED, match); + idxset(graph->nrecv, 0, match+nvtxs); /* Easy way to handle remote vertices */ + + /*------------------------------------------------------------ + / Send/Receive the home information of interface vertices + /------------------------------------------------------------*/ + if (ctrl->partType == ADAPTIVE_PARTITION || ctrl->partType == REFINE_PARTITION) { + idxcopy(nvtxs, home, myhome); + shome = wspace->indices; + rhome = myhome + nvtxs; + CommInterfaceData(ctrl, graph, myhome, shome, rhome); + } + + /************************************************************* + * Go now and find a local matching + *************************************************************/ + perm = wspace->indices; + FastRandomPermute(nvtxs, perm, 1); + cnvtxs = 0; + for (ii=0; ii<nvtxs; ii++) { + i = perm[ii]; + if (match[i] == UNMATCHED) { + maxidx = maxi = -1; + + /* Find a heavy-edge matching, if the weight of the vertex is OK */ + for (h=0; h<ncon; h++) + if (nvwgt[i*ncon+h] > maxnvwgt) + break; + + if (h == ncon) { + for (j=xadj[i]; j<xadj[i+1]; j++) { + edge = ladjncy[j]; + + /* match only with local vertices */ + if (myhome[edge] != myhome[i] || edge >= nvtxs) + continue; + + for (h=0; h<ncon; h++) + if (nvwgt[edge*ncon+h] > maxnvwgt) + break; + + if (h == ncon) { + if (match[edge] == UNMATCHED && + (maxi == -1 || + adjwgt[maxi] < adjwgt[j] || + (adjwgt[maxi] == adjwgt[j] && + BetterVBalance(ncon,nvwgt+i*ncon,nvwgt+maxidx*ncon,nvwgt+edge*ncon) >= 0))) { + maxi = j; + maxidx = edge; + } + } + } + } + + if (maxi != -1) { + k = ladjncy[maxi]; + if (i <= k) { + match[i] = firstvtx+k + KEEP_BIT; + match[k] = firstvtx+i; + } + else { + match[i] = firstvtx+k; + match[k] = firstvtx+i + KEEP_BIT; + } + } + else { + match[i] = (firstvtx+i) + KEEP_BIT; + } + cnvtxs++; + } + } + + CommInterfaceData(ctrl, graph, match, wspace->indices, match+nvtxs); + GKfree((void **)(&myhome), LTERM); + +#ifdef DEBUG_MATCH + PrintVector2(ctrl, nvtxs, firstvtx, match, "Match1"); +#endif + + + if (ctrl->dbglvl&DBG_MATCHINFO) { + PrintVector2(ctrl, nvtxs, firstvtx, match, "Match"); + myprintf(ctrl, "Cnvtxs: %d\n", cnvtxs); + rprintf(ctrl, "Done with matching...\n"); + } + + IFSET(ctrl->dbglvl, DBG_TIME, MPI_Barrier(ctrl->comm)); + IFSET(ctrl->dbglvl, DBG_TIME, stoptimer(ctrl->MatchTmr)); + + IFSET(ctrl->dbglvl, DBG_TIME, starttimer(ctrl->ContractTmr)); + Mc_Local_CreateCoarseGraph(ctrl, graph, wspace, cnvtxs); + IFSET(ctrl->dbglvl, DBG_TIME, stoptimer(ctrl->ContractTmr)); + +} + + + + + +/************************************************************************* +* This function creates the coarser graph +**************************************************************************/ +void Mc_Local_CreateCoarseGraph(CtrlType *ctrl, GraphType *graph, WorkSpaceType *wspace, int cnvtxs) +{ + int h, i, j, k, l; + int nvtxs, ncon, nedges, firstvtx, cfirstvtx; + int npes=ctrl->npes, mype=ctrl->mype; + int cnedges, v, u; + idxtype *xadj, *vwgt, *vsize, *ladjncy, *adjwgt, *vtxdist, *where, *home; + idxtype *match, *cmap; + idxtype *cxadj, *cvwgt, *cvsize = NULL, *cadjncy, *cadjwgt, *cvtxdist, *chome = NULL, *cwhere = NULL; + float *cnvwgt; + GraphType *cgraph; + int mask=(1<<13)-1, htable[8192], htableidx[8192]; + + nvtxs = graph->nvtxs; + ncon = graph->ncon; + + vtxdist = graph->vtxdist; + xadj = graph->xadj; + vwgt = graph->vwgt; + home = graph->home; + vsize = graph->vsize; + ladjncy = graph->adjncy; + adjwgt = graph->adjwgt; + where = graph->where; + match = graph->match; + + firstvtx = vtxdist[mype]; + + cmap = graph->cmap = idxmalloc(nvtxs+graph->nrecv, "CreateCoarseGraph: cmap"); + + /* Initialize the coarser graph */ + cgraph = CreateGraph(); + cgraph->nvtxs = cnvtxs; + cgraph->level = graph->level+1; + cgraph->ncon = ncon; + + cgraph->finer = graph; + graph->coarser = cgraph; + + + /************************************************************* + * Obtain the vtxdist of the coarser graph + **************************************************************/ + cvtxdist = cgraph->vtxdist = idxmalloc(npes+1, "CreateCoarseGraph: cvtxdist"); + cvtxdist[npes] = cnvtxs; /* Use last position in the cvtxdist as a temp buffer */ + + MPI_Allgather((void *)(cvtxdist+npes), 1, IDX_DATATYPE, (void *)cvtxdist, 1, IDX_DATATYPE, ctrl->comm); + + MAKECSR(i, npes, cvtxdist); + + cgraph->gnvtxs = cvtxdist[npes]; + +#ifdef DEBUG_CONTRACT + PrintVector(ctrl, npes+1, 0, cvtxdist, "cvtxdist"); +#endif + + + /************************************************************* + * Construct the cmap vector + **************************************************************/ + cfirstvtx = cvtxdist[mype]; + + /* Create the cmap of what you know so far locally */ + cnvtxs = 0; + for (i=0; i<nvtxs; i++) { + if (match[i] >= KEEP_BIT) { + k = match[i] - KEEP_BIT; + if (k<firstvtx+i) + continue; /* i has been matched via the (k,i) side */ + + cmap[i] = cfirstvtx + cnvtxs++; + if (k != firstvtx+i) { + cmap[k-firstvtx] = cmap[i]; + match[k-firstvtx] += KEEP_BIT; /* Add the KEEP_BIT to simplify coding */ + } + } + } + + CommInterfaceData(ctrl, graph, cmap, wspace->indices, cmap+nvtxs); + + +#ifdef DEBUG_CONTRACT + PrintVector(ctrl, nvtxs, firstvtx, cmap, "Cmap"); +#endif + + + + /************************************************************* + * Finally, create the coarser graph + **************************************************************/ + /* Allocate memory for the coarser graph, and fire up coarsening */ + cxadj = cgraph->xadj = idxmalloc(cnvtxs+1, "CreateCoarserGraph: cxadj"); + cvwgt = cgraph->vwgt = idxmalloc(cnvtxs*ncon, "CreateCoarserGraph: cvwgt"); + cnvwgt = cgraph->nvwgt = fmalloc(cnvtxs*ncon, "CreateCoarserGraph: cnvwgt"); + if (ctrl->partType == ADAPTIVE_PARTITION || ctrl->partType == REFINE_PARTITION) + chome = cgraph->home = idxmalloc(cnvtxs, "CreateCoarserGraph: chome"); + if (vsize != NULL) + cvsize = cgraph->vsize = idxmalloc(cnvtxs, "CreateCoarserGraph: cvsize"); + if (where != NULL) + cwhere = cgraph->where = idxmalloc(cnvtxs, "CreateCoarserGraph: cwhere"); + cadjncy = idxmalloc(2*graph->nedges, "CreateCoarserGraph: cadjncy"); + cadjwgt = cadjncy+graph->nedges; + + iset(8192, -1, htable); + + cxadj[0] = cnvtxs = cnedges = 0; + for (i=0; i<nvtxs; i++) { + v = firstvtx+i; + u = match[i]-KEEP_BIT; + + if (v > u) + continue; /* I have already collapsed it as (u,v) */ + + /* Collapse the v vertex first, which you know that is local */ + for (h=0; h<ncon; h++) + cvwgt[cnvtxs*ncon+h] = vwgt[i*ncon+h]; + if (ctrl->partType == ADAPTIVE_PARTITION || ctrl->partType == REFINE_PARTITION) + chome[cnvtxs] = home[i]; + if (vsize != NULL) + cvsize[cnvtxs] = vsize[i]; + if (where != NULL) + cwhere[cnvtxs] = where[i]; + nedges = 0; + + for (j=xadj[i]; j<xadj[i+1]; j++) { + k = cmap[ladjncy[j]]; + if (k != cfirstvtx+cnvtxs) { /* If this is not an internal edge */ + l = k&mask; + if (htable[l] == -1) { /* Seeing this for first time */ + htable[l] = k; + htableidx[l] = cnedges+nedges; + cadjncy[cnedges+nedges] = k; + cadjwgt[cnedges+nedges++] = adjwgt[j]; + } + else if (htable[l] == k) { + cadjwgt[htableidx[l]] += adjwgt[j]; + } + else { /* Now you have to go and do a search. Expensive case */ + for (l=0; l<nedges; l++) { + if (cadjncy[cnedges+l] == k) + break; + } + if (l < nedges) { + cadjwgt[cnedges+l] += adjwgt[j]; + } + else { + cadjncy[cnedges+nedges] = k; + cadjwgt[cnedges+nedges++] = adjwgt[j]; + } + } + } + } + + /* Collapse the u vertex next */ + if (v != u) { + u -= firstvtx; + for (h=0; h<ncon; h++) + cvwgt[cnvtxs*ncon+h] += vwgt[u*ncon+h]; + if (vsize != NULL) + cvsize[cnvtxs] += vsize[u]; + if (where != NULL && cwhere[cnvtxs] != where[u]) + myprintf(ctrl, "Something went wrong with the where local matching! %d %d\n", cwhere[cnvtxs], where[u]); + + for (j=xadj[u]; j<xadj[u+1]; j++) { + k = cmap[ladjncy[j]]; + if (k != cfirstvtx+cnvtxs) { /* If this is not an internal edge */ + l = k&mask; + if (htable[l] == -1) { /* Seeing this for first time */ + htable[l] = k; + htableidx[l] = cnedges+nedges; + cadjncy[cnedges+nedges] = k; + cadjwgt[cnedges+nedges++] = adjwgt[j]; + } + else if (htable[l] == k) { + cadjwgt[htableidx[l]] += adjwgt[j]; + } + else { /* Now you have to go and do a search. Expensive case */ + for (l=0; l<nedges; l++) { + if (cadjncy[cnedges+l] == k) + break; + } + if (l < nedges) { + cadjwgt[cnedges+l] += adjwgt[j]; + } + else { + cadjncy[cnedges+nedges] = k; + cadjwgt[cnedges+nedges++] = adjwgt[j]; + } + } + } + } + } + + cnedges += nedges; + for (j=cxadj[cnvtxs]; j<cnedges; j++) + htable[cadjncy[j]&mask] = -1; /* reset the htable */ + cxadj[++cnvtxs] = cnedges; + } + + cgraph->nedges = cnedges; + + for (j=0; j<cnvtxs; j++) + for (h=0; h<ncon; h++) + cgraph->nvwgt[j*ncon+h] = (float)(cvwgt[j*ncon+h])/(float)(ctrl->tvwgts[h]); + + cgraph->adjncy = idxmalloc(cnedges, "CreateCoarserGraph: cadjncy"); + cgraph->adjwgt = idxmalloc(cnedges, "CreateCoarserGraph: cadjwgt"); + idxcopy(cnedges, cadjncy, cgraph->adjncy); + idxcopy(cnedges, cadjwgt, cgraph->adjwgt); + GKfree((void **)&cadjncy, (void **)&graph->where, LTERM); /* Note that graph->where works fine even if it is NULL */ + +} + + |
