00001
00002
00003
00004
00005
00006
00007
00008
00009 #include <math.h>
00010 #include <stdlib.h>
00011 #include "TopoCentLB.decl.h"
00012 #include "TopoCentLB.h"
00013
00014 #define alpha PER_MESSAGE_SEND_OVERHEAD_DEFAULT
00015 #define beta PER_BYTE_SEND_OVERHEAD_DEFAULT
00016 #define DEG_THRES 0.50
00017
00018
00019
00020 #define make_mapping 0
00021
00022 extern int quietModeRequested;
00023
00024 CreateLBFunc_Def(TopoCentLB,"Balance objects based on the network topology")
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036 TopoCentLB::TopoCentLB(const CkLBOptions &opt) : CBase_TopoCentLB (opt)
00037 {
00038 lbname = "TopoCentLB";
00039 if (CkMyPe () == 0 && !quietModeRequested) {
00040 CkPrintf("CharmLB> TopoCentLB created.\n");
00041 }
00042 }
00043
00044
00045 bool TopoCentLB::QueryBalanceNow (int _step)
00046 {
00047 return true;
00048 }
00049
00050 TopoCentLB::~TopoCentLB(){
00051 if(topo) delete topo;
00052 }
00053
00054
00055
00056 void TopoCentLB::computePartitions(CentralLB::LDStats *stats,int count,int *newmap)
00057 {
00058
00059 int numobjs = stats->n_objs;
00060 int i, j, m;
00061
00062
00063 double *objtime = new double[numobjs];
00064 int *objwt = new int[numobjs];
00065 int *origmap = new int[numobjs];
00066 LDObjHandle *handles = new LDObjHandle[numobjs];
00067
00068 for(i=0;i<numobjs;i++) {
00069 objtime[i] = 0.0;
00070 objwt[i] = 0;
00071 origmap[i] = 0;
00072 }
00073
00074
00075 for (i=0; i<stats->n_objs; i++) {
00076 LDObjData &odata = stats->objData[i];
00077 if (!odata.migratable)
00078 CmiAbort("MetisLB doesnot dupport nonmigratable object.\n");
00079 int frompe = stats->from_proc[i];
00080 origmap[i] = frompe;
00081 objtime[i] = odata.wallTime*stats->procs[frompe].pe_speed;
00082 handles[i] = odata.handle;
00083 }
00084
00085
00086 double max_objtime = objtime[0];
00087 for(i=0; i<numobjs; i++) {
00088 if(max_objtime < objtime[i])
00089 max_objtime = objtime[i];
00090 }
00091 int maxobj=0;
00092 int totalwt=0;
00093 double ratio = 1000.0/max_objtime;
00094 for(i=0; i<numobjs; i++) {
00095 objwt[i] = (int)(objtime[i]*ratio);
00096 if(maxobj<objwt[i])
00097 maxobj=objwt[i];
00098 totalwt+=objwt[i];
00099 }
00100
00101 int **comm = new int*[numobjs];
00102 for (i=0; i<numobjs; i++) {
00103 comm[i] = new int[numobjs];
00104 for (j=0; j<numobjs; j++) {
00105 comm[i][j] = 0;
00106 }
00107 }
00108
00109
00110 const int csz = stats->n_comm;
00111 for(i=0; i<csz; i++) {
00112 LDCommData &cdata = stats->commData[i];
00113
00114
00115 if(!cdata.from_proc() && cdata.receiver.get_type() == LD_OBJ_MSG){
00116 int senderID = stats->getHash(cdata.sender);
00117 int recverID = stats->getHash(cdata.receiver.get_destObj());
00118 CmiAssert(senderID < numobjs);
00119 CmiAssert(recverID < numobjs);
00120 comm[senderID][recverID] += cdata.messages;
00121 comm[recverID][senderID] += cdata.messages;
00122
00123 }
00124 else if (cdata.receiver.get_type() == LD_OBJLIST_MSG) {
00125
00126 int nobjs;
00127 const LDObjKey *objs = cdata.receiver.get_destObjs(nobjs);
00128 int senderID = stats->getHash(cdata.sender);
00129 for (j=0; j<nobjs; j++) {
00130 int recverID = stats->getHash(objs[j]);
00131 if((senderID == -1)||(recverID == -1)) {
00132 if (_lb_args.migObjOnly()) continue;
00133 else CkAbort("Error in search\n");
00134 }
00135 comm[senderID][recverID] += cdata.messages;
00136 comm[recverID][senderID] += cdata.messages;
00137 }
00138 }
00139 }
00140
00141
00142 for (i=0; i<numobjs; i++)
00143 comm[i][i] = 0;
00144
00145
00146 int *xadj = new int[numobjs+1];
00147 int numedges = 0;
00148 for(i=0;i<numobjs;i++) {
00149 for(j=0;j<numobjs;j++) {
00150 if(comm[i][j] != 0)
00151 numedges++;
00152 }
00153 }
00154 int *adjncy = new int[numedges];
00155 int *edgewt = new int[numedges];
00156 int factor = 10;
00157 xadj[0] = 0;
00158 int count4all = 0;
00159 for (i=0; i<numobjs; i++) {
00160 for (j=0; j<numobjs; j++) {
00161 if (comm[i][j] != 0) {
00162 adjncy[count4all] = j;
00163 edgewt[count4all++] = comm[i][j]/factor;
00164 }
00165 }
00166 xadj[i+1] = count4all;
00167 }
00168
00169
00170 int wgtflag = 3;
00171 int numflag = 0;
00172 int options[5];
00173 int edgecut;
00174 options[0] = 0;
00175
00176 if (count < 1) {
00177 CkPrintf("error: Number of Pe less than 1!");
00178 }
00179 else if (count == 1) {
00180 for(m=0;m<numobjs;m++)
00181 newmap[i] = origmap[i];
00182 }
00183 else {
00184
00185
00186
00187
00188
00189
00190
00191
00192
00193
00194 METIS_PartGraphRecursive(&numobjs, xadj, adjncy, objwt, edgewt,
00195 &wgtflag, &numflag, &count, options,
00196 &edgecut, newmap);
00197 }
00198
00199
00200
00201 if(_lb_args.debug() >=2){
00202 int total=0;
00203 int *chkwt = new int[count];
00204 for(i=0;i<count;i++)
00205 chkwt[i]=0;
00206 for(i=0;i<numobjs;i++){
00207 chkwt[newmap[i]] += objwt[i];
00208 total += objwt[i];
00209 }
00210 for(i=0;i<count;i++)
00211 CkPrintf("%d -- %d\n",i,chkwt[i]);
00212 CkPrintf("Totalwt of all partitions after call to METIS:%d, Avg is %d\n",total,total/count);
00213 }
00214
00215
00216 for(i=0;i<numobjs;i++)
00217 delete[] comm[i];
00218 delete[] comm;
00219 delete[] objtime;
00220 delete[] xadj;
00221 delete[] adjncy;
00222 delete[] objwt;
00223 delete[] edgewt;
00224 delete[] handles;
00225 delete[] origmap;
00226
00227 }
00228
00229 int TopoCentLB::findMaxObjs(int *map,int totalobjs,int count)
00230 {
00231 int *max_num = new int[count];
00232 int i;
00233 int maxobjs=0;
00234
00235 for(i=0;i<count;i++)
00236 max_num[i]=0;
00237
00238 for(i=0;i<totalobjs;i++)
00239 max_num[map[i]]++;
00240
00241 for(i=0;i<count;i++)
00242 if(max_num[i]>maxobjs)
00243 maxobjs = max_num[i];
00244
00245 delete[] max_num;
00246
00247 return maxobjs;
00248 }
00249
00250 void TopoCentLB::Heapify(HeapNode *heap, int node, int heapSize)
00251 {
00252 int left = 2*node+1;
00253 int right = 2*node+2;
00254 int xchange;
00255
00256 if (left < heapSize && (heap[left].key > heap[node].key))
00257 xchange = left;
00258 else
00259 xchange = node;
00260
00261 if (right < heapSize && (heap[right].key > heap[xchange].key))
00262 xchange = right;
00263
00264 if (xchange != node) {
00265 HeapNode tmp;
00266 tmp = heap[node];
00267 heap[node] = heap[xchange];
00268 heap[xchange] = tmp;
00269 heapMapping[heap[node].node]=node;
00270 heapMapping[heap[xchange].node]=xchange;
00271 Heapify(heap,xchange,heapSize);
00272 }
00273 }
00274
00275
00276 TopoCentLB::HeapNode TopoCentLB::extractMax(HeapNode *heap,int *heapSize){
00277
00278 if(*heapSize < 1)
00279 CmiAbort("Empty Heap passed to extractMin!\n");
00280
00281 HeapNode max = heap[0];
00282 heap[0] = heap[*heapSize-1];
00283 heapMapping[heap[0].node]=0;
00284 *heapSize = *heapSize - 1;
00285 Heapify(heap,0,*heapSize);
00286 return max;
00287 }
00288
00289 void TopoCentLB::BuildHeap(HeapNode *heap,int heapSize){
00290 for(int i=heapSize/2; i >= 0; i--)
00291 Heapify(heap,i,heapSize);
00292 }
00293
00294 void TopoCentLB :: increaseKey(HeapNode *heap,int i,double wt){
00295 if(wt != -1.00){
00296 #ifdef MAX_EDGE
00297 if(wt>heap[i].key)
00298 heap[i].key = wt;
00299 #else
00300 heap[i].key += wt;
00301 #endif
00302 }
00303 int parent = (i-1)/2;
00304
00305 if(heap[parent].key >= heap[i].key)
00306 return;
00307 else {
00308 HeapNode tmp = heap[parent];
00309 heap[parent] = heap[i];
00310 heap[i] = tmp;
00311 heapMapping[heap[parent].node]=parent;
00312 heapMapping[heap[i].node]=i;
00313 increaseKey(heap,parent,-1.00);
00314 }
00315 }
00316
00317
00318
00319 void TopoCentLB :: calculateMST(PartGraph *partgraph,LBTopology *topo,int *proc_mapping,int max_comm_part) {
00320
00321 int *inHeap;
00322 double *keys;
00323 int count = partgraph->n_nodes;
00324 int i=0,j=0;
00325
00326
00327 inHeap = new int[partgraph->n_nodes];
00328 keys = new double[partgraph->n_nodes];
00329
00330 int *assigned_procs = new int[count];
00331
00332 hopCount = new double*[count];
00333 for(i=0;i<count;i++){
00334 proc_mapping[i]=-1;
00335 assigned_procs[i]=0;
00336 hopCount[i] = new double[count];
00337 for(j=0;j<count;j++)
00338 hopCount[i][j] = 0;
00339 }
00340
00341
00342 topo->get_pairwise_hop_count(hopCount);
00343
00344 int max_neighbors = topo->max_neighbors();
00345
00346 HeapNode *heap = new HeapNode[partgraph->n_nodes];
00347 heapMapping = new int[partgraph->n_nodes];
00348
00349 int heapSize = 0;
00350
00351 for(i=0;i<partgraph->n_nodes;i++){
00352 heap[i].key = 0.00;
00353 heap[i].node = i;
00354 keys[i] = 0.00;
00355 inHeap[i] = 1;
00356 heapMapping[i]=i;
00357 }
00358
00359
00360 heap[max_comm_part].key = 1.00;
00361
00362 heapSize = partgraph->n_nodes;
00363 BuildHeap(heap,heapSize);
00364
00365 int k=0,comm_cnt=0,m=0;
00366 int *commParts = new int[partgraph->n_nodes];
00367
00368
00369
00370 while(heapSize > 0){
00371
00372
00373
00374 HeapNode max = extractMax(heap,&heapSize);
00375 inHeap[max.node] = 0;
00376
00377 for(i=0;i<partgraph->n_nodes;i++){
00378 commParts[i]=-1;
00379 PartGraph::Edge wt = partgraph->edges[max.node][i];
00380 if(wt == 0)
00381 continue;
00382 if(inHeap[i]){
00383 #ifdef MAX_EDGE
00384 if(wt>keys[i])
00385 keys[i]=wt;
00386 #else
00387 keys[i] += wt;
00388 #endif
00389
00390
00391
00392
00393
00394
00395
00396
00397
00398
00399 increaseKey(heap,heapMapping[i],wt);
00400 }
00401 }
00402
00403
00404
00405
00406 if(heapSize == partgraph->n_nodes-1){
00407 proc_mapping[max.node]=0;
00408 assigned_procs[0]=1;
00409 continue;
00410 }
00411
00412 m=0;
00413
00414 comm_cnt=0;
00415
00416 double min_cost=-1;
00417 int min_cost_index=-1;
00418 double cost=0;
00419 int p=0;
00420
00421
00422 for(k=0;k<partgraph->n_nodes;k++){
00423 if(!inHeap[k] && partgraph->edges[k][max.node]){
00424 commParts[comm_cnt]=k;
00425 comm_cnt++;
00426 }
00427 }
00428
00429
00430 for(m=0;m<count;m++){
00431 if(!assigned_procs[m]){
00432 cost=0;
00433 for(p=0;p<comm_cnt;p++){
00434
00435
00436 cost += hopCount[proc_mapping[commParts[p]]][m]*partgraph->edges[commParts[p]][max.node];
00437 }
00438 if(min_cost==-1 || cost<min_cost){
00439 min_cost=cost;
00440 min_cost_index=m;
00441 }
00442 }
00443 }
00444
00445 proc_mapping[max.node]=min_cost_index;
00446 assigned_procs[min_cost_index]=1;
00447 }
00448
00449
00450 delete[] inHeap;
00451 delete[] keys;
00452 delete[] assigned_procs;
00453 delete[] heap;
00454 delete[] commParts;
00455 }
00456
00457
00458 void TopoCentLB :: work(LDStats *stats)
00459 {
00460 int proc;
00461 int i,j;
00462 int n_pes = stats->nprocs();
00463
00464 if (_lb_args.debug() >= 2) {
00465 CkPrintf("In TopoCentLB Strategy...\n");
00466 }
00467
00468
00469 for (proc = 0; proc < n_pes; proc++) {
00470 if (stats->procs[proc].available) {
00471 break;
00472 }
00473 }
00474
00475 if (proc == n_pes) {
00476 CmiAbort ("TopoCentLB: no available processors!");
00477 }
00478
00479
00480 removeNonMigratable(stats, n_pes);
00481 int *newmap = new int[stats->n_objs];
00482
00483
00484 if(make_mapping)
00485 computePartitions(stats, n_pes, newmap);
00486 else {
00487
00488 for(i=0;i<stats->n_objs;i++) {
00489 newmap[i]=stats->from_proc[i];
00490 }
00491 }
00492
00493
00494 if(_lb_args.debug() >=2){
00495 CkPrintf("Map obtained from partitioning:\n");
00496 for(i=0;i<stats->n_objs;i++)
00497 CkPrintf(" %d,%d ",i,newmap[i]);
00498 }
00499
00500 int max_objs = findMaxObjs(newmap,stats->n_objs, n_pes);
00501
00502 partgraph = new PartGraph(n_pes, max_objs);
00503
00504
00505
00506 for(i=0;i<stats->n_objs;i++)
00507 {
00508 PartGraph::Node* n = &partgraph->nodes[newmap[i]];
00509 n->obj_list[n->num_objs]=i;
00510 n->num_objs++;
00511 }
00512
00513 int *addedComm=new int[n_pes];
00514
00515 stats->makeCommHash();
00516
00517 int max_comm_part=-1;
00518
00519 double max_comm=0;
00520
00521
00522
00523 #ifdef RAND_COMM
00524 for(i = 0; i < n_pes; i++) {
00525 for(j = i+1; j < n_pes; j++) {
00526 int val;
00527 if(rand()%5==0)
00528 val=0;
00529 else
00530 val= rand()%1000;
00531
00532 partgraph->edges[i][j] = val;
00533 partgraph->edges[j][i] = val;
00534
00535 partgraph->nodes[i].comm += val;
00536 partgraph->nodes[j].comm += val;
00537
00538 if(partgraph->nodes[i].comm > max_comm){
00539 max_comm = partgraph->nodes[i].comm;
00540 max_comm_part = i;
00541 }
00542 if(partgraph->nodes[j].comm > max_comm){
00543 max_comm = partgraph->nodes[j].comm;
00544 max_comm_part = j;
00545 }
00546 }
00547 }
00548 #else
00549
00550 for(i=0;i<stats->n_comm;i++)
00551 {
00552
00553 LDCommData &cdata = stats->commData[i];
00554 if(!cdata.from_proc() && cdata.receiver.get_type() == LD_OBJ_MSG){
00555 int senderID = stats->getHash(cdata.sender);
00556 int recverID = stats->getHash(cdata.receiver.get_destObj());
00557 CmiAssert(senderID < stats->n_objs);
00558 CmiAssert(recverID < stats->n_objs);
00559
00560 if(newmap[senderID]==newmap[recverID])
00561 continue;
00562
00563 if(partgraph->edges[newmap[senderID]][newmap[recverID]] == 0){
00564 partgraph->nodes[newmap[senderID]].degree++;
00565 partgraph->nodes[newmap[recverID]].degree++;
00566 }
00567
00568 partgraph->edges[newmap[senderID]][newmap[recverID]] += cdata.bytes;
00569 partgraph->edges[newmap[recverID]][newmap[senderID]] += cdata.bytes;
00570
00571 partgraph->nodes[newmap[senderID]].comm += cdata.bytes;
00572 partgraph->nodes[newmap[recverID]].comm += cdata.bytes;
00573
00574
00575 if(partgraph->nodes[newmap[senderID]].comm > max_comm){
00576 max_comm = partgraph->nodes[newmap[senderID]].comm;
00577 max_comm_part = newmap[senderID];
00578 }
00579 if(partgraph->nodes[newmap[recverID]].comm > max_comm){
00580 max_comm = partgraph->nodes[newmap[recverID]].comm;
00581 max_comm_part = newmap[recverID];
00582 }
00583 }
00584 else if(cdata.receiver.get_type() == LD_OBJLIST_MSG) {
00585 int nobjs;
00586 const LDObjKey *objs = cdata.receiver.get_destObjs(nobjs);
00587 int senderID = stats->getHash(cdata.sender);
00588 for(j = 0; j < n_pes; j++)
00589 addedComm[j]=0;
00590 for (j=0; j<nobjs; j++) {
00591 int recverID = stats->getHash(objs[j]);
00592 if((senderID == -1)||(recverID == -1)) {
00593 if (_lb_args.migObjOnly()) continue;
00594 else CkAbort("Error in search\n");
00595 }
00596
00597 if(newmap[senderID]==newmap[recverID])
00598 continue;
00599
00600 if(partgraph->edges[newmap[senderID]][newmap[recverID]] == 0){
00601 partgraph->nodes[newmap[senderID]].degree++;
00602 partgraph->nodes[newmap[recverID]].degree++;
00603 }
00604
00605
00606 if(!addedComm[newmap[recverID]]){
00607 partgraph->edges[newmap[senderID]][newmap[recverID]] += cdata.bytes;
00608 partgraph->edges[newmap[recverID]][newmap[senderID]] += cdata.bytes;
00609
00610 partgraph->nodes[newmap[senderID]].comm += cdata.bytes;
00611 partgraph->nodes[newmap[recverID]].comm += cdata.bytes;
00612
00613 if(partgraph->nodes[newmap[senderID]].comm > max_comm){
00614 max_comm = partgraph->nodes[newmap[senderID]].comm;
00615 max_comm_part = newmap[senderID];
00616 }
00617 if(partgraph->nodes[newmap[recverID]].comm > max_comm){
00618 max_comm = partgraph->nodes[newmap[recverID]].comm;
00619 max_comm_part = newmap[recverID];
00620 }
00621
00622
00623 addedComm[newmap[recverID]]=1;
00624 }
00625 }
00626 }
00627
00628 }
00629 #endif
00630
00631 int *proc_mapping = new int[n_pes];
00632
00633 delete [] addedComm;
00634
00635 LBtopoFn topofn;
00636
00637
00638 char *lbcopy = strdup(_lbtopo);
00639 char *ptr = strchr(lbcopy, ':');
00640 if (ptr!=NULL)
00641 ptr = strtok(lbcopy, ":");
00642 else
00643 ptr=lbcopy;
00644
00645 topofn = LBTopoLookup(ptr);
00646 if (topofn == NULL) {
00647 char str[1024];
00648 CmiPrintf("TopoCentLB> Fatal error: Unknown topology: %s. Choose from:\n", ptr);
00649 printoutTopo();
00650 sprintf(str, "TopoCentLB> Fatal error: Unknown topology: %s", ptr);
00651 CmiAbort(str);
00652 }
00653
00654 topo = topofn(n_pes);
00655
00656
00657 calculateMST(partgraph,topo,proc_mapping,max_comm_part);
00658
00659
00660
00661 if (_lb_args.debug()>1) {
00662 CkPrintf("Resultant mapping..(partition,processor)\n");
00663 for(i = 0; i < n_pes; i++)
00664 CkPrintf("%d,%d\n",i,proc_mapping[i]);
00665 }
00666
00667
00668 int pe;
00669 PartGraph::Node* n;
00670 for(i = 0; i < n_pes; i++){
00671 pe = proc_mapping[i];
00672 n = &partgraph->nodes[i];
00673 for(j=0;j<n->num_objs;j++){
00674 stats->to_proc[n->obj_list[j]] = pe;
00675 if (_lb_args.debug()>1)
00676 CkPrintf("[%d] Obj %d migrating from %d to %d\n", CkMyPe(),n->obj_list[j],stats->from_proc[n->obj_list[j]],pe);
00677 }
00678 }
00679
00680 delete[] newmap;
00681 delete[] proc_mapping;
00682
00683 for(i = 0; i < n_pes; i++)
00684 delete[] hopCount[i];
00685
00686 delete[] hopCount;
00687 delete[] heapMapping;
00688
00689 delete partgraph;
00690 }
00691
00692 #include "TopoCentLB.def.h"