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/match.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/match.c')
| -rw-r--r-- | benchmarks/CUDA/DG/3rdParty/ParMetis-3.1/ParMETISLib/match.c | 320 |
1 files changed, 320 insertions, 0 deletions
diff --git a/benchmarks/CUDA/DG/3rdParty/ParMetis-3.1/ParMETISLib/match.c b/benchmarks/CUDA/DG/3rdParty/ParMetis-3.1/ParMETISLib/match.c new file mode 100644 index 0000000..89bfa62 --- /dev/null +++ b/benchmarks/CUDA/DG/3rdParty/ParMetis-3.1/ParMETISLib/match.c @@ -0,0 +1,320 @@ +/* + * Copyright 1997, Regents of the University of Minnesota + * + * mmatch.c + * + * This file contains code that finds a matching + * + * Started 2/22/96 + * George + * + * $Id: match.c,v 1.2 2003/07/21 17:18:50 karypis Exp $ + * + */ + +#include <parmetislib.h> + + +/************************************************************************* +* This function finds a matching +**************************************************************************/ +void Moc_GlobalMatch_Balance(CtrlType *ctrl, GraphType *graph, WorkSpaceType *wspace) +{ + int h, i, ii, j, k; + int nnbrs, nvtxs, ncon, cnvtxs, firstvtx, lastvtx, maxi, maxidx, nkept; + int otherlastvtx, nrequests, nchanged, pass, nmatched, wside; + idxtype *xadj, *ladjncy, *adjwgt, *vtxdist, *home, *myhome, *shome, *rhome; + idxtype *match, *rmatch, *smatch; + idxtype *peind, *sendptr, *recvptr; + idxtype *perm, *iperm, *nperm, *changed; + float *nvwgt, maxnvwgt; + int *nreqs_pe; + KeyValueType *match_requests, *match_granted, *pe_requests; + + maxnvwgt = 1.0/((float)(ctrl->nparts)*MAXNVWGT_FACTOR); + + graph->match_type = MATCH_GLOBAL; + + 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; + ladjncy = graph->adjncy; + adjwgt = graph->adjwgt; + home = graph->home; + nvwgt = graph->nvwgt; + + vtxdist = graph->vtxdist; + firstvtx = vtxdist[ctrl->mype]; + lastvtx = vtxdist[ctrl->mype+1]; + + match = graph->match = idxsmalloc(nvtxs+graph->nrecv, UNMATCHED, "HEM_Match: match"); + myhome = idxsmalloc(nvtxs+graph->nrecv, UNMATCHED, "HEM_Match: myhome"); + + /*------------------------------------------------------------ + / 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); + } + + nnbrs = graph->nnbrs; + peind = graph->peind; + sendptr = graph->sendptr; + recvptr = graph->recvptr; + + /* Use wspace->indices as the tmp space for matching info of the boundary + * vertices that are sent and received */ + rmatch = match + nvtxs; + smatch = wspace->indices; + changed = smatch+graph->nsend; + + /* Use wspace->indices as the tmp space for match requests of the boundary + * vertices that are sent and received */ + match_requests = wspace->pairs; + match_granted = match_requests + graph->nsend; + + nreqs_pe = ismalloc(nnbrs, 0, "Match_HEM: nreqs_pe"); + + nkept = graph->gnvtxs/ctrl->npes - nvtxs; + + perm = (idxtype *)wspace->degrees; + iperm = perm + nvtxs; + FastRandomPermute(nvtxs, perm, 1); + for (i=0; i<nvtxs; i++) + iperm[perm[i]] = i; + + nperm = iperm + nvtxs; + for (i=0; i<nnbrs; i++) + nperm[i] = i; + + /************************************************************* + * Go now and find a matching by doing multiple iterations + *************************************************************/ + /* First nullify the heavy vertices */ + for (nchanged=i=0; i<nvtxs; i++) { + for (h=0; h<ncon; h++) + if (nvwgt[i*ncon+h] > maxnvwgt) { + break; + } + + if (h != ncon) { + match[i] = TOO_HEAVY; + nchanged++; + } + } + if (GlobalSESum(ctrl, nchanged) > 0) { + IFSET(ctrl->dbglvl, DBG_PROGRESS, + rprintf(ctrl, "We found %d heavy vertices!\n", GlobalSESum(ctrl, nchanged))); + CommInterfaceData(ctrl, graph, match, smatch, rmatch); + } + + + for (nmatched=pass=0; pass<NMATCH_PASSES; pass++) { + wside = (graph->level+pass)%2; + nchanged = nrequests = 0; + for (ii=nmatched; ii<nvtxs; ii++) { + i = perm[ii]; + if (match[i] == UNMATCHED) { /* Unmatched */ + maxidx = i; + maxi = -1; + + /* Find a heavy-edge matching */ + for (j=xadj[i]; j<xadj[i+1]; j++) { + k = ladjncy[j]; + if (match[k] == UNMATCHED && + myhome[k] == myhome[i] && + (maxi == -1 || + adjwgt[maxi] < adjwgt[j] || + (maxidx < nvtxs && + k < nvtxs && + adjwgt[maxi] == adjwgt[j] && + BetterVBalance(ncon,nvwgt+i*ncon,nvwgt+maxidx*ncon,nvwgt+k*ncon) >= 0))) { + maxi = j; + maxidx = k; + } + } + + if (maxi != -1) { + k = ladjncy[maxi]; + if (k < nvtxs) { /* Take care the local vertices first */ + /* Here we give preference the local matching by granting it right away */ + if (i <= k) { + match[i] = firstvtx+k + KEEP_BIT; + match[k] = firstvtx+i; + } + else { + match[i] = firstvtx+k; + match[k] = firstvtx+i + KEEP_BIT; + } + changed[nchanged++] = i; + changed[nchanged++] = k; + } + else { /* Take care any remote boundary vertices */ + match[k] = MAYBE_MATCHED; + /* Alternate among which vertices will issue the requests */ + if ((wside ==0 && firstvtx+i < graph->imap[k]) || (wside == 1 && firstvtx+i > graph->imap[k])) { + match[i] = MAYBE_MATCHED; + match_requests[nrequests].key = graph->imap[k]; + match_requests[nrequests].val = firstvtx+i; + nrequests++; + } + } + } + } + } + + +#ifdef DEBUG_MATCH + PrintVector2(ctrl, nvtxs, firstvtx, match, "Match1"); + myprintf(ctrl, "[c: %2d] Nlocal: %d, Nrequests: %d\n", c, nlocal, nrequests); +#endif + + + /*********************************************************** + * Exchange the match_requests, requests for me are stored in + * match_granted + ************************************************************/ + /* Issue the receives first. Note that from each PE can receive a maximum + of the interface node that it needs to send it in the case of a mat-vec */ + for (i=0; i<nnbrs; i++) { + MPI_Irecv((void *)(match_granted+recvptr[i]), 2*(recvptr[i+1]-recvptr[i]), IDX_DATATYPE, + peind[i], 1, ctrl->comm, ctrl->rreq+i); + } + + /* Issue the sends next. This needs some work */ + ikeysort(nrequests, match_requests); + for (j=i=0; i<nnbrs; i++) { + otherlastvtx = vtxdist[peind[i]+1]; + for (k=j; k<nrequests && match_requests[k].key < otherlastvtx; k++); + MPI_Isend((void *)(match_requests+j), 2*(k-j), IDX_DATATYPE, peind[i], 1, ctrl->comm, ctrl->sreq+i); + j = k; + } + + /* OK, now get into the loop waiting for the operations to finish */ + MPI_Waitall(nnbrs, ctrl->rreq, ctrl->statuses); + for (i=0; i<nnbrs; i++) { + MPI_Get_count(ctrl->statuses+i, IDX_DATATYPE, nreqs_pe+i); + nreqs_pe[i] = nreqs_pe[i]/2; /* Adjust for pairs of IDX_DATATYPE */ + } + MPI_Waitall(nnbrs, ctrl->sreq, ctrl->statuses); + + + /*********************************************************** + * Now, go and service the requests that you received in + * match_granted + ************************************************************/ + RandomPermute(nnbrs, nperm, 0); + for (ii=0; ii<nnbrs; ii++) { + i = nperm[ii]; + pe_requests = match_granted+recvptr[i]; + for (j=0; j<nreqs_pe[i]; j++) { + k = pe_requests[j].key; + ASSERTP(ctrl, k >= firstvtx && k < lastvtx, (ctrl, "%d %d %d %d %d\n", firstvtx, lastvtx, k, j, peind[i])); + /* myprintf(ctrl, "Requesting a match %d %d\n", pe_requests[j].key, pe_requests[j].val); */ + if (match[k-firstvtx] == UNMATCHED) { /* Bingo, lets grant this request */ + changed[nchanged++] = k-firstvtx; + if (nkept >= 0) { /* Flip a coin for who gets it */ + match[k-firstvtx] = pe_requests[j].val + KEEP_BIT; + nkept--; + } + else { + match[k-firstvtx] = pe_requests[j].val; + pe_requests[j].key += KEEP_BIT; + nkept++; + } + /* myprintf(ctrl, "Request from pe:%d (%d %d) granted!\n", peind[i], pe_requests[j].val, pe_requests[j].key); */ + } + else { /* We are not granting the request */ + /* myprintf(ctrl, "Request from pe:%d (%d %d) not granted!\n", peind[i], pe_requests[j].val, pe_requests[j].key); */ + pe_requests[j].key = UNMATCHED; + } + } + } + + + /*********************************************************** + * Exchange the match_granted information. It is stored in + * match_requests + ************************************************************/ + /* Issue the receives first. Note that from each PE can receive a maximum + of the interface node that it needs to send during the case of a mat-vec */ + for (i=0; i<nnbrs; i++) { + MPI_Irecv((void *)(match_requests+sendptr[i]), 2*(sendptr[i+1]-sendptr[i]), IDX_DATATYPE, + peind[i], 1, ctrl->comm, ctrl->rreq+i); + } + + /* Issue the sends next. */ + for (i=0; i<nnbrs; i++) { + MPI_Isend((void *)(match_granted+recvptr[i]), 2*nreqs_pe[i], IDX_DATATYPE, + peind[i], 1, ctrl->comm, ctrl->sreq+i); + } + + /* OK, now get into the loop waiting for the operations to finish */ + MPI_Waitall(nnbrs, ctrl->rreq, ctrl->statuses); + for (i=0; i<nnbrs; i++) { + MPI_Get_count(ctrl->statuses+i, IDX_DATATYPE, nreqs_pe+i); + nreqs_pe[i] = nreqs_pe[i]/2; /* Adjust for pairs of IDX_DATATYPE */ + } + MPI_Waitall(nnbrs, ctrl->sreq, ctrl->statuses); + + + /*********************************************************** + * Now, go and through the match_requests and update local + * match information for the matchings that were granted. + ************************************************************/ + for (i=0; i<nnbrs; i++) { + pe_requests = match_requests+sendptr[i]; + for (j=0; j<nreqs_pe[i]; j++) { + match[pe_requests[j].val-firstvtx] = pe_requests[j].key; + if (pe_requests[j].key != UNMATCHED) + changed[nchanged++] = pe_requests[j].val-firstvtx; + } + } + + for (i=0; i<nchanged; i++) { + ii = iperm[changed[i]]; + perm[ii] = perm[nmatched]; + iperm[perm[nmatched]] = ii; + nmatched++; + } + + CommChangedInterfaceData(ctrl, graph, nchanged, changed, match, match_requests, match_granted, wspace->pv4); + } + + /* Traverse the vertices and those that were unmatched, match them with themselves */ + cnvtxs = 0; + for (i=0; i<nvtxs; i++) { + if (match[i] == UNMATCHED || match[i] == TOO_HEAVY) { + match[i] = (firstvtx+i) + KEEP_BIT; + cnvtxs++; + } + else if (match[i] >= KEEP_BIT) { /* A matched vertex which I get to keep */ + cnvtxs++; + } + } + + if (ctrl->dbglvl&DBG_MATCHINFO) { + PrintVector2(ctrl, nvtxs, firstvtx, match, "Match"); + myprintf(ctrl, "Cnvtxs: %d\n", cnvtxs); + rprintf(ctrl, "Done with matching...\n"); + } + + GKfree((void **)(&myhome), (void **)(&nreqs_pe), LTERM); + + 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)); + + Moc_Global_CreateCoarseGraph(ctrl, graph, wspace, cnvtxs); + + IFSET(ctrl->dbglvl, DBG_TIME, MPI_Barrier(ctrl->comm)); + IFSET(ctrl->dbglvl, DBG_TIME, stoptimer(ctrl->ContractTmr)); + +} + |
