00001
00005
00016 #include <charm++.h>
00017
00018 #include "RecBisectBfLB.h"
00019
00020 extern "C" {
00021 Graph * g_initGraph(int v, int e);
00022 void g_freeGraph(Graph* g);
00023 void g_nextVertex(Graph *g, int v, float w);
00024 void g_finishVertex(Graph *g);
00025 void g_addEdge(Graph *g, int w, float w2);
00026 float graph_weightof(Graph *g, int vertex);
00027 int g_numNeighbors(Graph *g, int node);
00028 int g_getNeighbor(Graph *g, int d , int i);
00029 void g_printGraph(Graph *g);
00030
00031 int bvset_size(BV_Set *);
00032 int bvset_find(BV_Set *, int i);
00033 void bvset_enumerate(BV_Set * s1, int **p1, int *numP1);
00034 void bvset_insert(BV_Set *ss1, int t1);
00035 BV_Set *makeSet(int *nodes, int numNodes, int V);
00036 BV_Set *makeEmptySet( int V);
00037 void destroySet(BV_Set* s);
00038 }
00039
00040 extern int quietModeRequested;
00041
00042 CreateLBFunc_Def(RecBisectBfLB, "Recursive partitioning with Breadth first enumeration")
00043
00044 RecBisectBfLB::RecBisectBfLB(const CkLBOptions &opt): CBase_RecBisectBfLB(opt)
00045 {
00046 lbname = (char*)"RecBisectBfLB";
00047 if (CkMyPe() == 0 && !quietModeRequested)
00048 CkPrintf("CharmLB> RecBisectBfLB created.\n");
00049 }
00050
00051 bool RecBisectBfLB::QueryBalanceNow(int _step)
00052 {
00053
00054 return true;
00055 }
00056
00057 void RecBisectBfLB::work(LDStats* stats)
00058 {
00059 int i;
00060 int numPartitions = CkNumPes();
00061
00062 PartitionList *partitions;
00063
00064 CkPrintf("[%d] RecBisectBfLB strategy\n",CkMyPe());
00065 ObjGraph og(numPartitions, stats);
00066
00067 Graph *g = convertGraph( &og);
00068 CkPrintf("[%d] RecBisectBfLB: graph converted\n",CkMyPe());
00069
00070
00071 int* nodes = (int *) malloc(sizeof(int)*g->V);
00072
00073 for (i=0; i<g->V; i++)
00074 nodes[i] = i;
00075
00076
00077
00078
00079 partitions = (PartitionList *) malloc(sizeof(PartitionList));
00080 partitions->next = 0;
00081 partitions->max = numPartitions;
00082 partitions->partitions = (PartitionRecord *)
00083 malloc(sizeof(PartitionRecord)* numPartitions);
00084
00085 recursivePartition(numPartitions, g, nodes, g->V, partitions);
00086
00087
00088
00089 g_freeGraph(g);
00090
00091
00092
00093 for (i=0; i<partitions->max; i++) {
00094
00095 for (int j=0; j< partitions->partitions[i].size; j++) {
00096
00097 const int objref = partitions->partitions[i].nodeArray[j];
00098 ObjGraph::Node n = og.GraphNode(objref);
00099
00100
00101 if (n.proc != i) {
00102 CmiAssert(stats->from_proc[n.index] == n.proc);
00103 stats->to_proc[n.index] = i;
00104 }
00105 }
00106 free(partitions->partitions[i].nodeArray);
00107 }
00108 free(partitions->partitions);
00109 free(partitions);
00110
00111 CmiPrintf("returning from partitioner strategy\n");
00112 }
00113
00114
00115 Graph *
00116 RecBisectBfLB::convertGraph(ObjGraph *og) {
00117
00118 Graph *g;
00119
00120 int V, E, i;
00121
00122 V = og->NodeCount();
00123 E = og->EdgeCount();
00124
00125 g = g_initGraph(V, E);
00126
00127
00128
00129
00130 for (i =0; i<V; i++) {
00131 g_nextVertex(g, i, og->LoadOf(i));
00132
00133 ObjGraph::Node n = og->GraphNode(i);
00134 ObjGraph::Edge *l;
00135
00136
00137
00138 l = n.edges_from();
00139 while (l) {
00140
00141 g_addEdge(g, l->to_node, 1.0);
00142 l = l->next_from();
00143 }
00144
00145 l = n.edges_to();
00146 while (l) {
00147
00148 g_addEdge(g, l->from_node, 1.0);
00149 l = l->next_to();
00150 }
00151 g_finishVertex(g);
00152 }
00153 return g;
00154 }
00155
00156 void RecBisectBfLB::partitionInTwo(Graph *g, int nodes[], int numNodes,
00157 int ** pp1, int *numP1, int **pp2, int *numP2,
00158 int ratio1, int ratio2)
00159 {
00160 int r1, r2;
00161 int i;
00162 float w, weight1, weight2;
00163 BV_Set *all, *s1, *s2;
00164 IntQueue * q1, *q2;
00165 int * p1, *p2;
00166
00167
00168
00169
00170
00171
00172
00173 if (numNodes <2) CkAbort("error: too few objects to paritition\n");
00174 r1 = nodes[0];
00175
00176 r2 = nodes[1];
00177 weight1 = graph_weightof(g, r1);
00178 weight2 = graph_weightof(g, r2);
00179
00180
00181
00182
00183
00184 for (i=2; i<numNodes; i++) {
00185 w = graph_weightof(g, nodes[i]);
00186 if (w > weight1) { weight1 = w; r1 = nodes[i]; }
00187 else if (w > weight2) { weight2 = w; r2 = nodes[i]; }
00188 }
00189
00190
00191 all = makeSet(nodes, numNodes, g->V);
00192 s1 = makeEmptySet(g->V);
00193 s2 = makeEmptySet(g->V);
00194
00195 q1 = new IntQueue(g->V);
00196 q2 = new IntQueue(g->V);
00197
00198 q1->enq(r1);
00199 q2->enq(r2);
00200
00201
00202 weight1 = 0; weight2 = 0;
00203 while ( (bvset_size(s1) + bvset_size(s2)) < numNodes ) {
00204
00205 if (weight1*ratio2 < weight2*ratio1)
00206 weight1 += addToQ(q1, g, all, s1,s2);
00207 else
00208 weight2 += addToQ(q2, g, all, s2,s1);
00209 }
00210
00211 bvset_enumerate(s1, &p1, numP1);
00212 bvset_enumerate(s2, &p2, numP2);
00213 *pp1 = p1;
00214 *pp2 = p2;
00215 destroySet(s1);
00216 destroySet(s2);
00217 delete q1;
00218 delete q2;
00219
00220
00221 }
00222
00223 int
00224 RecBisectBfLB::findNextUnassigned(int max, BV_Set * all,
00225 BV_Set * s1, BV_Set * s2)
00226 {
00227 int i;
00228 for (i=0; i<max; i++) {
00229 if (bvset_find(all, i))
00230 if ( (!bvset_find(s1,i)) && (!bvset_find(s2,i)) )
00231 return i;
00232 }
00233 return (max + 1);
00234 }
00235
00236 float RecBisectBfLB::addToQ(IntQueue * q, Graph *g, BV_Set * all,
00237 BV_Set * s1, BV_Set * s2)
00238 {
00239 int t1, doneUpto;
00240 float weightAdded;
00241
00242 weightAdded = 0.0;
00243
00244 if (q->isEmpty()) {
00245 doneUpto = findNextUnassigned(g->V, all, s1, s2);
00246 if (doneUpto < g->V) q->enq(doneUpto);
00247 }
00248 if (!q->isEmpty() ) {
00249 t1 = q->deq();
00250 if (bvset_find(all, t1))
00251 if ( (!bvset_find(s1, t1)) && ( !bvset_find(s2, t1)) ) {
00252 bvset_insert(s1, t1);
00253 weightAdded = graph_weightof(g, t1);
00254
00255 enqChildren(q, g, all, s1, s2, t1);
00256 }
00257 }
00258 return weightAdded;
00259 }
00260
00261 void RecBisectBfLB::enqChildren(IntQueue * q, Graph *g, BV_Set * all,
00262 BV_Set * s1, BV_Set * s2, int node)
00263 {
00264 int nbrs, i, j;
00265
00266 nbrs = g_numNeighbors(g, node);
00267 for (i=0; i<nbrs; i++) {
00268 j = g_getNeighbor(g, node, i);
00269 if ( (bvset_find(all,j)) && (!bvset_find(s1,j))
00270 && (!bvset_find(s2,j)) ) {
00271 q->enq(j);
00272 }
00273 }
00274 }
00275
00276
00277 void RecBisectBfLB::addPartition(PartitionList * partitions,
00278 int * nodes, int num)
00279 {
00280 int i;
00281
00282 i = partitions->next++;
00283 partitions->partitions[i].size = num;
00284 partitions->partitions[i].nodeArray = nodes ;
00285 }
00286
00287 void RecBisectBfLB::printPartitions(PartitionList * partitions)
00288 {
00289 int i,j;
00290
00291
00292 CmiPrintf("\n**************************\n The Partitions are: \n");
00293 for (i=0; i<partitions->max; i++) {
00294 CmiPrintf("[%d] (%d) : \t", i, partitions->partitions[i].size);
00295 for (j=0; j< partitions->partitions[i].size; j++)
00296 CmiPrintf("%d ", partitions->partitions[i].nodeArray[j]);
00297 CmiPrintf("\n");
00298 }
00299 }
00300
00301 void RecBisectBfLB::recursivePartition(int numParts, Graph *g,
00302 int nodes[], int numNodes,
00303 PartitionList *partitions)
00304 {
00305 int *p1, *p2;
00306 int first, second;
00307 int numP1, numP2;
00308
00309 if (numParts < 2) {
00310 addPartition(partitions, nodes, numNodes);
00311 } else {
00312 first = numParts/2;
00313 second = numParts - first;
00314 partitionInTwo(g, nodes, numNodes, &p1, &numP1, &p2, &numP2, first,second);
00315 recursivePartition(first, g, p1, numP1, partitions);
00316 recursivePartition(second, g, p2, numP2, partitions);
00317 free(nodes);
00318 }
00319 }
00320
00321 #include "RecBisectBfLB.def.h"
00322
00323
00324 #define printf CmiPrintf
00325 void printPartition(Graph * g, int nodes[], int numNodes)
00326 {
00327 int i;
00328 for (i=0; i<numNodes; i++)
00329 printf("\t%d", nodes[i]);
00330 printf("\n");
00331
00332 }
00333
00334 int intSqrt(int x)
00335 {
00336 int y=1;
00337 while (y*y<x) y++;
00338 return y;
00339 }
00340
00341 Graph * g_initGraph(int V, int E) {
00342 Graph *g;
00343
00344 g = (Graph *) malloc(sizeof(Graph));
00345
00346 g->V = V;
00347 g->E = E ;
00348 g->vertices = (VertexRecord *) malloc(V*sizeof(VertexRecord));
00349 g->edges = (int *) malloc( 2* (1 + g->E) * sizeof(int));
00350 g->currentVertex = -1;
00351 g->currentEdge = 0;
00352 return g;
00353 }
00354
00355 void g_freeGraph(Graph* g)
00356 {
00357 free(g->vertices);
00358 g->vertices=0;
00359 free(g->edges);
00360 g->edges = 0;
00361 free(g);
00362 }
00363
00364 void g_nextVertex(Graph *g, int v, float weight)
00365 {
00366 int current;
00367
00368 g->currentVertex++;
00369 current = g->currentVertex;
00370 if(current >= g->V)
00371 printf("current overflow\n");
00372 g->vertices[current].index = v;
00373 g->vertices[current].weight = weight;
00374 g->vertices[current].firstEdge = g->currentEdge;
00375 g->vertices[current].numEdges = 0;
00376
00377
00378 }
00379
00380
00381 void g_addEdge(Graph *g, int w, float weight)
00382 {
00383
00384 int v, i;
00385 v = g->currentVertex;
00386
00387
00388
00389
00390
00391
00392
00393 i = g->vertices[v].firstEdge;
00394 while (i < g->currentEdge) {
00395 if (g->edges[i] == w) {
00396 return; }
00397 i++;
00398 }
00399
00400
00401
00402 g->vertices[v].numEdges++;
00403 g->edges[g->currentEdge++] = w;
00404
00405 }
00406
00407 void g_finishVertex(Graph *g) {
00408
00409 if (g->vertices[g->currentVertex].numEdges != g->currentEdge - g->vertices[g->currentVertex].firstEdge)
00410 printf("Error in finishVertex\n");
00411
00412
00413 }
00414
00415
00416 Graph *generateRandomGraph(int numNodes) {
00417
00418 Graph *g;
00419
00420 int i, stride, n;
00421
00422 g = (Graph *) malloc(sizeof(Graph));
00423 g->vertices = (VertexRecord *) malloc(numNodes*sizeof(VertexRecord));
00424 g->V = numNodes;
00425
00426 g->E = 4* g->V ;
00427 g->edges = (int *) malloc( (1 + g->E) * sizeof(int));
00428 stride = intSqrt(g->V);
00429
00430 n = 0;
00431 for (i = 0; i<g->V; i++) {
00432 g->vertices[i].index = i;
00433 g->vertices[i].firstEdge = n;
00434 g->vertices[i].numEdges = 4;
00435 g->vertices[i].weight = 1.0;
00436
00437 g->edges[n++] = (i + numNodes - 1) % numNodes;
00438 g->edges[n++] = (i + 1) % numNodes;
00439
00440 g->edges[n++] = (i +numNodes - stride) % numNodes;
00441 g->edges[n++] = (i + stride) % numNodes;
00442
00443 }
00444 return g;
00445 }
00446
00447
00448
00449
00450 void g_printGraph(Graph *g) {
00451 int i, j;
00452
00453 CmiPrintf("%d vertices, %d edges \n", g->V, g->E);
00454 for (i=0; i< g->V; i++)
00455 { printf("\n %d: (%d)\t", i, g->vertices[i].numEdges );
00456 for (j=0; j<g->vertices[i].numEdges; j++)
00457 printf(" %d,", g->edges[g->vertices[i].firstEdge + j ]); }
00458
00459 }
00460
00461 int g_numNeighbors(Graph *g, int node) {
00462
00463 return g->vertices[node].numEdges;
00464 }
00465
00466 int g_getNeighbor(Graph *g, int node, int i) {
00467
00468 if (i >= g->vertices[node].numEdges) {
00469 printf("error: node %d has only %d neighbors. You asked for %d'th nbr\n",
00470 node, g->vertices[node].numEdges, i);
00471 return 0;
00472 }
00473 return g->edges [ g->vertices[node].firstEdge + i];
00474
00475 }
00476
00477 float graph_weightof(Graph *g, int vertex) {
00478
00479 return g->vertices[vertex].weight;
00480
00481 }
00482