libs/ck-libs/pose/ldbal.C

Go to the documentation of this file.
00001 #include "pose.h"
00002 #include "ldbal.def.h"
00003 
00004 CProxy_LBgroup TheLBG;
00005 CProxy_LBstrategy TheLBstrategy;
00006 
00007 LBgroup::LBgroup(void)
00008 {
00009 #ifndef CMK_OPTIMIZE
00010   if(pose_config.stats)
00011     localStats = (localStat *)CkLocalBranch(theLocalStats);
00012 #endif
00013   busy = reportTo = 0;
00014 }
00015 
00016 // local methods
00017 int LBgroup::computeObjectLoad(POSE_TimeType ovt, POSE_TimeType eet, double rbOh, int sync, POSE_TimeType gvt)
00018 {
00019   // an object can score a max of 100 if it is the heaviest an object can be
00020   int offset = eet - gvt; 
00021 
00022   if (!offset)  return 100;
00023   else if (offset < pose_config.spec_window)  return 90;
00024   else if (eet < 0)  return 50;
00025   else  return 80;
00026 }
00027 
00028 int LBgroup::computePeLoad()
00029 {
00030   PVT *localPVT = (PVT *)CkLocalBranch(ThePVT);
00031   POSE_TimeType gvt = localPVT->getGVT();
00032   peLoad = 0;
00033   for (int i=0; i<objs.numSpaces; i++)
00034     if (objs.objs[i].present) {
00035       objs.objs[i].execPrio = 
00036         computeObjectLoad(objs.objs[i].ovt, objs.objs[i].eet, 
00037                           objs.objs[i].rbOh, objs.objs[i].sync, gvt);
00038       peLoad += objs.objs[i].execPrio;
00039     }
00040   return peLoad;
00041 }
00042 
00043 int LBgroup::findHeaviestUnder(int loadDiff, int prioLoad, int **mvObjs,
00044                                int pe, int *contrib)
00045 {
00046   int objIdx = -1, i;
00047   int maxContribUnder = 0, newContrib;
00048 
00049   if (mvObjs[pe][0] > 0) {
00050     objIdx = mvObjs[pe][mvObjs[pe][0]];
00051     mvObjs[pe][0]--;
00052     *contrib = objs.objs[objIdx].execPrio;
00053     //CkPrintf("-");
00054     return objIdx;
00055   }
00056 
00057   for (i=0; i<objs.numSpaces; i++)
00058     if (objs.objs[i].present) {
00059       newContrib = objs.objs[i].execPrio;
00060       if ((newContrib <= loadDiff) && (newContrib > maxContribUnder)) {
00061         objIdx = i;
00062         maxContribUnder = newContrib;
00063       }
00064     }
00065 
00066   *contrib = maxContribUnder;
00067   //  if (objIdx >= 0) CkPrintf("|");
00068   return objIdx;
00069 }
00070 
00071 int LBgroup::objRegister(int arrayIdx, int sync, sim *myPtr)
00072 {
00073   int i = objs.Insert(sync, arrayIdx, myPtr); // add to object list
00074   return(i*1000 + CkMyPe());                  // return a unique index
00075 }
00076 
00077 void LBgroup::objRemove(int arrayIdx)
00078 {
00079   int idx = (arrayIdx-CkMyPe())/1000; // calculate local idx from unique idx
00080   objs.Delete(idx);                   // delete the object
00081 }
00082 
00083 void LBgroup::objUpdate(int ldIdx, POSE_TimeType ovt, POSE_TimeType eet, int ne, double rbOh, 
00084                         int *srVec)
00085 {
00086   int idx = (ldIdx-CkMyPe())/1000; // calculate local idx from unique idx
00087   objs.UpdateEntry(idx, ovt, eet, ne, rbOh, srVec); // update data for object
00088 }
00089 
00090 // entry methods
00091 void LBgroup::calculateLocalLoad(void)
00092 {
00093 
00094 #ifndef CMK_OPTIMIZE
00095   if(pose_config.stats)
00096     localStats->TimerStart(LB_TIMER);
00097 #endif
00098   if (busy) {
00099     TheLBG[CkMyPe()].calculateLocalLoad();
00100 #ifndef CMK_OPTIMIZE
00101     if(pose_config.stats)
00102       localStats->TimerStop();
00103 #endif
00104     return;
00105   }
00106   busy = 1;
00107 
00108   CProxy_LBstrategy rootLB(TheLBstrategy);
00109   LoadReport *lr = new LoadReport;
00110   
00111   objs.ResetComm();
00112   objs.RequestReport();
00113 
00114   lr->PE = CkMyPe();
00115   lr->peLoad = computePeLoad();
00116 
00117   CkPrintf("PE%d reporting load of %d.\n", CkMyPe(), lr->peLoad);
00118 
00119   // reduce loads to strategy
00120   rootLB[reportTo].recvLoadReport(lr);
00121   reportTo = (reportTo + 1) % CkNumPes();
00122 #ifndef CMK_OPTIMIZE
00123   if(pose_config.stats)
00124     localStats->TimerStop();
00125 #endif
00126 }
00127 
00128 void LBgroup::balance(BalanceSpecs *bs)
00129 {
00130 #ifndef CMK_OPTIMIZE
00131   if(pose_config.stats)
00132     localStats->TimerStart(LB_TIMER);
00133 #endif
00134   int myIndex = bs->indexArray[CkMyPe()], i, start, end, objIdx;
00135   int underLoad, contrib;
00136   destMsg *dm;
00137 
00138   if (bs->sortArray[0].peLoad + pose_config.lb_diff < bs->sortArray[CkNumPes()-1].peLoad){
00139     // we only want to move objects that are not tightly coupled with other 
00140     // local objects via communication, so we build a list of movable objects
00141     // the very first time this processor is overloaded
00142     static int **movableObjs = NULL;
00143     if (!movableObjs) { // allocate space for the movable objects
00144       movableObjs = (int **)malloc(CkNumPes()*sizeof(int *));
00145       for (i=0; i<CkNumPes(); i++)
00146       movableObjs[i] = (int *)malloc(21*sizeof(int));
00147     }
00148     
00149     if ((peLoad > bs->avgLoad) &&
00150         (bs->sortArray[myIndex].peLoad - 
00151          bs->sortArray[bs->sortArray[myIndex].startPEidx].peLoad 
00152          > pose_config.lb_threshold)) {
00153       CkPrintf("[%d] overload: checking balancing prospects.\n", CkMyPe());
00154       // Load up the table with movable objects
00155       for (i=0; i<CkNumPes(); i++)
00156         movableObjs[i][0] = 0;
00157       for (i=0; i<objs.numSpaces; i++)
00158         if (objs.objs[i].present && 
00159             (objs.objs[i].localComm < objs.objs[i].remoteComm)) {
00160           objs.objs[i].maxComm = objs.objs[i].comm[0];
00161           objs.objs[i].maxCommPE = 0;
00162           for (int j=0; j<CkNumPes(); j++)
00163             if (objs.objs[i].comm[j] > objs.objs[i].maxComm) {
00164               objs.objs[i].maxComm = objs.objs[i].comm[j];
00165               objs.objs[i].maxCommPE = j;
00166             }
00167           if (objs.objs[i].maxComm > objs.objs[i].localComm) {
00168             //CkPrintf("[%d] Obj %3d@[%3d] ", CkMyPe(), i, objs.objs[i].index);
00169             //for (int k=0; k<CkNumPes(); k++) CkPrintf("%3d ", objs.objs[i].comm[k]);
00170             //CkPrintf("%3d %3d %3d %3d %3d\n", objs.objs[i].totalComm, objs.objs[i].localComm, objs.objs[i].remoteComm, objs.objs[i].maxComm, objs.objs[i].maxCommPE);
00171             if (movableObjs[objs.objs[i].maxCommPE][0] < 20) {
00172               movableObjs[objs.objs[i].maxCommPE][0]++;
00173               movableObjs[objs.objs[i].maxCommPE][movableObjs[objs.objs[i].maxCommPE][0]] = i;
00174             }
00175           }
00176         }
00177       // done building movable objects table; now, try to migrate objects away
00178       start = bs->sortArray[myIndex].startPEidx;
00179       end = bs->sortArray[myIndex].endPEidx;
00180       if (start != -1) {
00181         for (i=start; i<=end; i++) {
00182           //CkPrintf("start=%d end=%d avgPeLd=%f i=%d [i].peLoad=%f\n", start, end, bs->avgPeLd, i, bs->sortArray[i].peLoad);
00183           if (bs->sortArray[myIndex].peLoad - bs->sortArray[i].peLoad 
00184               < pose_config.lb_threshold)
00185             break;
00186           if (bs->avgLoad > bs->sortArray[i].peLoad)
00187             underLoad = bs->avgLoad - bs->sortArray[i].peLoad;
00188           else
00189             underLoad = (bs->sortArray[myIndex].peLoad - bs->sortArray[i].peLoad)/2;
00190           objIdx = findHeaviestUnder(underLoad, bs->sortArray[i].peLoad, 
00191                                      movableObjs, bs->sortArray[i].PE, 
00192                                      &contrib);
00193           while (objIdx >= 0) {
00194             dm = new destMsg;
00195             dm->destPE = bs->sortArray[i].PE;
00196             //CkPrintf("%d->%d ", CkMyPe(), dm->destPE);
00197             CkPrintf("PE[%d] to migrate %d to PE %d: contrib %d to load %d with diff %d\n", CkMyPe(), objs.objs[objIdx].index, dm->destPE, contrib, bs->sortArray[i].peLoad, underLoad);
00198             POSE_Objects[objs.objs[objIdx].index].Migrate(dm);
00199             objs.objs[objIdx].present = 0;
00200             underLoad -= contrib;
00201             objIdx = findHeaviestUnder(underLoad, bs->sortArray[i].peLoad,
00202                                        movableObjs, bs->sortArray[i].PE,
00203                                        &contrib);
00204           }
00205         }
00206       }
00207     }
00208     else CkPrintf("[%d] underload.\n", CkMyPe());
00209   }
00210   CkFreeMsg(bs);
00211   busy = 0;
00212 #ifndef CMK_OPTIMIZE
00213   if(pose_config.stats)
00214     localStats->TimerStop();
00215 #endif
00216 }
00217 
00218 LBstrategy::LBstrategy(void)
00219 {
00220 #ifndef CMK_OPTIMIZE
00221   if(pose_config.stats)
00222     localStats = (localStat *)CkLocalBranch(theLocalStats);
00223 #endif
00224   peLoads = (int *)malloc(CkNumPes()*sizeof(int));
00225   for (int i=0; i<CkNumPes(); i++)
00226     peLoads[i] = -1;
00227 }
00228 
00229 // local methods
00230 
00231 void LBstrategy::computeLoadMap(int avgLd, int ttlLd)
00232 {
00233   BalanceSpecs *dm = new BalanceSpecs;
00234   int i, pe, start, count;
00235   int overLoad, underLoad;
00236 
00237   //  CkPrintf(":");
00238   dm->avgLoad = avgLd;
00239   dm->totalLoad = ttlLd;
00240 
00241   for (i=0; i<CkNumPes(); i++) {
00242     dm->indexArray[i] = -1;
00243     dm->sortArray[i].PE = dm->sortArray[i].startPEidx = 
00244       dm->sortArray[i].endPEidx = -1;
00245     dm->sortArray[i].peLoad = 0;
00246   }
00247 
00248   for (i=0; i<CkNumPes(); i++) {
00249     pe = findMinPE();
00250     dm->indexArray[pe] = i;
00251     dm->sortArray[i].PE = pe;
00252     dm->sortArray[i].peLoad = peLoads[pe];
00253     peLoads[pe] = -1;
00254   }
00255 
00256   pe = CkNumPes() - 1;
00257   start = 0;
00258   while (dm->sortArray[pe].peLoad > avgLd) {
00259     overLoad = dm->sortArray[pe].peLoad - avgLd;
00260     count = 0;
00261     while ((overLoad > (avgLd - dm->sortArray[start].peLoad)/2) 
00262            && (start < pe)) {
00263       if (dm->sortArray[start].peLoad < avgLd) {
00264         underLoad = avgLd - dm->sortArray[start].peLoad;
00265         overLoad -= underLoad;
00266         count++;
00267         start++;
00268       }
00269       else {
00270         underLoad = (dm->sortArray[pe].peLoad - dm->sortArray[start].peLoad)/2;
00271         overLoad -= underLoad;
00272         count++;
00273         start++;
00274       }
00275     }
00276     if (count > 0) {
00277       dm->sortArray[pe].startPEidx = start - count;
00278       dm->sortArray[pe].endPEidx = start-1;
00279     }
00280     else
00281       dm->sortArray[pe].startPEidx = dm->sortArray[pe].endPEidx = -1;
00282     pe--;
00283   }
00284 
00285   CkPrintf("LB balance info: Total Load = %d; Avg load = %d\n", dm->totalLoad, dm->avgLoad);
00286   for (i=0; i<CkNumPes(); i++) CkPrintf("[%d] PE:%d PE Load:%d start:%d end:%d\n", i, dm->sortArray[i].PE, dm->sortArray[i].peLoad, dm->sortArray[i].startPEidx, dm->sortArray[i].endPEidx);
00287   TheLBG.balance(dm);
00288   CkPrintf("...DONE load balancing]\n");
00289 }
00290 
00291 int LBstrategy::findMinPE()
00292 {
00293   int minPE = 0, i;
00294   int minLoad = peLoads[0];
00295   
00296   for (i=1; i<CkNumPes(); i++)
00297     if ((minLoad < 0) || 
00298         ((peLoads[i] < minLoad) && (peLoads[i] >= 0))) {
00299       minLoad = peLoads[i];
00300       minPE = i;
00301     }
00302   return minPE;
00303 }
00304 
00305 // entry methods
00306 
00307 void LBstrategy::recvLoadReport(LoadReport *lr)
00308 {
00309 #ifndef CMK_OPTIMIZE
00310   if(pose_config.stats)
00311     localStats->TimerStart(LB_TIMER);
00312 #endif
00313   int i, avgLd = 0, totalLd = 0;
00314   static int done=0;
00315 
00316   peLoads[lr->PE] = lr->peLoad;  
00317   CkFreeMsg(lr);
00318   done++;  
00319 
00320   if (done == CkNumPes()) {
00321     CkPrintf("[BEGIN load balancing on %d...\n", CkMyPe());
00322     for (i=0; i<CkNumPes(); i++)
00323       totalLd += peLoads[i];
00324     avgLd = totalLd / CkNumPes();
00325 
00326     CkPrintf("LB[%d] totalLd=%d avgLd=%d\n", CkMyPe(), totalLd, avgLd);
00327     computeLoadMap(avgLd, totalLd);
00328 
00329     done = 0;
00330   }
00331 #ifndef CMK_OPTIMIZE
00332   if(pose_config.stats)
00333     localStats->TimerStop();
00334 #endif
00335 }

Generated on Sun Jun 29 13:29:25 2008 for Charm++ by  doxygen 1.5.1