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