/* * 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 /************************************************************************* * 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 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; passlevel+pass)%2; nchanged = nrequests = 0; for (ii=nmatched; ii= 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; icomm, ctrl->rreq+i); } /* Issue the sends next. This needs some work */ ikeysort(nrequests, match_requests); for (j=i=0; icomm, 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; istatuses+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= 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; icomm, ctrl->rreq+i); } /* Issue the sends next. */ for (i=0; icomm, 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; istatuses+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; ipv4); } /* Traverse the vertices and those that were unmatched, match them with themselves */ cnvtxs = 0; for (i=0; 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)); }