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
00041
00042 CreateLBFunc_Def(RecBisectBfLB, "Recursive partitioning with Breadth first enumeration")
00043
00044 RecBisectBfLB::RecBisectBfLB(const CkLBOptions &opt): CentralLB(opt)
00045 {
00046 lbname = (char*)"RecBisectBfLB";
00047 if (CkMyPe() == 0)
00048 CkPrintf("[%d] RecBisectBfLB created\n",CkMyPe());
00049 }
00050
00051 CmiBool RecBisectBfLB::QueryBalanceNow(int _step)
00052 {
00053
00054 return CmiTrue;
00055 }
00056
00057 void RecBisectBfLB::work(LDStats* stats)
00058 {
00059 int i;
00060 int numPartitions = stats->n_pes;
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