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 #if !CMK_TRACE_DISABLED
00010   if(pose_config.stats)
00011     localStats = (localStat *)CkLocalBranch(theLocalStats);
00012 #endif
00013   busy = reportTo = 0;
00014 }
00015 
00016 
00017 int LBgroup::computeObjectLoad(POSE_TimeType ovt, POSE_TimeType eet, double rbOh, int sync, POSE_TimeType gvt)
00018 {
00019   
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     
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   
00068   return objIdx;
00069 }
00070 
00071 int LBgroup::objRegister(int arrayIdx, int sync, sim *myPtr)
00072 {
00073   int i = objs.Insert(sync, arrayIdx, myPtr); 
00074   return(i*1000 + CkMyPe());                  
00075 }
00076 
00077 void LBgroup::objRemove(int arrayIdx)
00078 {
00079   int idx = (arrayIdx-CkMyPe())/1000; 
00080   objs.Delete(idx);                   
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; 
00087   objs.UpdateEntry(idx, ovt, eet, ne, rbOh, srVec); 
00088 }
00089 
00090 
00091 void LBgroup::calculateLocalLoad(void)
00092 {
00093 
00094 #if !CMK_TRACE_DISABLED
00095   if(pose_config.stats)
00096     localStats->TimerStart(LB_TIMER);
00097 #endif
00098   if (busy) {
00099     TheLBG[CkMyPe()].calculateLocalLoad();
00100 #if !CMK_TRACE_DISABLED
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   
00120   rootLB[reportTo].recvLoadReport(lr);
00121   reportTo = (reportTo + 1) % CkNumPes();
00122 #if !CMK_TRACE_DISABLED
00123   if(pose_config.stats)
00124     localStats->TimerStop();
00125 #endif
00126 }
00127 
00128 void LBgroup::balance(BalanceSpecs *bs)
00129 {
00130 #if !CMK_TRACE_DISABLED
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     
00140     
00141     
00142     static int **movableObjs = NULL;
00143     if (!movableObjs) { 
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       
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         
00169         
00170         
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       
00178       start = bs->sortArray[myIndex].startPEidx;
00179       end = bs->sortArray[myIndex].endPEidx;
00180       if (start != -1) {
00181     for (i=start; i<=end; i++) {
00182       
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         
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 #if !CMK_TRACE_DISABLED
00213   if(pose_config.stats)
00214     localStats->TimerStop();
00215 #endif
00216 }
00217 
00218 LBstrategy::LBstrategy(void)
00219 {
00220 #if !CMK_TRACE_DISABLED
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 
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   
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 
00306 
00307 void LBstrategy::recvLoadReport(LoadReport *lr)
00308 {
00309 #if !CMK_TRACE_DISABLED
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 #if !CMK_TRACE_DISABLED
00332   if(pose_config.stats)
00333     localStats->TimerStop();
00334 #endif
00335 }