/************************************************************************* * This function is the entry point of refinement **************************************************************************/ void MocRefineKWayHorizontal(CtrlType *ctrl, GraphType *orggraph, GraphType *graph, int nparts, float *ubvec) { IFSET(ctrl->dbglvl, DBG_TIME, starttimer(ctrl->UncoarsenTmr)); /* Compute the parameters of the coarsest graph */ MocComputeKWayPartitionParams(ctrl, graph, nparts); for (;;) { IFSET(ctrl->dbglvl, DBG_TIME, starttimer(ctrl->RefTmr)); if (!MocIsHBalanced(graph->ncon, nparts, graph->npwgts, ubvec)) { MocComputeKWayBalanceBoundary(ctrl, graph, nparts); MCGreedy_KWayEdgeBalanceHorizontal(ctrl, graph, nparts, ubvec, 4); ComputeKWayBoundary(ctrl, graph, nparts); } MCRandom_KWayEdgeRefineHorizontal(ctrl, graph, nparts, ubvec, 10); IFSET(ctrl->dbglvl, DBG_TIME, stoptimer(ctrl->RefTmr)); if (graph == orggraph) break; graph = graph->finer; IFSET(ctrl->dbglvl, DBG_TIME, starttimer(ctrl->ProjectTmr)); MocProjectKWayPartition(ctrl, graph, nparts); IFSET(ctrl->dbglvl, DBG_TIME, stoptimer(ctrl->ProjectTmr)); } if (!MocIsHBalanced(graph->ncon, nparts, graph->npwgts, ubvec)) { MocComputeKWayBalanceBoundary(ctrl, graph, nparts); MCGreedy_KWayEdgeBalanceHorizontal(ctrl, graph, nparts, ubvec, 4); ComputeKWayBoundary(ctrl, graph, nparts); MCRandom_KWayEdgeRefineHorizontal(ctrl, graph, nparts, ubvec, 10); } IFSET(ctrl->dbglvl, DBG_TIME, stoptimer(ctrl->UncoarsenTmr)); }
void RefineKWay(ctrl_t *ctrl, graph_t *orggraph, graph_t *graph) { idx_t i, nlevels, contig=ctrl->contig; graph_t *ptr; IFSET(ctrl->dbglvl, METIS_DBG_TIME, gk_startcputimer(ctrl->UncoarsenTmr)); /* Determine how many levels are there */ for (ptr=graph, nlevels=0; ptr!=orggraph; ptr=ptr->finer, nlevels++); /* Compute the parameters of the coarsest graph */ ComputeKWayPartitionParams(ctrl, graph); /* Try to minimize the sub-domain connectivity */ if (ctrl->minconn) EliminateSubDomainEdges(ctrl, graph); /* Deal with contiguity constraints at the beginning */ if (contig && FindPartitionInducedComponents(graph, graph->where, NULL, NULL) > ctrl->nparts) { EliminateComponents(ctrl, graph); ComputeKWayBoundary(ctrl, graph, BNDTYPE_BALANCE); Greedy_KWayOptimize(ctrl, graph, 5, 0, OMODE_BALANCE); ComputeKWayBoundary(ctrl, graph, BNDTYPE_REFINE); Greedy_KWayOptimize(ctrl, graph, ctrl->niter, 0, OMODE_REFINE); ctrl->contig = 0; } /* Refine each successively finer graph */ for (i=0; ;i++) { if (ctrl->minconn && i == nlevels/2) EliminateSubDomainEdges(ctrl, graph); IFSET(ctrl->dbglvl, METIS_DBG_TIME, gk_startcputimer(ctrl->RefTmr)); if (2*i >= nlevels && !IsBalanced(ctrl, graph, .02)) { ComputeKWayBoundary(ctrl, graph, BNDTYPE_BALANCE); Greedy_KWayOptimize(ctrl, graph, 1, 0, OMODE_BALANCE); ComputeKWayBoundary(ctrl, graph, BNDTYPE_REFINE); } Greedy_KWayOptimize(ctrl, graph, ctrl->niter, 5.0, OMODE_REFINE); IFSET(ctrl->dbglvl, METIS_DBG_TIME, gk_stopcputimer(ctrl->RefTmr)); /* Deal with contiguity constraints in the middle */ if (contig && i == nlevels/2) { if (FindPartitionInducedComponents(graph, graph->where, NULL, NULL) > ctrl->nparts) { EliminateComponents(ctrl, graph); if (!IsBalanced(ctrl, graph, .02)) { ctrl->contig = 1; ComputeKWayBoundary(ctrl, graph, BNDTYPE_BALANCE); Greedy_KWayOptimize(ctrl, graph, 5, 0, OMODE_BALANCE); ComputeKWayBoundary(ctrl, graph, BNDTYPE_REFINE); Greedy_KWayOptimize(ctrl, graph, ctrl->niter, 0, OMODE_REFINE); ctrl->contig = 0; } } } if (graph == orggraph) break; graph = graph->finer; IFSET(ctrl->dbglvl, METIS_DBG_TIME, gk_startcputimer(ctrl->ProjectTmr)); ASSERT(graph->vwgt != NULL); ProjectKWayPartition(ctrl, graph); IFSET(ctrl->dbglvl, METIS_DBG_TIME, gk_stopcputimer(ctrl->ProjectTmr)); } /* Deal with contiguity requirement at the end */ ctrl->contig = contig; if (contig && FindPartitionInducedComponents(graph, graph->where, NULL, NULL) > ctrl->nparts) EliminateComponents(ctrl, graph); if (!IsBalanced(ctrl, graph, 0.0)) { ComputeKWayBoundary(ctrl, graph, BNDTYPE_BALANCE); Greedy_KWayOptimize(ctrl, graph, 10, 0, OMODE_BALANCE); ComputeKWayBoundary(ctrl, graph, BNDTYPE_REFINE); Greedy_KWayOptimize(ctrl, graph, ctrl->niter, 0, OMODE_REFINE); } if (ctrl->contig) ASSERT(FindPartitionInducedComponents(graph, graph->where, NULL, NULL) == ctrl->nparts); IFSET(ctrl->dbglvl, METIS_DBG_TIME, gk_stopcputimer(ctrl->UncoarsenTmr)); }
void GrowKWayPartitioning(ctrl_t *ctrl, graph_t *graph) { idx_t v, i, ii, j, nvtxs, nparts, nmis, minvwgt; idx_t *xadj, *adjncy, *vwgt, *adjwgt; idx_t *where, *pwgts, *minwgt, *maxwgt, *nbrwgt; idx_t *perm; real_t ubfactor_original; WCOREPUSH; nvtxs = graph->nvtxs; xadj = graph->xadj; adjncy = graph->adjncy; adjwgt = graph->adjwgt; vwgt = graph->vwgt; where = graph->where; pwgts = graph->pwgts; nparts = ctrl->nparts; /* setup the weight intervals of the various subdomains */ minwgt = iwspacemalloc(ctrl, nparts); maxwgt = iwspacemalloc(ctrl, nparts); for (i=0; i<nparts; i++) { maxwgt[i] = ctrl->tpwgts[i]*graph->tvwgt[0]*ctrl->ubfactors[0]; minwgt[i] = ctrl->tpwgts[i]*graph->tvwgt[0]*(1.0/ctrl->ubfactors[0]); } /* setup the initial state of the partitioning */ iset(nvtxs, nparts, where); iset(nparts, 0, pwgts); perm = iwspacemalloc(ctrl, nvtxs); /* compute the weights of the neighborhood */ nbrwgt = iwspacemalloc(ctrl, nvtxs); /* for (i=0; i<nvtxs; i++) { nbrwgt[i] = vwgt[i]; for (j=xadj[i]; j<xadj[i+1]; j++) { ii = adjncy[j]; nbrwgt[i] += vwgt[ii]/log2(2+xadj[ii+1]-xadj[ii]); } } */ for (i=0; i<nvtxs; i++) { nbrwgt[i] = 0; for (j=xadj[i]; j<xadj[i+1]; j++) nbrwgt[i] += adjwgt[j]; } minvwgt = isum(nvtxs, nbrwgt, 1)/nvtxs; #ifdef XXX perm = iwspacemalloc(ctrl, nvtxs); tperm = iwspacemalloc(ctrl, nvtxs); degrees = iwspacemalloc(ctrl, nvtxs); irandArrayPermute(nvtxs, tperm, nvtxs, 1); irandArrayPermute(nvtxs, tperm, nvtxs, 0); avgdegree = 1.0*(xadj[nvtxs]/nvtxs); for (i=0; i<nvtxs; i++) { bnum = sqrt(1+xadj[i+1]-xadj[i]); degrees[i] = (bnum > avgdegree ? avgdegree : bnum); } BucketSortKeysInc(ctrl, nvtxs, avgdegree, degrees, tperm, perm); #endif ubfactor_original = ctrl->ubfactors[0]; ctrl->ubfactors[0] = 1.05*ubfactor_original; /* find an MIS of vertices by randomly traversing the vertices and assign them to the different partitions */ irandArrayPermute(nvtxs, perm, nvtxs, 1); for (nmis=0, ii=0; ii<nvtxs; ii++) { i=perm[ii]; if (nbrwgt[i] < minvwgt) continue; if (where[i] == nparts) { pwgts[nmis] = vwgt[i]; where[i] = nmis++; /* mark first level neighbors */ for (j=xadj[i]; j<xadj[i+1]; j++) { v = adjncy[j]; if (where[v] == nparts) where[v] = nparts+1; } } if (nmis == nparts) break; } printf(" nvtxs: %"PRIDX", nmis: %"PRIDX", minvwgt: %"PRIDX", ii: %"PRIDX"\n", nvtxs, nmis, minvwgt, ii); /* if the size of the MIS is not sufficiently large, go and find some additional seeds */ if (nmis < nparts) { minvwgt = .75*minvwgt; irandArrayPermute(nvtxs, perm, nvtxs, 0); for (ii=0; ii<nvtxs; ii++) { i=perm[ii]; if (nbrwgt[i] < minvwgt) continue; if (where[i] == nparts) { pwgts[nmis] = vwgt[i]; where[i] = nmis++; /* mark first level neighbors */ for (j=xadj[i]; j<xadj[i+1]; j++) { v = adjncy[j]; if (where[v] == nparts) where[v] = nparts+1; } } if (nmis == nparts) break; } printf(" nvtxs: %"PRIDX", nmis: %"PRIDX"\n", nvtxs, nmis); } /* if the size of the MIS is not sufficiently large, go and find some additional seeds */ if (nmis < nparts) { irandArrayPermute(nvtxs, perm, nvtxs, 0); for (ii=0; ii<nvtxs; ii++) { i = perm[ii]; if (where[i] == nparts+1) { pwgts[nmis] = vwgt[i]; where[i] = nmis++; } if (nmis == nparts) break; } printf(" nvtxs: %"PRIDX", nmis: %"PRIDX"\n", nvtxs, nmis); } /* set all unassigned vertices to 'nparts' */ for (i=0; i<nvtxs; i++) { if (where[i] >= nparts) where[i] = nparts; } WCOREPOP; /* refine the partition */ ComputeKWayPartitionParams(ctrl, graph); if (ctrl->minconn) EliminateSubDomainEdges(ctrl, graph); for (i=0; i<4; i++) { ComputeKWayBoundary(ctrl, graph, BNDTYPE_BALANCE); Greedy_KWayOptimize(ctrl, graph, 10, 0, OMODE_BALANCE); /* for (k=0; k<nparts; k++) printf("%"PRIDX"\n", graph->pwgts[k]); exit(0); */ ComputeKWayBoundary(ctrl, graph, BNDTYPE_REFINE); Greedy_KWayOptimize(ctrl, graph, ctrl->niter, 1, OMODE_REFINE); Greedy_KWayEdgeCutOptimize(ctrl, graph, ctrl->niter); } ctrl->ubfactors[0] = ubfactor_original; }
/************************************************************************* * This function is the entry point of refinement **************************************************************************/ void RefineKWay(CtrlType *ctrl, GraphType *orggraph, GraphType *graph, int nparts, float *tpwgts, float ubfactor) { int i, nlevels, mustfree=0; GraphType *ptr; IFSET(ctrl->dbglvl, DBG_TIME, starttimer(ctrl->UncoarsenTmr)); /* Compute the parameters of the coarsest graph */ ComputeKWayPartitionParams(ctrl, graph, nparts); /* Take care any non-contiguity */ IFSET(ctrl->dbglvl, DBG_TIME, starttimer(ctrl->AuxTmr1)); if (ctrl->RType == RTYPE_KWAYRANDOM_MCONN) { EliminateComponents(ctrl, graph, nparts, tpwgts, 1.25); EliminateSubDomainEdges(ctrl, graph, nparts, tpwgts); EliminateComponents(ctrl, graph, nparts, tpwgts, 1.25); } IFSET(ctrl->dbglvl, DBG_TIME, stoptimer(ctrl->AuxTmr1)); /* Determine how many levels are there */ for (ptr=graph, nlevels=0; ptr!=orggraph; ptr=ptr->finer, nlevels++); for (i=0; ;i++) { /* PrintSubDomainGraph(graph, nparts, graph->where); */ if (ctrl->RType == RTYPE_KWAYRANDOM_MCONN && (i == nlevels/2 || i == nlevels/2+1)) EliminateSubDomainEdges(ctrl, graph, nparts, tpwgts); IFSET(ctrl->dbglvl, DBG_TIME, starttimer(ctrl->RefTmr)); if (2*i >= nlevels && !IsBalanced(graph->pwgts, nparts, tpwgts, 1.04*ubfactor)) { ComputeKWayBalanceBoundary(ctrl, graph, nparts); if (ctrl->RType == RTYPE_KWAYRANDOM_MCONN) Greedy_KWayEdgeBalanceMConn(ctrl, graph, nparts, tpwgts, ubfactor, 1); else Greedy_KWayEdgeBalance(ctrl, graph, nparts, tpwgts, ubfactor, 1); ComputeKWayBoundary(ctrl, graph, nparts); } switch (ctrl->RType) { case RTYPE_KWAYRANDOM: Random_KWayEdgeRefine(ctrl, graph, nparts, tpwgts, ubfactor, 10, 1); break; case RTYPE_KWAYGREEDY: Greedy_KWayEdgeRefine(ctrl, graph, nparts, tpwgts, ubfactor, 10); break; case RTYPE_KWAYRANDOM_MCONN: Random_KWayEdgeRefineMConn(ctrl, graph, nparts, tpwgts, ubfactor, 10, 1); break; } IFSET(ctrl->dbglvl, DBG_TIME, stoptimer(ctrl->RefTmr)); if (graph == orggraph) break; GKfree(&graph->gdata, LTERM); /* Deallocate the graph related arrays */ graph = graph->finer; IFSET(ctrl->dbglvl, DBG_TIME, starttimer(ctrl->ProjectTmr)); if (graph->vwgt == NULL) { graph->vwgt = idxsmalloc(graph->nvtxs, 1, "RefineKWay: graph->vwgt"); graph->adjwgt = idxsmalloc(graph->nedges, 1, "RefineKWay: graph->adjwgt"); mustfree = 1; } ProjectKWayPartition(ctrl, graph, nparts); IFSET(ctrl->dbglvl, DBG_TIME, stoptimer(ctrl->ProjectTmr)); } if (!IsBalanced(graph->pwgts, nparts, tpwgts, ubfactor)) { ComputeKWayBalanceBoundary(ctrl, graph, nparts); if (ctrl->RType == RTYPE_KWAYRANDOM_MCONN) { Greedy_KWayEdgeBalanceMConn(ctrl, graph, nparts, tpwgts, ubfactor, 8); Random_KWayEdgeRefineMConn(ctrl, graph, nparts, tpwgts, ubfactor, 10, 0); } else { Greedy_KWayEdgeBalance(ctrl, graph, nparts, tpwgts, ubfactor, 8); Random_KWayEdgeRefine(ctrl, graph, nparts, tpwgts, ubfactor, 10, 0); } } /* Take care any trivial non-contiguity */ IFSET(ctrl->dbglvl, DBG_TIME, starttimer(ctrl->AuxTmr2)); EliminateComponents(ctrl, graph, nparts, tpwgts, ubfactor); IFSET(ctrl->dbglvl, DBG_TIME, stoptimer(ctrl->AuxTmr2)); if (mustfree) GKfree(&graph->vwgt, &graph->adjwgt, LTERM); IFSET(ctrl->dbglvl, DBG_TIME, stoptimer(ctrl->UncoarsenTmr)); }