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 int 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 int isroot(int mype, int level) {
00072 if (level == 0) return 0;
00073 if (level == 1 && mype == toproot) return 1;
00074 return 0;
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 int isroot(int mype, int level) {
00132 if (level == 0) return 0;
00133 if (level == 1 && mype % span[0] == 0) return 1;
00134 if (level == 2 && mype == toproot) return 1;
00135 return 0;
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 int isroot(int mype, int level) {
00197 if (level == 0) return 0;
00198 if (level == 1 && (mype % span[0]) == 0) return 1;
00199 if (level == 2 && ((mype-1)%(span[0]*span[1])) == 0) return 1;
00200 if (level == 3 && mype == toproot) return 1;
00201 return 0;
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 int isroot(int mype, int level) {
00262 if (level == 0) return 0;
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 1;
00267 return 0;
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 BaseLB
00296 {
00297 public:
00298 HybridBaseLB(const CkLBOptions &);
00299 HybridBaseLB(CkMigrateMessage *m):BaseLB(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(CkReductionMsg *msg);
00308 void ResumeClients(int balancing);
00309 void ReceiveMigration(LBMigrateMsg *);
00310 void ReceiveVectorMigration(LBVectorMigrateMsg *);
00311 void TotalObjMigrated(int count, int level);
00312
00313
00314 static void staticMigrated(void* me, LDObjHandle h, int waitBarrier);
00315 void Migrated(LDObjHandle h, int waitBarrier);
00316
00317 void ObjMigrated(LDObjData data, LDCommData *cdata, int n, int level);
00318 void ObjsMigrated(LDObjData *data, int m, LDCommData *cdata, int n, int level);
00319 void VectorDone(int atlevel);
00320 void MigrationDone(int balancing);
00321 void StatsDone(int level);
00322 void NotifyObjectMigrationDone(int level);
00323 virtual void Loadbalancing(int level);
00324 void StartCollectInfo(DummyMsg *m);
00325 void CollectInfo(Location *loc, int n, int fromlevel);
00326 void PropagateInfo(Location *loc, int n, int fromlevel);
00327
00328 void reportLBQulity(double mload, double mCpuLoad, double totalload, int nmsgs, double bytesentry );
00329 void reportLBMem(double);
00330
00331 struct MigrationRecord {
00332 LDObjHandle handle;
00333 int fromPe;
00334 int toPe;
00335 MigrationRecord(): fromPe(-1), toPe(-1) {}
00336 MigrationRecord(LDObjHandle &k, int f, int t): handle(k), fromPe(f), toPe(t) {}
00337 void pup(PUP::er &p) { p|handle; p|fromPe; p|toPe; }
00338 };
00339
00340 private:
00341 CProxy_HybridBaseLB thisProxy;
00342 int foundNeighbors;
00343 CmiGroup group1;
00344 int group1_created;
00345
00346 protected:
00347 virtual CmiBool QueryBalanceNow(int) { return CmiTrue; };
00348 virtual CmiBool QueryMigrateStep(int) { return CmiTrue; };
00349 virtual LBMigrateMsg* Strategy(LDStats* stats);
00350 virtual void work(LDStats* stats);
00351 virtual LBMigrateMsg * createMigrateMsg(LDStats* stats);
00352
00353 LBMigrateMsg * createMigrateMsg(CkVec<MigrateInfo *> &migrateInfo, int count);
00354 virtual LBVectorMigrateMsg* VectorStrategy(LDStats* stats);
00355 void printSummary(LDStats *stats, int count);
00356 void initTree();
00357
00358
00359 virtual LBMigrateMsg* Strategy(LDStats* stats, int nprocs) {
00360 return Strategy(stats);
00361 }
00362
00363 virtual int useMem();
00364 int NeighborIndex(int pe, int atlevel);
00365
00366 MyHierarchyTree *tree;
00367 int shrinklevel;
00368
00369 class LevelData {
00370 public:
00371 int parent;
00372 int* children;
00373 int nChildren;
00374 CLBStatsMsg **statsMsgsList;
00375 int stats_msg_count;
00376 LDStats *statsData;
00377 int obj_expected, obj_completed;
00378 int migrates_expected, migrates_completed;
00379 int mig_reported;
00380 int info_recved;
00381 int vector_expected, vector_completed;
00382 int resumeAfterMigration;
00383 CkVec<MigrationRecord> outObjs;
00384
00385 std::map< LDObjKey, int > unmatchedObjs;
00386 CkVec<Location> matchedObjs;
00387 public:
00388 LevelData(): parent(-1), children(NULL), nChildren(0),
00389 statsMsgsList(NULL), stats_msg_count(0),
00390 statsData(NULL), obj_expected(-1), obj_completed(0),
00391 migrates_expected(-1), migrates_completed(0),
00392 mig_reported(0), info_recved(0),
00393 vector_expected(-1), vector_completed(0),
00394 resumeAfterMigration(0)
00395 {}
00396 ~LevelData() {
00397 if (children) delete [] children;
00398 if (statsMsgsList) delete [] statsMsgsList;
00399 if (statsData) delete statsData;
00400 }
00401 int migrationDone() {
00402
00403 return migrates_expected == 0 || migrates_completed + obj_completed == migrates_expected;
00404 }
00405 int vectorReceived() {
00406 return vector_expected==0 || vector_expected == vector_completed;
00407 }
00408 void clear() {
00409 obj_expected = -1;
00410 obj_completed = 0;
00411 migrates_expected = -1;
00412 migrates_completed = 0;
00413 mig_reported = 0;
00414 info_recved = 0;
00415 vector_expected = -1;
00416 vector_completed = 0;
00417 resumeAfterMigration = 0;
00418 if (statsData) statsData->clear();
00419 outObjs.free();
00420 matchedObjs.free();
00421 unmatchedObjs.clear();
00422 }
00423 int useMem() {
00424 int memused = sizeof(LevelData);
00425 if (statsData) memused += statsData->useMem();
00426 memused += outObjs.size() * sizeof(MigrationRecord);
00427 memused += (unmatchedObjs.size()+matchedObjs.size()) * sizeof(Location);
00428 return memused;
00429 }
00430 };
00431
00432 CkVec<LevelData *> levelData;
00433
00434 int currentLevel;
00435
00436 enum StatsStrategy { FULL, SHRINK, SHRINK_NULL} ;
00437 StatsStrategy statsStrategy;
00438
00439 private:
00440 void FindNeighbors();
00441 CLBStatsMsg* AssembleStats();
00442 void buildStats(int level);
00443 CLBStatsMsg * buildCombinedLBStatsMessage(int atlevel);
00444 void depositLBStatsMessage(CLBStatsMsg *msg, int atlevel);
00445 void collectCommData(int objIdx, CkVec<LDCommData> &comm, int atlevel);
00446
00447 int future_migrates_expected;
00448 LBMigrateMsg** mig_msgs;
00449 int mig_msgs_received;
00450 int cur_ld_balancer;
00451 double start_lb_time;
00452
00453 double maxLoad;
00454 double maxCpuLoad;
00455 double maxCommBytes;
00456 int maxCommCount;
00457 double totalLoad;
00458 double maxMem;
00459
00460 CkVec<Location> newObjs;
00461
00462 int vector_n_moves;
00463 };
00464
00465
00466 #endif
00467