📄 match.c
字号:
/* * 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 2501 2007-11-20 02:33:29Z benkirk $ * */#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));}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -