00001
00005
00006 #ifndef HYBRIDBASELB_H
00007 #define HYBRIDBASELB_H
00008
00009 #include <map>
00010
00011 #include "charm++.h"
00012 #include "BaseLB.h"
00013 #include "CentralLB.h"
00014 #include "HybridBaseLB.decl.h"
00015
00016 #include "topology.h"
00017
00018 void CreateHybridBaseLB();
00019
00021 typedef LBMigrateMsg NLBMigrateMsg;
00022
00023 inline int mymin(int x, int y) { return x<y?x:y; }
00024
00025
00026 class MyHierarchyTree {
00027 protected:
00028 int *span;
00029 int nLevels;
00030 const char *myname;
00031 public:
00032 MyHierarchyTree(): span(NULL), myname(NULL) {}
00033 virtual ~MyHierarchyTree() {}
00034 const char* name() const { return myname; }
00035 virtual int numLevels() const { return nLevels; }
00036 virtual int parent(int mype, int level) = 0;
00037 virtual bool isroot(int mype, int level) = 0;
00038 virtual int numChildren(int mype, int level) = 0;
00039 virtual void getChildren(int mype, int level, int *children, int &count) = 0;
00040 virtual int numNodes(int level) {
00041 CmiAssert(level>=0 && level<nLevels);
00042 int count=1;
00043 for (int i=0; i<level; i++) count *= span[i];
00044 CmiAssert(CkNumPes()%count ==0);
00045 return CkNumPes()/count;
00046 }
00047 };
00048
00049
00050
00051
00052
00053 class TwoLevelTree: public MyHierarchyTree {
00054 private:
00055 int toproot;
00056 public:
00057 TwoLevelTree() {
00058 myname = "TwoLevelTree";
00059 span = new int[1];
00060 nLevels = 2;
00061 span[0] = CkNumPes();
00062 toproot = 0;
00063 }
00064 virtual ~TwoLevelTree() { delete [] span; }
00065 virtual int parent(int mype, int level) {
00066 if (level == 0) return toproot;
00067 if (level == 1) return -1;
00068 CmiAssert(0);
00069 return -1;
00070 }
00071 virtual bool isroot(int mype, int level) {
00072 if (level == 0) return false;
00073 if (level == 1 && mype == toproot) return true;
00074 return false;
00075 }
00076 virtual int numChildren(int mype, int level) {
00077 if (level == 0) return 0;
00078 if (level == 1) return CkNumPes();
00079 CmiAssert(0);
00080 return 0;
00081 }
00082 virtual void getChildren(int mype, int level, int *children, int &count) {
00083 CmiAssert(isroot(mype, level));
00084 count = numChildren(mype, level);
00085 if (count == 0) { return; }
00086 if (level == 1) {
00087 for (int i=0; i<count; i++)
00088 children[i] = i;
00089 }
00090 }
00091 };
00092
00093
00094
00095
00096
00097
00098
00099 class ThreeLevelTree: public MyHierarchyTree {
00100 private:
00101 int toproot;
00102 public:
00103 ThreeLevelTree(int groupsize=512) {
00104 myname = "ThreeLevelTree";
00105 span = new int[2];
00106 nLevels = 3;
00107 while (groupsize && CkNumPes() / groupsize < 2) {
00108 groupsize /= 2;
00109 }
00110 while ( CkNumPes() % groupsize ) --groupsize;
00111 if ( groupsize == 1 ) {
00112 ++groupsize;
00113 while ( CkNumPes() % groupsize ) ++groupsize;
00114 }
00115 span[0] = groupsize;
00116 CmiAssert(span[0]>1);
00117 span[1] = (CkNumPes()+span[0]-1)/span[0];
00118 if (CmiNumPhysicalNodes() > 1)
00119 toproot = CmiGetFirstPeOnPhysicalNode(1);
00120 else
00121 toproot = 1;
00122 }
00123 virtual ~ThreeLevelTree() { delete [] span; }
00124 virtual int parent(int mype, int level) {
00125 if (level == 0) return mype/span[0]*span[0];
00126 if (level == 1) return toproot;
00127 if (level == 2) return -1;
00128 CmiAssert(0);
00129 return -1;
00130 }
00131 virtual bool isroot(int mype, int level) {
00132 if (level == 0) return false;
00133 if (level == 1 && mype % span[0] == 0) return true;
00134 if (level == 2 && mype == toproot) return true;
00135 return false;
00136 }
00137 virtual int numChildren(int mype, int level) {
00138 if (level == 0) return 0;
00139 if (level == 1) return mymin(CkNumPes(), mype+span[0]) - mype;
00140 if (level == 2) return span[1];
00141 CmiAssert(0);
00142 return 0;
00143 }
00144 virtual void getChildren(int mype, int level, int *children, int &count) {
00145 CmiAssert(isroot(mype, level));
00146 count = numChildren(mype, level);
00147 if (count == 0) { return; }
00148 if (level == 1) {
00149 for (int i=0; i<count; i++)
00150 children[i] = mype + i;
00151 }
00152 if (level == 2) {
00153 for (int i=0; i<count; i++)
00154 children[i] = i*span[0];
00155 }
00156 }
00157 };
00158
00159
00160
00161
00162
00163
00164
00165
00166
00167 class FourLevelTree: public MyHierarchyTree {
00168 private:
00169 int toproot;
00170 public:
00171 FourLevelTree() {
00172 myname = "FourLevelTree";
00173 span = new int[3];
00174 nLevels = 4;
00175 #if 1
00176 span[0] = 64;
00177 span[1] = 32;
00178 span[2] = 32;
00179 #else
00180 span[0] = 4;
00181 span[1] = 2;
00182 span[2] = 2;
00183 #endif
00184 CmiAssert(CkNumPes() == span[0]*span[1]*span[2]);
00185 toproot = 2;
00186 }
00187 virtual ~FourLevelTree() { delete [] span; }
00188 virtual int parent(int mype, int level) {
00189 if (level == 0) return mype/span[0]*span[0];
00190 if (level == 1) return mype/span[0]/span[1]*span[0]*span[1]+1;
00191 if (level == 2) return toproot;
00192 if (level == 3) return -1;
00193 CmiAssert(0);
00194 return -1;
00195 }
00196 virtual bool isroot(int mype, int level) {
00197 if (level == 0) return false;
00198 if (level == 1 && (mype % span[0]) == 0) return true;
00199 if (level == 2 && ((mype-1)%(span[0]*span[1])) == 0) return true;
00200 if (level == 3 && mype == toproot) return true;
00201 return false;
00202 }
00203 virtual int numChildren(int mype, int level) {
00204 if (level == 0) return 0;
00205 if (level == 1) return span[0];
00206 if (level == 2) return span[1];
00207 if (level == 3) return span[2];
00208 CmiAssert(0);
00209 return 0;
00210 }
00211 virtual void getChildren(int mype, int level, int *children, int &count) {
00212 CmiAssert(isroot(mype, level));
00213 count = numChildren(mype, level);
00214 if (count == 0) { return; }
00215 if (level == 1) {
00216 for (int i=0; i<count; i++)
00217 children[i] = mype + i;
00218 }
00219 if (level == 2) {
00220 for (int i=0; i<count; i++)
00221 children[i] = mype-1+i*span[0];
00222 }
00223 if (level == 3) {
00224 for (int i=0; i<count; i++)
00225 children[i] = i*span[0]*span[1]+1;
00226 }
00227 }
00228 };
00229
00230
00231 class KLevelTree: public MyHierarchyTree {
00232 private:
00233 int toproot;
00234 int G;
00235 public:
00236 KLevelTree(int k) {
00237 myname = "KLevelTree";
00238 nLevels = k;
00239 span = new int[nLevels-1];
00240 int P=CkNumPes();
00241 G = (int)(exp(log(P*1.0)/(nLevels-1))+0.5);
00242 if (pow(G*1.0, nLevels-1) != P) {
00243 CkPrintf("KLevelTree failed: P=%d Level=%d G=%d\n", P, nLevels, G);
00244 CmiAbort("KLevelTree failed");
00245 }
00246 for (int i=0; i<nLevels-1; i++) span[i] = G;
00247 if (CmiNumPhysicalNodes() > 1)
00248 toproot = CmiGetFirstPeOnPhysicalNode(1);
00249 else
00250 toproot = 1;
00251 if (CkMyPe()==0) CmiPrintf("KLevelTree: %d (toproot:%d).\n", G, toproot);
00252 }
00253 virtual ~KLevelTree() { delete [] span; }
00254 virtual int parent(int mype, int level) {
00255 if (level == nLevels-2) return toproot;
00256 if (level == nLevels-1) return -1;
00257 int S = 1;
00258 for (int i=0; i<=level; i++) S*=span[i];
00259 return mype/S*S+level;
00260 }
00261 virtual bool isroot(int mype, int level) {
00262 if (level == 0) return false;
00263 if (level == nLevels-1) return mype == toproot;
00264 int S = 1;
00265 for (int i=0; i<level; i++) S*=span[i];
00266 if ((mype - (level-1)) % S == 0) return true;
00267 return false;
00268 }
00269 virtual int numChildren(int mype, int level) {
00270 if (level == 0) return 0;
00271 return span[level-1];
00272 }
00273 virtual void getChildren(int mype, int level, int *children, int &count) {
00274 CmiAssert(isroot(mype, level));
00275 count = numChildren(mype, level);
00276 if (count == 0) { return; }
00277 int S = 1;
00278 for (int i=0; i<level-1; i++) S*=span[i];
00279
00280 if (level == nLevels-1) {
00281 for (int i=0; i<count; i++)
00282 children[i] = i*S+(level-2);
00283 }
00284 else if (level == 1) {
00285 for (int i=0; i<count; i++)
00286 children[i] = mype+i*S;
00287 }
00288 else {
00289 for (int i=0; i<count; i++)
00290 children[i] = mype-1+i*S;
00291 }
00292 }
00293 };
00294
00295 class HybridBaseLB : public CBase_HybridBaseLB
00296 {
00297 public:
00298 HybridBaseLB(const CkLBOptions &);
00299 HybridBaseLB(CkMigrateMessage *m): CBase_HybridBaseLB(m) {}
00300 ~HybridBaseLB();
00301
00302 static void staticAtSync(void*);
00303 void AtSync(void);
00304 void ProcessAtSync(void);
00305
00306 void ReceiveStats(CkMarshalledCLBStatsMessage &&m, int fromlevel);
00307 void ResumeClients(double result);
00308 void ResumeClients(int balancing);
00309 void ReceiveMigration(LBMigrateMsg *);
00310 void ReceiveVectorMigration(LBVectorMigrateMsg *);
00311 virtual void GetObjsToMigrate(int toPe, double load, LDStats *stats,
00312 int atlevel, CkVec<LDCommData>& comms, CkVec<LDObjData>& objs);
00313 void CreateMigrationOutObjs(int atlevel, LDStats* stats, int objidx);
00314 void TotalObjMigrated(int count, int level);
00315
00316
00317 static void staticMigrated(void* me, LDObjHandle h, int waitBarrier);
00318 void Migrated(LDObjHandle h, int waitBarrier);
00319
00320 void ObjMigrated(LDObjData data, LDCommData *cdata, int n, int level);
00321 void ObjsMigrated(CkVec<LDObjData>&& data, int m, LDCommData *cdata, int n, int level);
00322 void VectorDone(int atlevel);
00323 void MigrationDone(int balancing);
00324 void StatsDone(int level);
00325 void NotifyObjectMigrationDone(int level);
00326 virtual void Loadbalancing(int level);
00327 void StartCollectInfo(DummyMsg *m);
00328 void CollectInfo(Location *loc, int n, int fromlevel);
00329 void PropagateInfo(Location *loc, int n, int fromlevel);
00330
00331 void reportLBQulity(double mload, double mCpuLoad, double totalload, int nmsgs, double bytesentry );
00332 void reportLBMem(double);
00333
00334 struct MigrationRecord {
00335 LDObjHandle handle;
00336 int fromPe;
00337 int toPe;
00338 MigrationRecord(): fromPe(-1), toPe(-1) {}
00339 MigrationRecord(LDObjHandle &k, int f, int t): handle(k), fromPe(f), toPe(t) {}
00340 void pup(PUP::er &p) { p|handle; p|fromPe; p|toPe; }
00341 };
00342
00343 private:
00344 int foundNeighbors;
00345 CmiGroup group1;
00346 int group1_created;
00347
00348 protected:
00349 virtual bool QueryBalanceNow(int) { return true; };
00350 virtual bool QueryMigrateStep(int) { return true; };
00351 virtual LBMigrateMsg* Strategy(LDStats* stats);
00352 virtual void work(LDStats* stats);
00353 virtual LBMigrateMsg * createMigrateMsg(LDStats* stats);
00354
00355 LBMigrateMsg * createMigrateMsg(CkVec<MigrateInfo *> &migrateInfo, int count);
00356 virtual LBVectorMigrateMsg* VectorStrategy(LDStats* stats);
00357 void printSummary(LDStats *stats, int count);
00358 void initTree();
00359 void collectCommData(int objIdx, CkVec<LDCommData> &comm, int atlevel);
00360
00361
00362 virtual LBMigrateMsg* Strategy(LDStats* stats, int nprocs) {
00363 return Strategy(stats);
00364 }
00365
00366 virtual CLBStatsMsg* AssembleStats();
00367 virtual int useMem();
00368 int NeighborIndex(int pe, int atlevel);
00369
00370 MyHierarchyTree *tree;
00371 int shrinklevel;
00372
00373 class LevelData {
00374 public:
00375 int parent;
00376 int* children;
00377 int nChildren;
00378 CLBStatsMsg **statsMsgsList;
00379 int stats_msg_count;
00380 LDStats *statsData;
00381 int obj_expected, obj_completed;
00382 int migrates_expected, migrates_completed;
00383 int mig_reported;
00384 int info_recved;
00385 int vector_expected, vector_completed;
00386 int resumeAfterMigration;
00387 CkVec<MigrationRecord> outObjs;
00388
00389 std::map< LDObjKey, int > unmatchedObjs;
00390 CkVec<Location> matchedObjs;
00391 public:
00392 LevelData(): parent(-1), children(NULL), nChildren(0),
00393 statsMsgsList(NULL), stats_msg_count(0),
00394 statsData(NULL), obj_expected(-1), obj_completed(0),
00395 migrates_expected(-1), migrates_completed(0),
00396 mig_reported(0), info_recved(0),
00397 vector_expected(-1), vector_completed(0),
00398 resumeAfterMigration(0)
00399 {}
00400 ~LevelData() {
00401 if (children) delete [] children;
00402 if (statsMsgsList) delete [] statsMsgsList;
00403 if (statsData) delete statsData;
00404 }
00405 int migrationDone() {
00406
00407 return migrates_expected == 0 || migrates_completed + obj_completed == migrates_expected;
00408 }
00409 int vectorReceived() {
00410 return vector_expected==0 || vector_expected == vector_completed;
00411 }
00412 void clear() {
00413 obj_expected = -1;
00414 obj_completed = 0;
00415 migrates_expected = -1;
00416 migrates_completed = 0;
00417 mig_reported = 0;
00418 info_recved = 0;
00419 vector_expected = -1;
00420 vector_completed = 0;
00421 resumeAfterMigration = 0;
00422 if (statsData) statsData->clear();
00423 outObjs.free();
00424 matchedObjs.free();
00425 unmatchedObjs.clear();
00426 }
00427 int useMem() {
00428 int memused = sizeof(LevelData);
00429 if (statsData) memused += statsData->useMem();
00430 memused += outObjs.size() * sizeof(MigrationRecord);
00431 memused += (unmatchedObjs.size()+matchedObjs.size()) * sizeof(Location);
00432 return memused;
00433 }
00434 };
00435
00436 CkVec<LevelData *> levelData;
00437
00438 int currentLevel;
00439
00440 enum StatsStrategy { FULL, SHRINK, SHRINK_NULL} ;
00441 StatsStrategy statsStrategy;
00442
00443 private:
00444 void FindNeighbors();
00445 void buildStats(int level);
00446 CLBStatsMsg * buildCombinedLBStatsMessage(int atlevel);
00447 void depositLBStatsMessage(CLBStatsMsg *msg, int atlevel);
00448
00449 int future_migrates_expected;
00450 LBMigrateMsg** mig_msgs;
00451 int mig_msgs_received;
00452 int cur_ld_balancer;
00453 double start_lb_time;
00454
00455 double maxLoad;
00456 double maxCpuLoad;
00457 double maxCommBytes;
00458 int maxCommCount;
00459 double totalLoad;
00460 double maxMem;
00461
00462 CkVec<Location> newObjs;
00463
00464 int vector_n_moves;
00465 };
00466
00467
00468 #endif
00469