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 }