// -------------------------------------------------------------------- // repartitionHMetis() // /// \brief Repartitions the two subpartitions using the hMetis min-cut library. /// /// The number of cut nets between the two partitions will be minimized. // // -------------------------------------------------------------------- void repartitionHMetis(Partition *parent) { #if defined(NO_HMETIS) printf("QPAR_02 : \t\tERROR: hMetis not available. Ignoring.\n"); #else int n,c,t, i; float area; int *edgeConnections = NULL; int *partitionAssignment = (int *)calloc(g_place_numCells, sizeof(int)); int *vertexWeights = (int *)calloc(g_place_numCells, sizeof(int)); int *edgeDegree = (int *)malloc(sizeof(int)*(g_place_numNets+1)); int numConnections = 0; int numEdges = 0; float initial_cut; int targets = 0; ConcreteCell *cell = NULL; int options[9]; int afterCuts = 0; assert(parent); assert(parent->m_sub1); assert(parent->m_sub2); printf("QPAR-02 : \t\trepartitioning with hMetis\n"); // count edges edgeDegree[0] = 0; for(n=0; n<g_place_numNets; n++) if (g_place_concreteNets[n]) if (g_place_concreteNets[n]->m_numTerms > 1) { numConnections += g_place_concreteNets[n]->m_numTerms; edgeDegree[++numEdges] = numConnections; } if (parent->m_vertical) { // vertical initial_cut = parent->m_sub2->m_bounds.x; // initialize all cells for(c=0; c<g_place_numCells; c++) if (g_place_concreteCells[c]) { if (g_place_concreteCells[c]->m_x < initial_cut) partitionAssignment[c] = 0; else partitionAssignment[c] = 1; } // initialize cells in partition 1 for(t=0; t<parent->m_sub1->m_numMembers; t++) if (parent->m_sub1->m_members[t]) { cell = parent->m_sub1->m_members[t]; vertexWeights[cell->m_id] = getCellArea(cell); // pay attention to cells that are close to the cut if (abs(cell->m_x-initial_cut) < parent->m_bounds.w*REPARTITION_TARGET_FRACTION) { targets++; partitionAssignment[cell->m_id] = -1; } } // initialize cells in partition 2 for(t=0; t<parent->m_sub2->m_numMembers; t++) if (parent->m_sub2->m_members[t]) { cell = parent->m_sub2->m_members[t]; vertexWeights[cell->m_id] = getCellArea(cell); // pay attention to cells that are close to the cut if (abs(cell->m_x-initial_cut) < parent->m_bounds.w*REPARTITION_TARGET_FRACTION) { targets++; partitionAssignment[cell->m_id] = -1; } } } else { // horizontal initial_cut = parent->m_sub2->m_bounds.y; // initialize all cells for(c=0; c<g_place_numCells; c++) if (g_place_concreteCells[c]) { if (g_place_concreteCells[c]->m_y < initial_cut) partitionAssignment[c] = 0; else partitionAssignment[c] = 1; } // initialize cells in partition 1 for(t=0; t<parent->m_sub1->m_numMembers; t++) if (parent->m_sub1->m_members[t]) { cell = parent->m_sub1->m_members[t]; vertexWeights[cell->m_id] = getCellArea(cell); // pay attention to cells that are close to the cut if (abs(cell->m_y-initial_cut) < parent->m_bounds.h*REPARTITION_TARGET_FRACTION) { targets++; partitionAssignment[cell->m_id] = -1; } } // initialize cells in partition 2 for(t=0; t<parent->m_sub2->m_numMembers; t++) if (parent->m_sub2->m_members[t]) { cell = parent->m_sub2->m_members[t]; vertexWeights[cell->m_id] = getCellArea(cell); // pay attention to cells that are close to the cut if (abs(cell->m_y-initial_cut) < parent->m_bounds.h*REPARTITION_TARGET_FRACTION) { targets++; partitionAssignment[cell->m_id] = -1; } } } options[0] = 1; // any non-default values? options[1] = 3; // num bisections options[2] = 1; // grouping scheme options[3] = 1; // refinement scheme options[4] = 1; // cycle refinement scheme options[5] = 0; // reconstruction scheme options[6] = 0; // fixed assignments? options[7] = 12261980; // random seed options[8] = 0; // debugging level edgeConnections = (int *)malloc(sizeof(int)*numConnections); i = 0; for(n=0; n<g_place_numNets; n++) if (g_place_concreteNets[n]) { if (g_place_concreteNets[n]->m_numTerms > 1) for(t=0; t<g_place_concreteNets[n]->m_numTerms; t++) edgeConnections[i++] = g_place_concreteNets[n]->m_terms[t]->m_id; } HMETIS_PartRecursive(g_place_numCells, numEdges, vertexWeights, edgeDegree, edgeConnections, NULL, 2, (int)(100*MAX_PARTITION_NONSYMMETRY), options, partitionAssignment, &afterCuts); /* printf("HMET-20 : \t\t\tbalance before %d / %d ... ", parent->m_sub1->m_numMembers, parent->m_sub2->m_numMembers); */ // reassign members to subpartitions parent->m_sub1->m_numMembers = 0; parent->m_sub1->m_area = 0; parent->m_sub2->m_numMembers = 0; parent->m_sub2->m_area = 0; parent->m_sub1->m_members = (ConcreteCell**)realloc(parent->m_sub1->m_members, sizeof(ConcreteCell*)*parent->m_numMembers); parent->m_sub2->m_members = (ConcreteCell**)realloc(parent->m_sub2->m_members, sizeof(ConcreteCell*)*parent->m_numMembers); for(t=0; t<parent->m_numMembers; t++) if (parent->m_members[t]) { cell = parent->m_members[t]; area = getCellArea(cell); if (partitionAssignment[cell->m_id] == 0) { parent->m_sub1->m_members[parent->m_sub1->m_numMembers++] = cell; parent->m_sub1->m_area += area; } else { parent->m_sub2->m_members[parent->m_sub2->m_numMembers++] = cell; parent->m_sub2->m_area += area; } } /* printf("after %d / %d\n", parent->m_sub1->m_numMembers, parent->m_sub2->m_numMembers); */ // cout << "HMET-21 : \t\t\tloc: " << initial_cut << " targetting: " << targets*100/parent->m_members.length() << "%" << endl; // cout << "HMET-22 : \t\t\tstarting cuts= " << beforeCuts << " final cuts= " << afterCuts << endl; free(edgeConnections); free(vertexWeights); free(edgeDegree); free(partitionAssignment); #endif }
/* May 30th, Weinan: one problem I have just found is that I need to * establish a kind of checking table to connect my global vertex * number with local vertex number to be used in the HMETIS_PartRecursive * function calling. */ static int cutNode(struct node * source, struct node * left, struct node * right, int ub){ int nvtxs, nhedges; int * vwgts = NULL; int * eptr = NULL; int * eind = NULL; int * hewgts = NULL; int nparts; int ubfactor; int * options = NULL; int * part = NULL; int * edgecut = NULL; int tmp, i, j, k, l, tmpNO, flag, found, group0, group1, index0, index1; /* this is the table used to correspond global vertice number with * local vertice number. */ int * checkTable; /* number of vertices */ nvtxs = source->numberPoints; checkTable = (int *)calloc(nvtxs, sizeof(int)); if(checkTable == NULL) { printf("cannot allocate memory for checkTable! \n"); return -1; } /* load the vertice's number into the checkTable */ for(i=0; i<nvtxs; i++){ checkTable[i] = source->points[i]; }/* end for */ /* number of edges */ tmp=0; for(i=0; i<nvtxs; i++){ for(j=0; j<points[source->points[i]].length; j++){ /* decide a point whether belongs to a node */ if(belongs(source, points[source->points[i]].edges[j].pointNO)==1) /* !!!!!! */ tmp++; }/* end for j*/ }/* end for i*/ nhedges = tmp; /* weight of the vertices, because * the vertices are not weighted, so * according to p13 of the hMETIS manual, * vwgts can be NULL. */ vwgts = NULL; /* eptr and eind */ /* because all my edges are of * size 2, so it makes things * easier. */ tmp = nhedges+1; eptr = (int *)calloc(tmp, sizeof(int)); if(eptr == NULL) { printf("cannot allocate memory for eptr! \n"); return -1; } for(i=0; i<tmp; i++) eptr[i]=i*2; /* when loading eind, need to check the checkTable */ eind = (int *)calloc(2*tmp, sizeof(int)); if(eind == 0) { printf("cannot allocate memory for eind! \n"); return -1; } k = 0; for(i=0; i<nvtxs; i++){ for(j=0; j<points[source->points[i]].length; j++){ /* decide a point whether belongs to a node */ if(belongs(source, points[source->points[i]].edges[j].pointNO)==1){ /* eind[k] = source->points[i];*/ eind[k] = i; k++; /* eind[k] = points[source->points[i]].edges[j].pointNO; */ tmpNO = points[source->points[i]].edges[j].pointNO; flag = 0; for(l=0; l<nvtxs; l++){ if (tmpNO == checkTable[l]){ flag = 1; found = l; break; } } if(flag == 1) eind[k] = found; else { printf("some thing wrong with checkTable! \n"); return -1; }/* end if...else... */ k++; }/* end if */ }/* end for j*/ }/* end for i*/ if(k != 2*nhedges){ printf("some thing wrong with eind! \n"); return -1; }/* end if */ /* hewgts: an array of size nhedges that stores the weight * of the hyperedges. */ hewgts = (int *)calloc(nhedges, sizeof(int)); if(hewgts == 0) { printf("cannot allocate memory for hewgts! \n"); return -1; } k = 0; for(i=0; i<nvtxs; i++){ for(j=0; j<points[source->points[i]].length; j++){ /* decide a point whether belongs to a node */ if(belongs(source, points[source->points[i]].edges[j].pointNO)==1){ /*!!!!!! here I have to do a cast becasue now similarity is a double */ hewgts[k] = (int)(points[source->points[i]].edges[j].similarity*DIAG); k++; }/* end if */ }/* end for j*/ }/* end for i*/ if(k != nhedges){ printf("some thing wrong with hewgts! \n"); return -1; }/* end if */ /* nparts: number of desired partitions */ nparts = 2; /* ubfactor: relative imbalance factor */ ubfactor = ub; /* options */ /* note that is options[0]=0, * then default values are used. */ options = (int *)calloc(9, sizeof(int)); if(options == 0) { printf("cannot allocate memory for options! \n"); return -1; } options[0] = 0; /* part */ part = (int *)calloc(nvtxs, sizeof(int)); if(part == 0) { printf("cannot allocate memory for part! \n"); return -1; } /* edgecut */ edgecut = (int *)calloc(1, sizeof(int)); if(edgecut == 0) { printf("cannot allocate memory for edgecut! \n"); return -1; } HMETIS_PartRecursive(nvtxs, nhedges, vwgts, eptr, eind, hewgts, nparts, ubfactor, options, part, edgecut); group0 = 0; group1 = 0; for(i=0; i<nvtxs; i++){ if(part[i] == 0) group0++; else if(part[i] == 1) group1++; else { printf("something wrong with part. \n"); return -1; }/* end if..else...*/ }/* end for */ left->numberPoints = group0; right->numberPoints = group1; left->points = (int *)calloc(group0, sizeof(int)); if(left->points == NULL) { printf("cannot allocate memory for left->points \n"); return -1; } right->points = (int *)calloc(group1, sizeof(int)); if(right->points == NULL) { printf("cannot allocate memory for right->points \n"); return -1; } left->left = NULL; left->right = NULL; right->left = NULL; right->right = NULL; index0 = 0; index1 = 0; for(i=0; i<nvtxs; i++){ if(part[i] == 0) { left->points[index0] = checkTable[i]; index0++; } else if(part[i] == 1) { right->points[index1] = checkTable[i]; index1++; } else { printf("something wrong with part. \n"); return -1; }/* end if..else...*/ }/* end for */ if(index0!=group0 || index1!=group1) { printf("some thing wrong with index0-1. \n"); return -1; } free(vwgts); free(eptr); free(eind); free(hewgts); free(options); free(part); free(edgecut); free(checkTable); return 1; }/* end cutNode */