00001
00005
00006 #include "charm++.h"
00007 #include "BaseLB.h"
00008 #include "LBSimulation.h"
00009
00010 #if CMK_LBDB_ON
00011
00012 void BaseLB::initLB(const CkLBOptions &opt) {
00013 seqno = opt.getSeqNo();
00014 CkpvAccess(numLoadBalancers) ++;
00015
00016
00017
00018
00019 theLbdb = CProxy_LBDatabase(_lbdb).ckLocalBranch();
00020 lbname = "Unknown";
00021
00022 theLbdb->addLoadbalancer(this, seqno);
00023 }
00024
00025 BaseLB::~BaseLB() {
00026 CkpvAccess(numLoadBalancers) --;
00027 }
00028
00029 void BaseLB::unregister() {
00030 theLbdb->RemoveLocalBarrierReceiver(receiver);
00031 CkpvAccess(numLoadBalancers) --;
00032 }
00033
00034 void BaseLB::pup(PUP::er &p) {
00035 p|seqno;
00036 if (p.isUnpacking())
00037 {
00038 if (CkMyPe()==0) {
00039 if (seqno!=-1) {
00040 int newseq = LBDatabaseObj()->getLoadbalancerTicket();
00041 CmiAssert(newseq == seqno);
00042 }
00043 }
00044 initLB(seqno);
00045 }
00046 }
00047
00048 void BaseLB::flushStates() {
00049 Group::flushStates();
00050 theLbdb->ClearLoads();
00051 }
00052
00053 #else
00054 BaseLB::~BaseLB() {}
00055 void BaseLB::initLB(const CkLBOptions &) {}
00056 void BaseLB::unregister() {}
00057 void BaseLB::pup(PUP::er &p) {}
00058 void BaseLB::flushStates() {}
00059 #endif
00060
00061 static inline int i_abs(int c) { return c>0?c:-c; }
00062
00063
00064 inline static int ObjKey(const CmiUInt8 &oid, const int hashSize) {
00065
00066 return oid % hashSize;
00067 }
00068
00069 BaseLB::LDStats::LDStats(int c, int complete)
00070 : n_objs(0), n_migrateobjs(0), n_comm(0),
00071 objHash(NULL), complete_flag(complete)
00072 {
00073 count = c;
00074 if (count == 0) count = CkNumPes();
00075 procs = new ProcStats[count];
00076 }
00077
00078 const static unsigned int doublingPrimes[] = {
00079 3,
00080 7,
00081 17,
00082 37,
00083 73,
00084 157,
00085 307,
00086 617,
00087 1217,
00088 2417,
00089 4817,
00090 9677,
00091 20117,
00092 40177,
00093 80177,
00094 160117,
00095 320107,
00096 640007,
00097 1280107,
00098 2560171,
00099 5120117,
00100 10000079,
00101 20000077,
00102 40000217,
00103 80000111,
00104 160000177,
00105 320000171,
00106 640000171,
00107 1280000017,
00108 2560000217u,
00109 4200000071u
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139 };
00140
00141
00142 static unsigned int primeLargerThan(unsigned int x)
00143 {
00144 int i=0;
00145 while (doublingPrimes[i]<=x) i++;
00146 return doublingPrimes[i];
00147 }
00148
00149 void BaseLB::LDStats::makeCommHash() {
00150
00151 if (objHash) return;
00152
00153 int i;
00154 hashSize = n_objs*2;
00155 hashSize = primeLargerThan(hashSize);
00156 objHash = new int[hashSize];
00157 for(i=0;i<hashSize;i++)
00158 objHash[i] = -1;
00159
00160 for(i=0;i<n_objs;i++){
00161 const CmiUInt8 &oid = objData[i].objID();
00162 int hash = ObjKey(oid, hashSize);
00163 CmiAssert(hash != -1);
00164 while(objHash[hash] != -1)
00165 hash = (hash+1)%hashSize;
00166 objHash[hash] = i;
00167 }
00168 }
00169
00170 void BaseLB::LDStats::deleteCommHash() {
00171 if (objHash) delete [] objHash;
00172 objHash = NULL;
00173 for(int i=0; i < n_comm; i++) {
00174 commData[i].clearHash();
00175 }
00176 }
00177
00178 int BaseLB::LDStats::getHash(const CmiUInt8 &oid, const LDOMid &mid)
00179 {
00180 #if CMK_LBDB_ON
00181 CmiAssert(hashSize > 0);
00182 int hash = ObjKey(oid, hashSize);
00183
00184 for(int id=0;id<hashSize;id++){
00185 int index = (id+hash)%hashSize;
00186 if (index == -1 || objHash[index] == -1) return -1;
00187 if (objData[objHash[index]].objID() == oid &&
00188 LDOMidEqual(objData[objHash[index]].omID(), mid))
00189 return objHash[index];
00190 }
00191
00192 #endif
00193 return -1;
00194 }
00195
00196 int BaseLB::LDStats::getHash(const LDObjKey &objKey)
00197 {
00198 const CmiUInt8 &oid = objKey.objID();
00199 const LDOMid &mid = objKey.omID();
00200 return getHash(oid, mid);
00201 }
00202
00203 int BaseLB::LDStats::getSendHash(LDCommData &cData)
00204 {
00205 if (cData.sendHash == -1) {
00206 cData.sendHash = getHash(cData.sender);
00207 }
00208 return cData.sendHash;
00209 }
00210
00211 int BaseLB::LDStats::getRecvHash(LDCommData &cData)
00212 {
00213 if (cData.recvHash == -1) {
00214 cData.recvHash = getHash(cData.receiver.get_destObj());
00215 }
00216 return cData.recvHash;
00217 }
00218
00219 void BaseLB::LDStats::clearCommHash() {
00220 for(int i=0; i < n_comm; i++) {
00221 commData[i].clearHash();
00222 }
00223 }
00224
00225 void BaseLB::LDStats::computeNonlocalComm(int &nmsgs, int &nbytes)
00226 {
00227 #if CMK_LBDB_ON
00228 nmsgs = 0;
00229 nbytes = 0;
00230
00231 makeCommHash();
00232
00233 int mcast_count = 0;
00234 for (int cidx=0; cidx < n_comm; cidx++) {
00235 LDCommData& cdata = commData[cidx];
00236 int senderPE, receiverPE;
00237 if (cdata.from_proc())
00238 senderPE = cdata.src_proc;
00239 else {
00240 int idx = getHash(cdata.sender);
00241 if (idx == -1) continue;
00242 senderPE = to_proc[idx];
00243 CmiAssert(senderPE != -1);
00244 }
00245 CmiAssert(senderPE < nprocs() && senderPE >= 0);
00246
00247
00248 int receiver_type = cdata.receiver.get_type();
00249 if (receiver_type == LD_PROC_MSG || receiver_type == LD_OBJ_MSG) {
00250 if (receiver_type == LD_PROC_MSG)
00251 receiverPE = cdata.receiver.proc();
00252 else {
00253 int idx = getHash(cdata.receiver.get_destObj());
00254 if (idx == -1) {
00255 if (complete_flag) continue;
00256 else receiverPE = -1;
00257 }
00258 else {
00259 receiverPE = to_proc[idx];
00260 CmiAssert(receiverPE < nprocs() && receiverPE >= 0);
00261 }
00262 }
00263 if(senderPE != receiverPE)
00264 {
00265 nmsgs += cdata.messages;
00266 nbytes += cdata.bytes;
00267 }
00268 }
00269 else if (receiver_type == LD_OBJLIST_MSG) {
00270 int nobjs;
00271 const LDObjKey *objs = cdata.receiver.get_destObjs(nobjs);
00272 mcast_count ++;
00273 CkVec<int> pes;
00274 for (int i=0; i<nobjs; i++) {
00275 int idx = getHash(objs[i]);
00276 CmiAssert(idx != -1);
00277 if (idx == -1) continue;
00278 receiverPE = to_proc[idx];
00279 CmiAssert(receiverPE < nprocs() && receiverPE >= 0);
00280 int exist = 0;
00281 for (int p=0; p<pes.size(); p++)
00282 if (receiverPE == pes[p]) { exist=1; break; }
00283 if (exist) continue;
00284 pes.push_back(receiverPE);
00285 if(senderPE != receiverPE)
00286 {
00287 nmsgs += cdata.messages;
00288 nbytes += cdata.bytes;
00289 }
00290 }
00291 }
00292 }
00293 #endif
00294 }
00295
00296 void BaseLB::LDStats::normalize_speed() {
00297 int pe;
00298 double maxspeed = 0.0;
00299
00300 for(int pe=0; pe < nprocs(); pe++) {
00301 if (procs[pe].pe_speed > maxspeed) maxspeed = procs[pe].pe_speed;
00302 }
00303 for(int pe=0; pe < nprocs(); pe++)
00304 procs[pe].pe_speed /= maxspeed;
00305 }
00306
00307 void BaseLB::LDStats::print()
00308 {
00309 #if CMK_LBDB_ON
00310 int i;
00311 CkPrintf("------------- Processor Data: %d -------------\n", nprocs());
00312 for(int pe=0; pe < nprocs(); pe++) {
00313 struct ProcStats &proc = procs[pe];
00314
00315 CkPrintf("Proc %d (%d) Speed %d Total = %f Idle = %f Bg = %f nObjs = %d",
00316 pe, proc.pe, proc.pe_speed, proc.total_walltime, proc.idletime,
00317 proc.bg_walltime, proc.n_objs);
00318 #if CMK_LB_CPUTIMER
00319 CkPrintf(" CPU Total %f Bg %f", proc.total_cputime, proc.bg_cputime);
00320 #endif
00321 CkPrintf("\n");
00322 }
00323
00324 CkPrintf("------------- Object Data: %d objects -------------\n", n_objs);
00325 for(i=0; i < n_objs; i++) {
00326 LDObjData &odata = objData[i];
00327 CkPrintf("Object %d\n",i);
00328 CkPrintf(" id = %" PRIu64 "\n",odata.objID());
00329 CkPrintf(" OM id = %d\t",odata.omID().id);
00330 CkPrintf(" Mig. = %d\n",odata.migratable);
00331 #if CMK_LB_CPUTIMER
00332 CkPrintf(" CPU = %f\t",odata.cpuTime);
00333 #endif
00334 CkPrintf(" Wall = %f\n",odata.wallTime);
00335 }
00336
00337 CkPrintf("------------- Comm Data: %d records -------------\n", n_comm);
00338 CkVec<LDCommData> &cdata = commData;
00339 for(i=0; i < n_comm; i++) {
00340 CkPrintf("Link %d\n",i);
00341
00342 CmiUInt8 &sid = cdata[i].sender.objID();
00343 if (cdata[i].from_proc())
00344 CkPrintf(" sender PE = %d\t",cdata[i].src_proc);
00345 else
00346 CkPrintf(" sender id = %d:[%" PRIu64 "]\t",
00347 cdata[i].sender.omID().id,sid);
00348
00349 CmiUInt8 &rid = cdata[i].receiver.get_destObj().objID();
00350 if (cdata[i].recv_type() == LD_PROC_MSG)
00351 CkPrintf(" receiver PE = %d\n",cdata[i].receiver.proc());
00352 else
00353 CkPrintf(" receiver id = %d:[%" PRIu64 "]\n",
00354 cdata[i].receiver.get_destObj().omID().id,rid);
00355
00356 CkPrintf(" messages = %d\t",cdata[i].messages);
00357 CkPrintf(" bytes = %d\n",cdata[i].bytes);
00358 }
00359 CkPrintf("------------- Object to PE mapping -------------\n");
00360 for (i=0; i<n_objs; i++) CkPrintf(" %d", from_proc[i]);
00361 CkPrintf("\n");
00362 #endif
00363 }
00364
00365 double BaseLB::LDStats::computeAverageLoad()
00366 {
00367 int i, numAvail=0;
00368 double total = 0;
00369 for (i=0; i<n_objs; i++) total += objData[i].wallTime;
00370
00371 for (i=0; i<nprocs(); i++)
00372 if (procs[i].available == true) {
00373 total += procs[i].bg_walltime;
00374 numAvail++;
00375 }
00376
00377 double averageLoad = total/numAvail;
00378 return averageLoad;
00379 }
00380
00381
00382 void BaseLB::LDStats::removeObject(int obj)
00383 {
00384 CmiAssert(obj < objData.size());
00385 LDObjData odata = objData[obj];
00386
00387 LDObjKey okey;
00388 okey.omID() = odata.omID();
00389 okey.objID() = odata.objID();
00390
00391 objData.remove(obj);
00392 from_proc.remove(obj);
00393 to_proc.remove(obj);
00394 n_objs --;
00395 if (odata.migratable) n_migrateobjs --;
00396
00397
00398 int removed = 0;
00399 for (int com=0; com<n_comm; com++) {
00400 LDCommData &cdata = commData[com-removed];
00401 if(!cdata.from_proc() && cdata.sender == okey) {
00402 commData.remove(com-removed);
00403 removed++;
00404 }
00405 }
00406 n_comm -= removed;
00407 }
00408
00409 void BaseLB::LDStats::pup(PUP::er &p)
00410 {
00411 int i;
00412 p(count);
00413 p(n_objs);
00414 p(n_migrateobjs);
00415 p(n_comm);
00416 if (p.isUnpacking()) {
00417
00418 int maxpe = nprocs() > LBSimulation::simProcs ? nprocs() : LBSimulation::simProcs;
00419 procs = new ProcStats[maxpe];
00420 objData.resize(n_objs);
00421 commData.resize(n_comm);
00422 from_proc.resize(n_objs);
00423 to_proc.resize(n_objs);
00424 objHash = NULL;
00425 }
00426
00427
00428 if (p.isUnpacking() && LBSimulation::procsChanged) {
00429 ProcStats dummy;
00430 for (i=0; i<nprocs(); i++) p|dummy;
00431 }
00432 else
00433 for (i=0; i<nprocs(); i++) p|procs[i];
00434 for (i=0; i<n_objs; i++) p|objData[i];
00435 for (i=0; i<n_objs; i++) p|from_proc[i];
00436 for (i=0; i<n_objs; i++) p|to_proc[i];
00437
00438 if (p.isUnpacking())
00439 for (i=0; i<n_objs; i++) to_proc[i] = from_proc[i];
00440 for (i=0; i<n_comm; i++) p|commData[i];
00441 if (p.isUnpacking())
00442 count = LBSimulation::simProcs;
00443 if (p.isUnpacking()) {
00444 objHash = NULL;
00445 if (_lb_args.lbversion() <= 1)
00446 for (i=0; i<nprocs(); i++) procs[i].pe = i;
00447 }
00448 }
00449
00450 int BaseLB::LDStats::useMem() {
00451
00452 return sizeof(LDStats) + sizeof(ProcStats) * nprocs() +
00453 (sizeof(LDObjData) + 2 * sizeof(int)) * n_objs +
00454 sizeof(LDCommData) * n_comm;
00455 }
00456
00457 #include "BaseLB.def.h"
00458