3 * Updated by Abhinav Bhatele, 2010-11-26 to use ckgraph
16 CreateLBFunc_Def(MetisLB, "Use Metis(tm) to partition object graph")
18 MetisLB::MetisLB(const CkLBOptions &opt): CBase_MetisLB(opt)
22 CkPrintf("[%d] MetisLB created\n",CkMyPe());
25 void MetisLB::work(LDStats* stats)
27 /** ========================== INITIALIZATION ============================= */
28 ProcArray *parr = new ProcArray(stats);
29 ObjGraph *ogr = new ObjGraph(stats);
31 /** ============================= STRATEGY ================================ */
32 if (_lb_args.debug() >= 2) {
33 CkPrintf("[%d] In MetisLB Strategy...\n", CkMyPe());
36 // convert ObjGraph to the adjacency structure
37 int numVertices = ogr->vertices.size(); // number of vertices
38 int numEdges = 0; // number of edges
43 /** remove duplicate edges from recvFrom */
44 for(i = 0; i < numVertices; i++) {
45 for(j = 0; j < ogr->vertices[i].sendToList.size(); j++) {
46 vert = ogr->vertices[i].sendToList[j].getNeighborId();
47 for(k = 0; k < ogr->vertices[i].recvFromList.size(); k++) {
48 if(ogr->vertices[i].recvFromList[k].getNeighborId() == vert) {
49 ogr->vertices[i].sendToList[j].setNumBytes(ogr->vertices[i].sendToList[j].getNumBytes() + ogr->vertices[i].recvFromList[k].getNumBytes());
50 ogr->vertices[i].recvFromList.erase(ogr->vertices[i].recvFromList.begin() + k);
56 /** the object load is normalized to an integer between 0 and 256 */
57 for(i = 0; i < numVertices; i++) {
58 if(ogr->vertices[i].getVertexLoad() > maxLoad)
59 maxLoad = ogr->vertices[i].getVertexLoad();
60 numEdges = numEdges + ogr->vertices[i].sendToList.size() + ogr->vertices[i].recvFromList.size();
64 idx_t *xadj = new idx_t[numVertices + 1];
65 /* id of the neighbors */
66 idx_t *adjncy = new idx_t[numEdges];
67 /* weights of the vertices */
68 idx_t *vwgt = new idx_t[numVertices];
69 /* weights of the edges */
70 idx_t *adjwgt = new idx_t[numEdges];
73 double ratio = 256.0/maxLoad;
75 for(i = 0; i < numVertices; i++) {
77 vwgt[i] = (int)ceil(ogr->vertices[i].getVertexLoad() * ratio);
78 for(j = 0; j < ogr->vertices[i].sendToList.size(); j++) {
79 adjncy[edgeNum] = ogr->vertices[i].sendToList[j].getNeighborId();
80 adjwgt[edgeNum] = ogr->vertices[i].sendToList[j].getNumBytes();
83 for(j = 0; j < ogr->vertices[i].recvFromList.size(); j++) {
84 adjncy[edgeNum] = ogr->vertices[i].recvFromList[j].getNeighborId();
85 adjwgt[edgeNum] = ogr->vertices[i].recvFromList[j].getNumBytes();
90 CkAssert(edgeNum == numEdges);
92 idx_t edgecut; // number of edges cut by the partitioning
95 idx_t options[METIS_NOPTIONS];
96 METIS_SetDefaultOptions(options);
97 //options[METIS_OPTION_PTYPE] = METIS_PTYPE_RB;
99 options[METIS_OPTION_NUMBERING] = 0;
101 // number of constrains
103 // number of partitions
104 idx_t numPes = parr->procs.size();
106 // allow 10% imbalance
109 // mapping of objs to partitions
110 pemap = new idx_t[numVertices];
112 // Specifies size of vertices for computing the total communication volume
114 // This array of size nparts specifies the desired weight for each partition
115 // and setting it to NULL indicates graph should be equally divided among
117 real_t *tpwgts = NULL;
120 if (WEIGHTED == option) {
121 // set up the different weights between 0 and 1
122 tpwgts = new real_t[numPes];
123 for (i = 0; i < numPes; i++) {
124 tpwgts[i] = 1.0/(real_t)numPes;
126 } else if (MULTI_CONSTRAINT == option) {
127 CkAbort("Multiple constraints not implemented.\n");
130 // numVertices: num vertices in the graph; ncon: num balancing constrains
131 // xadj, adjncy: of size n+1 and adjncy of 2m, adjncy[xadj[i]] through and
132 // including adjncy[xadj[i+1]-1];
133 // vwgt: weight of the vertices; vsize: amt of data that needs to be sent
134 // for ith vertex is vsize[i]
135 // adjwght: the weight of edges; numPes: total parts
136 // tpwghts: target partition weight, can pass NULL to equally divide
137 // ubvec: of size ncon to indicate allowed load imbalance tolerance (> 1.0)
138 // options: array of options; edgecut: stores the edgecut; pemap: mapping
139 METIS_PartGraphRecursive(&numVertices, &ncon, xadj, adjncy, vwgt, vsize, adjwgt,
140 &numPes, tpwgts, ubvec, options, &edgecut, pemap);
149 if (_lb_args.debug() >= 1) {
150 CkPrintf("[%d] MetisLB done! \n", CkMyPe());
153 for(i = 0; i < numVertices; i++) {
154 if(pemap[i] != ogr->vertices[i].getCurrentPe())
155 ogr->vertices[i].setNewPe(pemap[i]);
160 /** ============================== CLEANUP ================================ */
161 ogr->convertDecisions(stats);
166 #include "MetisLB.def.h"