📄 coarsen.c
字号:
/* * Copyright 1997, Regents of the University of Minnesota * * mcoarsen.c * * This file contains code that performs graph coarsening * * Started 2/22/96 * George * * $Id: coarsen.c 2501 2007-11-20 02:33:29Z benkirk $ * */#include <parmetislib.h>/************************************************************************** This function creates the coarser graph**************************************************************************/void Moc_Global_CreateCoarseGraph(CtrlType *ctrl, GraphType *graph, WorkSpaceType *wspace, int cnvtxs){ int h, i, j, k, l, ii, jj, ll, nnbrs, nvtxs, nedges, ncon; int firstvtx, lastvtx, cfirstvtx, clastvtx, otherlastvtx; int npes=ctrl->npes, mype=ctrl->mype; int cnedges, nsend, nrecv, nkeepsize, nrecvsize, nsendsize, v, u; idxtype *xadj, *ladjncy, *adjwgt, *vwgt, *vsize, *vtxdist, *home; idxtype *match, *cmap, *rcmap, *scmap; idxtype *cxadj, *cadjncy, *cadjwgt, *cvwgt, *cvsize = NULL, *chome = NULL, *cvtxdist; idxtype *rsizes, *ssizes, *rlens, *slens, *rgraph, *sgraph, *perm; idxtype *peind, *recvptr, *recvind; float *nvwgt, *cnvwgt; GraphType *cgraph; KeyValueType *scand, *rcand; int mask=(1<<13)-1, htable[8192], htableidx[8192]; nvtxs = graph->nvtxs; ncon = graph->ncon; vtxdist = graph->vtxdist; xadj = graph->xadj; vwgt = graph->vwgt; vsize = graph->vsize; nvwgt = graph->nvwgt; home = graph->home; ladjncy = graph->adjncy; adjwgt = graph->adjwgt; match = graph->match; firstvtx = vtxdist[mype]; lastvtx = vtxdist[mype+1]; cmap = graph->cmap = idxmalloc(nvtxs+graph->nrecv, "CreateCoarseGraph: cmap"); nnbrs = graph->nnbrs; peind = graph->peind; recvind = graph->recvind; recvptr = graph->recvptr; /* Use wspace->indices as the tmp space for map of the boundary * vertices that are sent and received */ scmap = wspace->indices; rcmap = cmap + nvtxs; /* Initialize the coarser graph */ cgraph = CreateGraph(); cgraph->nvtxs = cnvtxs; cgraph->ncon = ncon; cgraph->level = graph->level+1; 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]; clastvtx = cvtxdist[mype+1]; /* 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 && k<firstvtx+i) continue; /* Both (i,k) are local and i has been matched via the (k,i) side */ cmap[i] = cfirstvtx + cnvtxs++; if (k != firstvtx+i && (k>=firstvtx && k<lastvtx)) { /* I'm matched locally */ cmap[k-firstvtx] = cmap[i]; match[k-firstvtx] += KEEP_BIT; /* Add the KEEP_BIT to simplify coding */ } } } ASSERT(ctrl, cnvtxs == clastvtx-cfirstvtx); CommInterfaceData(ctrl, graph, cmap, scmap, rcmap); /* Update the cmap of the locally stored vertices that will go away. * The remote processor assigned cmap for them */ for (i=0; i<nvtxs; i++) { if (match[i] < KEEP_BIT) { /* Only vertices that go away satisfy this*/ cmap[i] = rcmap[BSearch(graph->nrecv, recvind, match[i])]; } } CommInterfaceData(ctrl, graph, cmap, scmap, rcmap);#ifdef DEBUG_CONTRACT PrintVector(ctrl, nvtxs, firstvtx, cmap, "Cmap");#endif /************************************************************* * Determine how many adjcency lists you need to send/receive. **************************************************************/ /* Use wspace->pairs as the tmp space for the boundary vertices that are sent and received */ scand = wspace->pairs; rcand = graph->rcand = (KeyValueType *)GKmalloc(recvptr[nnbrs]*sizeof(KeyValueType), "CreateCoarseGraph: rcand"); nkeepsize = nsend = nrecv = 0; for (i=0; i<nvtxs; i++) { if (match[i] < KEEP_BIT) { /* This is going away */ scand[nsend].key = match[i]; scand[nsend].val = i; nsend++; } else { nkeepsize += (xadj[i+1]-xadj[i]); k = match[i]-KEEP_BIT; if (k<firstvtx || k>=lastvtx) { /* This is comming from afar */ rcand[nrecv].key = k; rcand[nrecv].val = cmap[i] - cfirstvtx; /* Set it for use during the partition projection */ ASSERT(ctrl, rcand[nrecv].val>=0 && rcand[nrecv].val<cnvtxs); nrecv++; } } }#ifdef DEBUG_CONTRACT PrintPairs(ctrl, nsend, scand, "scand"); PrintPairs(ctrl, nrecv, rcand, "rcand");#endif /*************************************************************** * Determine how many lists and their sizes you will send and * received for each of the neighboring PEs ****************************************************************/ rsizes = wspace->pv1; ssizes = wspace->pv2; idxset(nnbrs, 0, ssizes); idxset(nnbrs, 0, rsizes); rlens = graph->rlens = idxmalloc(nnbrs+1, "CreateCoarseGraph: graph->rlens"); slens = graph->slens = idxmalloc(nnbrs+1, "CreateCoarseGraph: graph->slens"); /* Take care the sending data first */ ikeyvalsort(nsend, scand); slens[0] = 0; for (k=i=0; i<nnbrs; i++) { otherlastvtx = vtxdist[peind[i]+1]; for (; k<nsend && scand[k].key < otherlastvtx; k++) ssizes[i] += (xadj[scand[k].val+1]-xadj[scand[k].val]); slens[i+1] = k; } /* Take care the receiving data next. You cannot yet determine the rsizes[] */ ikeyvalsort(nrecv, rcand); rlens[0] = 0; for (k=i=0; i<nnbrs; i++) { otherlastvtx = vtxdist[peind[i]+1]; for (; k<nrecv && rcand[k].key < otherlastvtx; k++); rlens[i+1] = k; }#ifdef DEBUG_CONTRACT PrintVector(ctrl, nnbrs+1, 0, slens, "slens"); PrintVector(ctrl, nnbrs+1, 0, rlens, "rlens");#endif /*************************************************************** * Exchange size information ****************************************************************/ /* Issue the receives first. */ for (i=0; i<nnbrs; i++) { if (rlens[i+1]-rlens[i] > 0) /* Issue a receive only if you are getting something */ MPI_Irecv((void *)(rsizes+i), 1, IDX_DATATYPE, peind[i], 1, ctrl->comm, ctrl->rreq+i); } /* Take care the sending data next */ for (i=0; i<nnbrs; i++) { if (slens[i+1]-slens[i] > 0) /* Issue a send only if you are sending something */ MPI_Isend((void *)(ssizes+i), 1, IDX_DATATYPE, peind[i], 1, ctrl->comm, ctrl->sreq+i); } /* OK, now get into the loop waiting for the operations to finish */ for (i=0; i<nnbrs; i++) { if (rlens[i+1]-rlens[i] > 0) MPI_Wait(ctrl->rreq+i, &ctrl->status); } for (i=0; i<nnbrs; i++) { if (slens[i+1]-slens[i] > 0) MPI_Wait(ctrl->sreq+i, &ctrl->status); }#ifdef DEBUG_CONTRACT PrintVector(ctrl, nnbrs, 0, rsizes, "rsizes"); PrintVector(ctrl, nnbrs, 0, ssizes, "ssizes");#endif /************************************************************* * Allocate memory for received/sent graphs and start sending * and receiving data. * rgraph and sgraph is a different data structure than CSR * to facilitate single message exchange. **************************************************************/ nrecvsize = idxsum(nnbrs, rsizes); nsendsize = idxsum(nnbrs, ssizes); if ((4+ncon)*(nrecv+nsend) + 2*(nrecvsize+nsendsize) <= wspace->nlarge) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -