Merge branch 'charm' of charmgit:charm into harshitha/adaptive_lb
authorHarshitha <gplkrsh2@illinois.edu>
Fri, 19 Oct 2012 16:04:57 +0000 (11:04 -0500)
committerHarshitha <gplkrsh2@illinois.edu>
Fri, 19 Oct 2012 16:04:57 +0000 (11:04 -0500)
34 files changed:
examples/charm++/load_balancing/kNeighbor/kNeighbor.C
src/ck-core/ckarray.C
src/ck-core/cklocation.C
src/ck-core/cklocation.ci
src/ck-core/cklocation.h
src/ck-core/init.C
src/ck-ldb/AdaptiveLB.C [new file with mode: 0644]
src/ck-ldb/AdaptiveLB.ci [new file with mode: 0644]
src/ck-ldb/AdaptiveLB.h [new file with mode: 0644]
src/ck-ldb/BaseLB.h
src/ck-ldb/CentralLB.C
src/ck-ldb/CentralLB.h
src/ck-ldb/EveryLB.ci
src/ck-ldb/GreedyLB.C
src/ck-ldb/HybridBaseLB.C
src/ck-ldb/HybridLB.C
src/ck-ldb/LBDBManager.C
src/ck-ldb/LBDBManager.h
src/ck-ldb/LBDatabase.C
src/ck-ldb/LBDatabase.h
src/ck-ldb/LBOM.h
src/ck-ldb/LBSimulation.C
src/ck-ldb/Make.lb
src/ck-ldb/Makefile_lb.sh
src/ck-ldb/MetaBalancer.C [new file with mode: 0644]
src/ck-ldb/MetaBalancer.ci [new file with mode: 0644]
src/ck-ldb/MetaBalancer.h [new file with mode: 0644]
src/ck-ldb/RefineLB.C
src/ck-ldb/Refiner.C
src/ck-ldb/Refiner.h
src/ck-ldb/lbdb.C
src/ck-ldb/lbdb.h
src/scripts/Make.cidepends
src/scripts/Makefile

index 6d3ad974ca6cf9dfd839d375f6af554f2c417848..98a3267612c44bec6981e5635080cdb06df0a4b1 100644 (file)
@@ -72,10 +72,10 @@ class Main: public CBase_Main {
       }
 
       num_chares = atoi(m->argv[1]);
-      if(num_chares < CkNumPes()) {
-       printf("Warning: #elements is forced to be equal to #pes\n");
-       num_chares = CkNumPes();
-      }
+//      if(num_chares < CkNumPes()) {
+//     printf("Warning: #elements is forced to be equal to #pes\n");
+//     num_chares = CkNumPes();
+//      }
 
       numSteps = atoi(m->argv[2]);
       currentMsgSize = atoi(m->argv[3]);
index f4bded4396c33a0e415c842df85496343d2b2fa4..3d929e4db1faff9a9b6591956d26e4c5ce20d1da 100644 (file)
@@ -619,10 +619,11 @@ CkArrayID CProxy_ArrayBase::ckCreateArray(CkArrayMessage *m,int ctor,
   { //Create a new location manager
 #if !CMK_LBDB_ON
     CkGroupID _lbdb;
+    CkGroupID _metalb;
 #endif
     CkEntryOptions  e_opts;
     e_opts.setGroupDepID(opts.getMap());       // group creation dependence
-    locMgr = CProxy_CkLocMgr::ckNew(opts.getMap(),_lbdb,opts.getNumInitial(),&e_opts);
+    locMgr = CProxy_CkLocMgr::ckNew(opts.getMap(),_lbdb,_metalb,opts.getNumInitial(),&e_opts);
     opts.setLocationManager(locMgr);
   }
   //Create the array manager
index c33807bab89b9e469e81b8b42ac708b42b2d4927..95038019eef6f3396c0c514663185d85b5eafdf7 100644 (file)
@@ -18,6 +18,7 @@
 
 #if CMK_LBDB_ON
 #include "LBDatabase.h"
+#include "MetaBalancer.h"
 #if CMK_GLOBAL_LOCATION_UPDATE
 #include "BaseLB.h"
 #include "init.h"
@@ -46,6 +47,7 @@ static const char *idx2str(const CkArrayMessage *m) {
 #   define AA "LocMgr on %d: "
 #   define AB ,CkMyPe()
 #   define DEBUG(x) CkPrintf x
+#   define DEBAD(x) CkPrintf x
 #else
 #   define DEB(X) /*CkPrintf x*/
 #   define DEBI(X) /*CkPrintf x*/
@@ -57,6 +59,7 @@ static const char *idx2str(const CkArrayMessage *m) {
 #   define DEBB(x) /*CkPrintf x*/
 #   define str(x) /**/
 #   define DEBUG(x)   /**/
+#   define DEBAD(x) /*CkPrintf x*/
 #endif
 
 //whether to use block mapping in the SMP node level
@@ -1048,6 +1051,14 @@ void CkMigratable::commonInit(void) {
        usesAtSync=CmiFalse;
        usesAutoMeasure=CmiTrue;
        barrierRegistered=CmiFalse;
+
+  local_state = OFF;
+  prev_load = 0.0;
+  can_reset = false;
+  if (_lb_args.metaLbOn()) {
+    atsync_iteration = myRec->getMetaBalancer()->get_iteration();
+  }
+
        /*
        FAULT_EVAC
        */
@@ -1069,6 +1080,7 @@ void CkMigratable::pup(PUP::er &p) {
        Chare::pup(p);
        p|thisIndexMax;
        p(usesAtSync);
+  p(can_reset);
        p(usesAutoMeasure);
 #if CMK_LBDB_ON 
        int readyMigrate;
@@ -1147,6 +1159,48 @@ double CkMigratable::getObjTime() {
        return myRec->getObjTime();
 }
 
+void CkMigratable::clearMetaLBData() {
+//  if (can_reset) {
+    local_state = OFF;
+    atsync_iteration = -1;
+    prev_load = 0.0;
+    can_reset = false;
+//  }
+}
+
+void CkMigratable::recvLBPeriod(void *data) {
+  if (atsync_iteration < 0) {
+    return;
+  }
+  int lb_period = *((int *) data);
+ DEBAD(("\t[obj %s] Received the LB Period %d current iter %d state %d on PE %d\n",
+     idx2str(thisIndexMax), lb_period, atsync_iteration, local_state, CkMyPe()));
+
+  bool is_tentative;
+  if (local_state == LOAD_BALANCE) {
+    CkAssert(lb_period == myRec->getMetaBalancer()->getPredictedLBPeriod(is_tentative));
+    return;
+  }
+
+  if (local_state == PAUSE) {
+    if (atsync_iteration < lb_period) {
+      local_state = DECIDED;
+      ResumeFromSync();
+      return;
+    }
+    local_state = LOAD_BALANCE;
+
+    can_reset = true;
+    //myRec->getLBDB()->AtLocalBarrier(ldBarrierHandle);
+    return;
+  }
+  local_state = DECIDED;
+}
+
+void CkMigratable::metaLBCallLB() {
+       myRec->getLBDB()->AtLocalBarrier(ldBarrierHandle);
+}
+
 void CkMigratable::ckFinishConstruction(void)
 {
 //     if ((!usesAtSync) || barrierRegistered) return;
@@ -1161,6 +1215,7 @@ void CkMigratable::ckFinishConstruction(void)
                (LDBarrierFn)staticResumeFromSync,(void*)(this));
        barrierRegistered=CmiTrue;
 }
+
 void CkMigratable::AtSync(int waitForMigration)
 {
        if (!usesAtSync)
@@ -1171,11 +1226,57 @@ void CkMigratable::AtSync(int waitForMigration)
        myRec->AsyncMigrate(!waitForMigration);
        if (waitForMigration) ReadyMigrate(CmiTrue);
        ckFinishConstruction();
-       DEBL((AA"Element %s going to sync\n"AB,idx2str(thisIndexMax)));
-          // model-based load balancing, ask user to provide cpu load
-        if (usesAutoMeasure == CmiFalse) UserSetLBLoad();
-       myRec->getLBDB()->AtLocalBarrier(ldBarrierHandle);
+  DEBL((AA"Element %s going to sync\n"AB,idx2str(thisIndexMax)));
+  // model-based load balancing, ask user to provide cpu load
+  if (usesAutoMeasure == CmiFalse) UserSetLBLoad();
+
+  if (!_lb_args.metaLbOn()) {
+    myRec->getLBDB()->AtLocalBarrier(ldBarrierHandle);
+    return;
+  }
+
+  // When MetaBalancer is turned on
+
+  if (atsync_iteration == -1) {
+    can_reset = false;
+    local_state = OFF;
+    prev_load = 0.0;
+  }
+
+  atsync_iteration++;
+  //CkPrintf("[pe %s] atsync_iter %d && predicted period %d state: %d\n",
+  //    idx2str(thisIndexMax), atsync_iteration,
+  //    myRec->getMetaBalancer()->getPredictedLBPeriod(), local_state);
+  double tmp = prev_load;
+  prev_load = myRec->getObjTime();
+  double current_load = prev_load - tmp;
+  if (atsync_iteration <= myRec->getMetaBalancer()->get_finished_iteration()) {
+    CkPrintf("[%d:%s] Error!! Contributing to iter %d < current iter %d\n",
+      CkMyPe(), idx2str(thisIndexMax), atsync_iteration,
+      myRec->getMetaBalancer()->get_finished_iteration());
+    CkAbort("Not contributing to the right iteration\n");
+  }
+
+  if (atsync_iteration != 0) {
+    myRec->getMetaBalancer()->AddLoad(atsync_iteration, current_load);
+  }
+
+  bool is_tentative;
+  if (atsync_iteration < myRec->getMetaBalancer()->getPredictedLBPeriod(is_tentative)) {
+    ResumeFromSync();
+  } else if (is_tentative) {
+    local_state = PAUSE;
+  } else if (local_state == DECIDED) {
+    DEBAD(("[%d:%s] Went to load balance iter %d\n", CkMyPe(), idx2str(thisIndexMax), atsync_iteration));
+    local_state = LOAD_BALANCE;
+    can_reset = true;
+    //myRec->getLBDB()->AtLocalBarrier(ldBarrierHandle);
+  } else {
+    DEBAD(("[%d:%s] Went to pause state iter %d\n", CkMyPe(), idx2str(thisIndexMax), atsync_iteration));
+    local_state = PAUSE;
+  }
 }
+
 void CkMigratable::ReadyMigrate(CmiBool ready)
 {
        myRec->ReadyMigrate(ready);
@@ -1197,6 +1298,10 @@ void CkMigratable::staticResumeFromSync(void* data)
 #if (defined(_FAULT_MLOG_) || defined(_FAULT_CAUSAL_))
     CpvAccess(_currentObj) = el;
 #endif
+
+  if (_lb_args.metaLbOn()) {
+       el->clearMetaLBData();
+       }
        el->ResumeFromSync();
 #if (defined(_FAULT_MLOG_) || defined(_FAULT_CAUSAL_))
     el->mlogData->resumeCount++;
@@ -1308,6 +1413,9 @@ CkLocRec_local::CkLocRec_local(CkLocMgr *mgr,CmiBool fromMigration,
         enable_measure = CmiTrue;
        bounced  = CmiFalse;
        the_lbdb=mgr->getLBDB();
+  if (_lb_args.metaLbOn()) {
+    the_metalb=mgr->getMetaBalancer();
+  }
         LDObjid ldid = idx2LDObjid(idx);
 #if CMK_GLOBAL_LOCATION_UPDATE
         ldid.locMgrGid = mgr->getGroupID().idx;
@@ -1345,6 +1453,14 @@ void CkLocRec_local::migrateMe(int toPe) //Leaving this processor
        myLocMgr->emigrate(this,toPe);
 }
 
+void CkLocRec_local::informIdealLBPeriod(int lb_ideal_period) {
+  myLocMgr->informLBPeriod(this, lb_ideal_period);
+}
+
+void CkLocRec_local::metaLBCallLB() {
+       myLocMgr->metaLBCallLB(this);
+}
+
 #if CMK_LBDB_ON
 void CkLocRec_local::startTiming(int ignore_running) {
        if (!ignore_running) running=CmiTrue;
@@ -1563,6 +1679,27 @@ CmiBool CkLocRec_local::deliver(CkArrayMessage *msg,CkDeliver_t type,int opts)
 }
 
 #if CMK_LBDB_ON
+
+void CkLocRec_local::staticMetaLBResumeWaitingChares(LDObjHandle h, int lb_ideal_period) {
+       CkLocRec_local *el=(CkLocRec_local *)LDObjUserData(h);
+       DEBL((AA"MetaBalancer wants to resume waiting chare %s\n"AB,idx2str(el->idx)));
+       el->metaLBResumeWaitingChares(lb_ideal_period);
+}
+
+void CkLocRec_local::metaLBResumeWaitingChares(int lb_ideal_period) {
+  informIdealLBPeriod(lb_ideal_period);
+}
+
+void CkLocRec_local::staticMetaLBCallLBOnChares(LDObjHandle h) {
+       CkLocRec_local *el=(CkLocRec_local *)LDObjUserData(h);
+       DEBL((AA"MetaBalancer wants to call LoadBalance on chare %s\n"AB,idx2str(el->idx)));
+       el->metaLBCallLBOnChares();
+}
+
+void CkLocRec_local::metaLBCallLBOnChares() {
+  metaLBCallLB();
+}
+
 void CkLocRec_local::staticMigrate(LDObjHandle h, int dest)
 {
        CkLocRec_local *el=(CkLocRec_local *)LDObjUserData(h);
@@ -1905,7 +2042,7 @@ void CkLocMgr::callForAllRecords(CkLocFn fnPointer,CkArray *arr,void *data){
 #endif
 
 /*************************** LocMgr: CREATION *****************************/
-CkLocMgr::CkLocMgr(CkGroupID mapID_,CkGroupID lbdbID_,CkArrayIndex& numInitial)
+CkLocMgr::CkLocMgr(CkGroupID mapID_,CkGroupID lbdbID_,CkGroupID metalbID_,CkArrayIndex& numInitial)
        :thisProxy(thisgroup),thislocalproxy(thisgroup,CkMyPe()),
         hash(17,0.3)
 {
@@ -1931,10 +2068,22 @@ CkLocMgr::CkLocMgr(CkGroupID mapID_,CkGroupID lbdbID_,CkArrayIndex& numInitial)
 
 //Find and register with the load balancer
        lbdbID = lbdbID_;
-       initLB(lbdbID_);
+  metalbID = metalbID_;
+       initLB(lbdbID_, metalbID_);
        hashImmLock = CmiCreateImmediateLock();
 }
 
+CkLocMgr::CkLocMgr(CkGroupID mapID_,CkGroupID lbdbID_,CkArrayIndex& numInitial)
+       :thisProxy(thisgroup),thislocalproxy(thisgroup,CkMyPe()),
+        hash(17,0.3)
+{
+#if !CMK_LBDB_ON
+       CkGroupID _metalb;
+#endif
+       CkLocMgr(mapID_, lbdbID_, _metalb, numInitial);
+}
+
+
 CkLocMgr::CkLocMgr(CkMigrateMessage* m)
        :IrrGroup(m),thisProxy(thisgroup),thislocalproxy(thisgroup,CkMyPe()),hash(17,0.3)
 {
@@ -1955,6 +2104,7 @@ void CkLocMgr::pup(PUP::er &p){
        p|mapID;
        p|mapHandle;
        p|lbdbID;
+  p|metalbID;
        mapID = _defaultArrayMapID;
        if(p.isUnpacking()){
                thisProxy=thisgroup;
@@ -1966,7 +2116,7 @@ void CkLocMgr::pup(PUP::er &p){
                 CkArrayIndex emptyIndex;
                map->registerArray(emptyIndex,thisgroup);
                // _lbdb is the fixed global groupID
-               initLB(lbdbID);
+               initLB(lbdbID, metalbID);
 
 #if (defined(_FAULT_MLOG_) || defined(_FAULT_CAUSAL_))     
         int count;
@@ -2640,6 +2790,16 @@ void CkLocMgr::callMethod(CkLocRec_local *rec,CkMigratable_voidfn_t fn)
        }
 }
 
+/// Call this member function on each element of this location:
+void CkLocMgr::callMethod(CkLocRec_local *rec,CkMigratable_voidfn_arg_t fn,     void * data)
+{
+       int localIdx=rec->getLocalIndex();
+       for (ManagerRec *m=firstManager;m!=NULL;m=m->next) {
+               CkMigratable *el=m->element(localIdx);
+               if (el) (el->* fn)(data);
+       }
+}
+
 /// return a list of migratables in this local record
 void CkLocMgr::migratableList(CkLocRec_local *rec, CkVec<CkMigratable *> &list)
 {
@@ -2749,6 +2909,14 @@ void CkLocMgr::emigrate(CkLocRec_local *rec,int toPe)
        CK_MAGICNUMBER_CHECK
 }
 
+void CkLocMgr::informLBPeriod(CkLocRec_local *rec, int lb_ideal_period) {
+       callMethod(rec,&CkMigratable::recvLBPeriod, (void *)&lb_ideal_period);
+}
+
+void CkLocMgr::metaLBCallLB(CkLocRec_local *rec) {
+       callMethod(rec, &CkMigratable::metaLBCallLB);
+}
+
 /**
   Migrating array element is arriving on this processor.
 */
@@ -3017,7 +3185,7 @@ unsigned int CkLocMgr::numLocalElements()
 
 #if !CMK_LBDB_ON
 //Empty versions of all load balancer calls
-void CkLocMgr::initLB(CkGroupID lbdbID_) {}
+void CkLocMgr::initLB(CkGroupID lbdbID_, CkGroupID metalbID_) {}
 void CkLocMgr::startInserting(void) {}
 void CkLocMgr::doneInserting(void) {}
 void CkLocMgr::dummyAtSync(void) {}
@@ -3025,12 +3193,17 @@ void CkLocMgr::dummyAtSync(void) {}
 
 
 #if CMK_LBDB_ON
-void CkLocMgr::initLB(CkGroupID lbdbID_)
+void CkLocMgr::initLB(CkGroupID lbdbID_, CkGroupID metalbID_)
 { //Find and register with the load balancer
        the_lbdb = (LBDatabase *)CkLocalBranch(lbdbID_);
        if (the_lbdb == 0)
                CkAbort("LBDatabase not yet created?\n");
        DEBL((AA"Connected to load balancer %p\n"AB,the_lbdb));
+  if (_lb_args.metaLbOn()) {
+    the_metalb = (MetaBalancer *)CkLocalBranch(metalbID_);
+    if (the_metalb == 0)
+      CkAbort("MetaBalancer not yet created?\n");
+  }
 
        // Register myself as an object manager
        LDOMid myId;
@@ -3039,6 +3212,10 @@ void CkLocMgr::initLB(CkGroupID lbdbID_)
        myCallbacks.migrate = (LDMigrateFn)CkLocRec_local::staticMigrate;
        myCallbacks.setStats = NULL;
        myCallbacks.queryEstLoad = NULL;
+  myCallbacks.metaLBResumeWaitingChares =
+      (LDMetaLBResumeWaitingCharesFn)CkLocRec_local::staticMetaLBResumeWaitingChares;
+  myCallbacks.metaLBCallLBOnChares =
+      (LDMetaLBCallLBOnCharesFn)CkLocRec_local::staticMetaLBCallLBOnChares;
        myLBHandle = the_lbdb->RegisterOM(myId,this,myCallbacks);
 
        // Tell the lbdb that I'm registering objects
index 3a2271ee2d6e393c10f081eb9231e1250462b220..cfaa08cf363f30dd542b38ac864a17f738b16a4e 100644 (file)
@@ -6,6 +6,7 @@ module CkLocation {
   };
 
   group [migratable] CkLocMgr {
+       entry CkLocMgr(CkGroupID map,CkGroupID _lbdb,CkGroupID _metalb,CkArrayIndex numInitial);
        entry CkLocMgr(CkGroupID map,CkGroupID _lbdb,CkArrayIndex numInitial);
        entry void deliverInline(CkMessage *m);
        entry [expedited] void immigrate(CkArrayElementMigrateMessage *msg);
index 00076bfde4cbf66b0844f27429a803ae6a4b62be..f09764166df743b49ef06c48706acdb2c9bc2b05 100644 (file)
@@ -28,6 +28,7 @@ public:
 /* Utility */
 //#if CMK_LBDB_ON
 #include "LBDatabase.h"
+#include "MetaBalancer.h"
 class LBDatabase;
 //#endif
 
@@ -173,6 +174,8 @@ public:
   CkLocRec_local(CkLocMgr *mgr,CmiBool fromMigration,CmiBool ignoreArrival,
        const CkArrayIndex &idx_,int localIdx_);
   void migrateMe(int toPe); //Leave this processor
+  void informIdealLBPeriod(int lb_ideal_period);
+  void metaLBCallLB();
   void destroy(void); //User called destructor
   virtual ~CkLocRec_local();
 
@@ -213,8 +216,13 @@ public:
 #if CMK_LBDB_ON
 public:
   inline LBDatabase *getLBDB(void) const {return the_lbdb;}
+  inline MetaBalancer *getMetaBalancer(void) const {return the_metalb;}
   inline LDObjHandle getLdHandle() const{return ldHandle;}
   static void staticMigrate(LDObjHandle h, int dest);
+  static void staticMetaLBResumeWaitingChares(LDObjHandle h, int lb_ideal_period);
+  static void staticMetaLBCallLBOnChares(LDObjHandle h);
+  void metaLBResumeWaitingChares(int lb_ideal_period);
+  void metaLBCallLBOnChares();
   void recvMigrate(int dest);
   void setMigratable(int migratable);  /// set migratable
   void AsyncMigrate(CmiBool use);
@@ -229,6 +237,7 @@ public:
   inline void setMeasure(CmiBool status) { enable_measure = status; }
 private:
   LBDatabase *the_lbdb;
+  MetaBalancer *the_metalb;
   LDObjHandle ldHandle;
   CmiBool  asyncMigrate;  /// if readyMove is inited
   CmiBool  readyMigrate;    /// status whether it is ready to migrate
@@ -271,6 +280,18 @@ private:
   int thisChareType;//My chare type
   void commonInit(void);
   CmiBool asyncEvacuate;
+  int atsync_iteration;
+
+  enum state {
+    OFF,
+    ON,
+    PAUSE,
+    DECIDED,
+    LOAD_BALANCE
+  } local_state;
+  double  prev_load;
+  bool can_reset;
+
 public:
   CkArrayIndex thisIndexMax;
 
@@ -289,6 +310,7 @@ public:
   //Begin load balancer measurements again (e.g., after CthSuspend)
   inline void ckStartTiming(void) {myRec->startTiming();}
   inline LBDatabase *getLBDB(void) const {return myRec->getLBDB();}
+  inline MetaBalancer *getMetaBalancer(void) const {return myRec->getMetaBalancer();}
 #else
   inline void ckStopTiming(void) { }
   inline void ckStartTiming(void) { }
@@ -305,6 +327,10 @@ public:
   virtual void ckAboutToMigrate(void); /*default is empty*/
   virtual void ckJustMigrated(void); /*default is empty*/
 
+  void recvLBPeriod(void *data);
+  void metaLBCallLB();
+  void clearMetaLBData(void);
+
   //used for out-of-core emulation
   virtual void ckJustRestored(void); /*default is empty*/
 
@@ -519,6 +545,7 @@ typedef void (*CkLocFn)(CkArray *,void *,CkLocRec *,CkArrayIndex *);
 class CkLocMgr : public IrrGroup {
        CkMagicNumber<CkMigratable> magic; //To detect heap corruption
 public:
+       CkLocMgr(CkGroupID map,CkGroupID _lbdb,CkGroupID _metalb,CkArrayIndex& numInitial);
        CkLocMgr(CkGroupID map,CkGroupID _lbdb,CkArrayIndex& numInitial);
        CkLocMgr(CkMigrateMessage *m);
        inline CmiBool isLocMgr(void) { return CmiTrue; }
@@ -580,9 +607,12 @@ public:
 
        //Migrate us to another processor
        void emigrate(CkLocRec_local *rec,int toPe);
+  void informLBPeriod(CkLocRec_local *rec, int lb_ideal_period);
+  void metaLBCallLB(CkLocRec_local *rec);
 
 #if CMK_LBDB_ON
        LBDatabase *getLBDB(void) const { return the_lbdb; }
+  MetaBalancer *getMetaBalancer(void) const { return the_metalb;}
        const LDOMHandle &getOMHandle(void) const { return myLBHandle; }
 #endif
 
@@ -671,6 +701,9 @@ private:
        /// Call this member function on each element of this location:
        typedef void (CkMigratable::* CkMigratable_voidfn_t)(void);
 
+       typedef void (CkMigratable::* CkMigratable_voidfn_arg_t)(void*);
+       void callMethod(CkLocRec_local *rec,CkMigratable_voidfn_arg_t fn, void*);
+
        CmiBool deliverUnknown(CkArrayMessage *msg,CkDeliver_t type,int opts);
 
        /// Create a new local record at this array index.
@@ -736,8 +769,10 @@ public:
        CkArrayMap *map;
 
        CkGroupID lbdbID;
+       CkGroupID metalbID;
 #if CMK_LBDB_ON
        LBDatabase *the_lbdb;
+  MetaBalancer *the_metalb;
        LDBarrierClient dummyBarrierHandle;
        static void staticDummyResumeFromSync(void* data);
        void dummyResumeFromSync(void);
@@ -745,7 +780,7 @@ public:
        void recvAtSync(void);
        LDOMHandle myLBHandle;
 #endif
-       void initLB(CkGroupID lbdbID);
+       void initLB(CkGroupID lbdbID, CkGroupID metalbID);
 
 #if (defined(_FAULT_MLOG_) || defined(_FAULT_CAUSAL_))
 public:
index 77908a9c2d6589086aa1d1a97c547287334e5c5a..4de014d63f446f5283410b9b18950a30840ffef9 100644 (file)
@@ -864,6 +864,7 @@ static void _nullFn(void *, void *)
 }
 
 extern void _registerLBDatabase(void);
+extern void _registerMetaBalancer(void);
 extern void _registerPathHistory(void);
 #if CMK_WITH_CONTROLPOINT
 extern void _registerControlPoints(void);
@@ -872,6 +873,7 @@ extern void _registerTraceControlPoints();
 extern void _registerExternalModules(char **argv);
 extern void _ckModuleInit(void);
 extern void _loadbalancerInit();
+extern void _metabalancerInit();
 extern void _initChareTables();
 #if CMK_MEM_CHECKPOINT
 extern void init_memcheckpt(char **argv);
@@ -1052,6 +1054,7 @@ void _initCharm(int unused_argc, char **argv)
 
        _futuresModuleInit(); // part of futures implementation is a converse module
        _loadbalancerInit();
+  _metabalancerInit();
        
 #if CMK_MEM_CHECKPOINT
         init_memcheckpt(argv);
@@ -1107,6 +1110,7 @@ void _initCharm(int unused_argc, char **argv)
                _registerCkFutures();
                _registerCkArray();
                _registerLBDatabase();
+    _registerMetaBalancer();
                _registerCkCallback();
                _registertempo();
                _registerwaitqd();
diff --git a/src/ck-ldb/AdaptiveLB.C b/src/ck-ldb/AdaptiveLB.C
new file mode 100644 (file)
index 0000000..4207876
--- /dev/null
@@ -0,0 +1,163 @@
+/**
+ * \addtogroup CkLdb
+*/
+/*@{*/
+
+#include "AdaptiveLB.h"
+#include "ckgraph.h"
+
+#define alpha 4.0e-6
+#define beta 2.67e-9
+#define percent_overhead 10
+
+extern LBAllocFn getLBAllocFn(char *lbname);
+
+CreateLBFunc_Def(AdaptiveLB, "Allow multiple strategies to work serially")
+
+AdaptiveLB::AdaptiveLB(const CkLBOptions &opt): CentralLB(opt)
+{
+  lbname = "AdaptiveLB";
+  const char *lbs = theLbdb->loadbalancer(opt.getSeqNo());
+  if (CkMyPe() == 0)
+    CkPrintf("[%d] AdaptiveLB created with %s\n",CkMyPe(), lbs);
+
+  char *lbcopy = strdup(lbs);
+  char *greedyLBString = "GreedyLB";
+  char *refineLBString = "RefineLB";
+  char *metisLBString = "MetisLB";
+  char *commRefineLBString = "CommAwareRefineLB";
+
+  LBAllocFn fn = getLBAllocFn(greedyLBString);
+  if (fn == NULL) {
+    CkPrintf("LB> Invalid load balancer: %s.\n", greedyLBString);
+    CmiAbort("");
+  }
+  BaseLB *glb = fn();
+  greedyLB = (CentralLB*)glb;
+
+  fn = getLBAllocFn(refineLBString);
+  if (fn == NULL) {
+    CkPrintf("LB> Invalid load balancer: %s.\n", refineLBString);
+    CmiAbort("");
+  }
+  BaseLB *rlb = fn();
+  refineLB = (CentralLB*)rlb;
+
+  fn = getLBAllocFn(metisLBString);
+  if (fn == NULL) {
+    CkPrintf("LB> Invalid load balancer: %s.\n", metisLBString);
+    CmiAbort("");
+  }
+  BaseLB *slb = fn();
+  metisLB = (CentralLB*)slb;
+
+  fn = getLBAllocFn(commRefineLBString);
+  if (fn == NULL) {
+    CkPrintf("LB> Invalid load balancer: %s.\n", commRefineLBString);
+    CmiAbort("");
+  }
+  BaseLB *crlb = fn();
+  commRefineLB = (CentralLB*)crlb;
+}
+
+void AdaptiveLB::work(LDStats* stats)
+{
+
+  ProcArray *parr = new ProcArray(stats);
+  ObjGraph *ogr = new ObjGraph(stats);
+  CkPrintf("Adaptive work\n");
+
+  //bool isComm = theLbdb->isStrategyComm();
+
+  // Calculate the load and total messages
+  double totalLoad = 0.0;
+  long totalMsgs = 0;
+  long long totalBytes = 0;
+  int vertnbr = ogr->vertices.size();
+
+  /** the object load is normalized to an integer between 0 and 256 */
+  for(int i = 0; i < vertnbr; i++) {
+    totalLoad += ogr->vertices[i].getVertexLoad();
+  }
+
+  for(int i = 0; i < vertnbr; i++) {
+    for(int j = 0; j < ogr->vertices[i].sendToList.size(); j++) {
+      totalMsgs += ogr->vertices[i].sendToList[j].getNumMsgs();
+      totalBytes += ogr->vertices[i].sendToList[j].getNumBytes();
+    }
+  }
+  double commOverhead = (totalMsgs * alpha) + (totalBytes * beta);
+
+  CkPrintf("AdaptiveLB> Total load %E\n", totalLoad);
+  CkPrintf("AdaptiveLB> Total Msgs %d\n", totalMsgs);
+  CkPrintf("AdaptiveLB> Total Bytes %ld\n", totalBytes);
+  CkPrintf("AdaptiveLB> Total Comm Overhead %E Total Load %E\n", commOverhead, totalLoad);
+
+  double tmp;
+  double refine_max_avg_ratio, lb_max_avg_ratio;
+  double greedy_max_avg_ratio;
+  int lb_type;
+  double comm_ratio, comm_refine_ratio;
+
+//  GetPrevLBData(lb_type, lb_max_avg_ratio, tmp);
+//  GetLBDataForLB(1, refine_max_avg_ratio, tmp);
+//  GetLBDataForLB(0, greedy_max_avg_ratio, tmp);
+//  GetLBDataForLB(2, tmp, comm_ratio);
+//  GetLBDataForLB(3, tmp, comm_refine_ratio);
+
+  CkPrintf("AdaptiveLB> Previous LB %d\n", lb_type);
+
+  // Choose the right LB
+  //
+  // If communication overhead is 10% computation, then choose Scotch LB
+  //if (isComm || (commOverhead > (totalLoad * percent_overhead / 100))) {
+  if ((commOverhead > (totalLoad * percent_overhead / 100))) {
+    if(lb_type == -1) {
+      lb_type = 2;
+      metisLB->work(stats);
+      CkPrintf("---METIS LB\n");
+    } else if (comm_refine_ratio <= 1.01) {
+      lb_type = 3;
+      commRefineLB->work(stats);
+      CkPrintf("---CommAwareRefineLB\n");
+    } else if (comm_ratio <= 1.01) {
+      lb_type = 2;
+      metisLB->work(stats);
+      CkPrintf("---METIS LB\n");
+    } else {
+      lb_type = 3;
+      commRefineLB->work(stats);
+      CkPrintf("---CommAwareRefineLB\n");
+    }
+
+  } else {
+    if (lb_type == -1) {
+      lb_type = 0;
+      greedyLB->work(stats);
+      CkPrintf("---GREEDY LB\n");
+    } else if (refine_max_avg_ratio <= 1.01) {
+      lb_type = 1;
+      refineLB->work(stats);
+      CkPrintf("---REFINE LB\n");
+    } else if (greedy_max_avg_ratio <= 1.01) {
+      lb_type = 0;
+      greedyLB->work(stats);
+      CkPrintf("---GREEDY LB\n");
+    } else {
+      lb_type = 1;
+      refineLB->work(stats);
+      CkPrintf("---REFINE LB\n");
+    }
+  }
+//  UpdateLBDBWithData(lb_type, stats->after_lb_max, stats->after_lb_avg,
+//      stats->local_comm, stats->remote_comm);
+
+  delete parr;
+  delete ogr;
+
+}
+
+#include "AdaptiveLB.def.h"
+
+
+/*@}*/
diff --git a/src/ck-ldb/AdaptiveLB.ci b/src/ck-ldb/AdaptiveLB.ci
new file mode 100644 (file)
index 0000000..29a3b4e
--- /dev/null
@@ -0,0 +1,9 @@
+module AdaptiveLB {
+
+extern module CentralLB;
+initnode void lbinit(void);
+group [migratable] AdaptiveLB : CentralLB {
+  entry void AdaptiveLB(const CkLBOptions &);  
+};
+
+};
diff --git a/src/ck-ldb/AdaptiveLB.h b/src/ck-ldb/AdaptiveLB.h
new file mode 100644 (file)
index 0000000..35bdd11
--- /dev/null
@@ -0,0 +1,40 @@
+/**
+ * \addtogroup CkLdb
+*/
+/*@{*/
+
+#ifndef CENTRAL_ADAPTIVE_LB_H
+#define CENTRAL_ADAPTIVE_LB_H
+
+#include "CentralLB.h"
+#include "AdaptiveLB.decl.h"
+
+void CreateAdaptiveLB();
+
+/// for backward compatibility
+typedef LBMigrateMsg  CLBMigrateMsg;
+
+class AdaptiveLB : public CentralLB
+{
+public:
+  AdaptiveLB(const CkLBOptions &);
+  AdaptiveLB(CkMigrateMessage *m):CentralLB(m) {}
+
+protected:
+  virtual CmiBool QueryBalanceNow(int) { return CmiTrue; };  
+  virtual void work(LDStats* stats);
+//  void computeNonlocalComm(long long &nmsgs, long long &nbytes);
+
+private:  
+//  CProxy_CentralLB thisProxy;
+  CentralLB *greedyLB;
+  CentralLB *refineLB;
+  CentralLB *metisLB;
+  CentralLB *commRefineLB;
+};
+
+#endif /* CENTRAL_ADAPTIVE_LB_H */
+
+/*@}*/
+
+
index 3171d4ebf31b233f12922ffec0baf581c9e7a1d7..dc73c6e60c3e43b019047b581d3d003281c36172 100644 (file)
@@ -100,7 +100,11 @@ public:
     int  hashSize;
 
     int complete_flag;         // if this ocg is complete, eg in HybridLB,
-                               // this LDStats may not be complete
+    // this LDStats may not be complete
+
+    int is_prev_lb_refine;
+    double after_lb_max;
+    double after_lb_avg;
 
     LDStats(int c=0, int complete_flag=1);
     /// the functions below should be used to obtain the number of processors
index 3c216822fa78a2329ddc8d5db4e52613497fee52..55c0a7f7cde8cbcc36f18765556252ede12b88c7 100644 (file)
@@ -1,3 +1,4 @@
+
 /**
  * \addtogroup CkLdb
 */
@@ -191,7 +192,6 @@ void CentralLB::ProcessAtSync()
     start_lb_time = CkWallTimer();
   }
 
-
 #if (defined(_FAULT_MLOG_) || defined(_FAULT_CAUSAL_))
        initMlogLBStep(thisgroup);
 #endif
@@ -288,6 +288,7 @@ void CentralLB::BuildStatsMsg()
 #endif
 }
 
+
 // called on every processor
 void CentralLB::SendStats()
 {
@@ -551,6 +552,7 @@ void CentralLB::LoadBalance()
   for (proc = 0; proc < clients; proc++) statsMsgsList[proc] = NULL;
 #endif
 
+  theLbdb->ResetAdaptive();
   if (!_lb_args.samePeSpeed()) statsData->normalize_speed();
 
   if (_lb_args.debug()) 
@@ -995,6 +997,7 @@ void CentralLB::ResumeClients(int balancing)
 
   theLbdb->ResumeClients();
   if (balancing)  {
+
     CheckMigrationComplete();
     if (future_migrates_expected == 0 || 
             future_migrates_expected == future_migrates_completed) {
@@ -1017,15 +1020,20 @@ void CentralLB::CheckMigrationComplete()
 #if CMK_LBDB_ON
   lbdone ++;
   if (lbdone == 2) {
+    double end_lb_time = CkWallTimer();
     if (_lb_args.debug() && CkMyPe()==0) {
-      double end_lb_time = CkWallTimer();
       CkPrintf("CharmLB> %s: PE [%d] step %d finished at %f duration %f s\n\n",
                 lbname, cur_ld_balancer, step()-1, end_lb_time,
                end_lb_time-start_lb_time);
     }
+
+    theLbdb->SetMigrationCost(end_lb_time - start_lb_time);
+
     lbdone = 0;
     future_migrates_expected = -1;
     future_migrates_completed = 0;
+
+
     DEBUGF(("[%d] Migration Complete\n", CkMyPe()));
     // release local barrier  so that the next load balancer can go
     LDOMHandle h;
@@ -1057,6 +1065,7 @@ LBMigrateMsg* CentralLB::Strategy(LDStats* stats)
 
   work(stats);
 
+
   if (_lb_args.debug()>2)  {
     CkPrintf("CharmLB> Obj Map:\n");
     for (int i=0; i<stats->n_objs; i++) CkPrintf("%d ", stats->to_proc[i]);
@@ -1065,6 +1074,15 @@ LBMigrateMsg* CentralLB::Strategy(LDStats* stats)
 
   LBMigrateMsg *msg = createMigrateMsg(stats);
 
+  if (_lb_args.metaLbOn()) {
+    int clients = CkNumPes();
+    LBInfo info(clients);
+    getPredictedLoadWithMsg(stats, clients, msg, info, 0);
+    LBRealType mLoad, mCpuLoad, totalLoad, totalLoadWComm;
+    info.getSummary(mLoad, mCpuLoad, totalLoad);
+    theLbdb->UpdateDataAfterLB(mLoad, mCpuLoad, totalLoad/clients);
+  }
+
   if (_lb_args.debug()) {
     double strat_end_time = CkWallTimer();
     envelope *env = UsrToEnv(msg);
@@ -1075,8 +1093,8 @@ LBMigrateMsg* CentralLB::Strategy(LDStats* stats)
     CkPrintf("CharmLB> %s: PE [%d] #Objects migrating: %d, LBMigrateMsg size: %.2f MB\n", lbname, cur_ld_balancer, msg->n_moves, env->getTotalsize()/1024.0/1024.0);
     CkPrintf("CharmLB> %s: PE [%d] strategy finished at %f duration %f s\n",
              lbname, cur_ld_balancer, strat_end_time, strat_end_time-strat_start_time);
+    theLbdb->SetStrategyCost(strat_end_time - strat_start_time);
   }
-
   return msg;
 #else
   return NULL;
index 21996ed0930d5b4f49820e73e40da8ea80595849..7c23332e3f1044f0647c20d2b4437ca5fd151034 100644 (file)
@@ -84,7 +84,6 @@ public:
   void AtSync(void); // Everything is at the PE barrier
   void ProcessAtSync(void); // Receive a message from AtSync to avoid
                             // making projections output look funny
-
   void SendStats();
   void ReceiveCounts(CkReductionMsg *);
   void ReceiveStats(CkMarshalledCLBStatsMessage &msg); // Receive stats on PE 0
@@ -93,8 +92,8 @@ public:
   void depositData(CLBStatsMsg *m);
   void LoadBalance(void); 
   void ResumeClients(int);                      // Resuming clients needs
-                                               // to be resumed via message
-  void ResumeClients(CkReductionMsg *);
+
+  void ResumeClients(CkReductionMsg *); // to be resumed via message
   void ReceiveMigration(LBMigrateMsg *);       // Receive migration data
   void ProcessReceiveMigration(CkReductionMsg  *);
 #if (defined(_FAULT_MLOG_) || defined(_FAULT_CAUSAL_))
@@ -249,6 +248,7 @@ private:
   LBMigrateMsg   *storedMigrateMsg;
   int  reduction_started;
 
+
   FutureModel *predicted_model;
 
   void BuildStatsMsg();
index 11eda6e8bb34d3175c7855c8620054837f0bf66f..476744d468b81f9131009dcccd9ff07427df27ef 100644 (file)
@@ -33,6 +33,7 @@ module EveryLB {
   extern module RefineTopoLB;
   extern module TopoCentLB;
   extern module TopoLB;
+  extern module AdaptiveLB;
 
   initnode void initEveryLB(void);
 };
index 06a128541bc2780c313d4d700384e518f72ec667..808e59ca1c09f5165fe5ee4b5af1722d90ccbc43 100644 (file)
@@ -57,6 +57,8 @@ void GreedyLB::work(LDStats* stats)
   int n_pes = stats->nprocs();
   int *map = new int[n_pes];
 
+  ProcArray *parr = new ProcArray(stats);
+
   std::vector<ProcInfo>  procs;
   for(pe = 0; pe < n_pes; pe++) {
     map[pe] = -1;
@@ -152,6 +154,22 @@ void GreedyLB::work(LDStats* stats)
     CkPrintf("\n");
   }
 
+  if (_lb_args.metaLbOn()) {
+    double max_load = 0;
+    double avg_load = 0;
+    for (pe = 0; pe<procs.size(); pe++) {
+      if (procs[pe].totalLoad() > max_load) {
+        max_load = procs[pe].totalLoad();
+      }
+      avg_load += procs[pe].totalLoad();
+    }
+
+    stats->after_lb_max = max_load;
+    stats->after_lb_avg = avg_load/procs.size();
+    stats->is_prev_lb_refine = 0;
+    if (_lb_args.debug() > 0)
+      CkPrintf("GreedyLB> After lb max load: %lf avg load: %lf\n", max_load, avg_load/procs.size());
+  }
 }
 
 #include "GreedyLB.def.h"
index 853acf1d596871d7de207fecdee94eb052fa09a3..8f6fde551ef563768f1b9eb1371b2e8cf346d0c5 100644 (file)
@@ -1145,8 +1145,8 @@ void HybridBaseLB::ResumeClients(int balancing)
 #if CMK_LBDB_ON
   DEBUGF(("[%d] ResumeClients. \n", CkMyPe()));
 
+  double end_lb_time = CkWallTimer();
   if (CkMyPe() == 0 && balancing) {
-    double end_lb_time = CkWallTimer();
     if (_lb_args.debug())
       CkPrintf("[%s] Load balancing step %d finished at %f duration %f\n",
                lbName(), step()-1,end_lb_time,end_lb_time - start_lb_time);
@@ -1156,6 +1156,7 @@ void HybridBaseLB::ResumeClients(int balancing)
   theLbdb->ClearLoads();
 
   theLbdb->ResumeClients();
+       theLbdb->SetMigrationCost(end_lb_time - start_lb_time);
 #endif
 }
 
index 342633e383c1afe6a0284656bc7b8a024f3932f4..d827beeffe0282e3696c2342d7c0797998057da6 100644 (file)
@@ -50,6 +50,7 @@ HybridLB::~HybridLB()
 void HybridLB::work(LDStats* stats)
 {
 #if CMK_LBDB_ON
+       theLbdb->ResetAdaptive();
   LevelData *lData = levelData[currentLevel];
 
   // TODO: let's generate LBMigrateMsg ourself
index f13d0200768bd84ae8d6a1c9fd420895ac8b8db7..9c65d729bbe59db325b8ea8971a63f4eafe195ef 100644 (file)
@@ -324,6 +324,28 @@ int LBDB::Migrate(LDObjHandle h, int dest)
   return 1;
 }
 
+void LBDB::MetaLBResumeWaitingChares(int lb_ideal_period) {
+  for (int i = 0; i < objs.length(); i++) {
+    LBObj* obj = objs[i];
+    if (obj) {
+      LBOM *om = oms[obj->parentOM().handle];
+      LDObjHandle h = obj->GetLDObjHandle();
+      om->MetaLBResumeWaitingChares(h, lb_ideal_period);
+    }
+  }
+}
+
+void LBDB::MetaLBCallLBOnChares() {
+  for (int i = 0; i < objs.length(); i++) {
+    LBObj* obj = objs[i];
+    if (obj) {
+      LBOM *om = oms[obj->parentOM().handle];
+      LDObjHandle h = obj->GetLDObjHandle();
+      om->MetaLBCallLBOnChares(h);
+    }
+  }
+}
+
 void LBDB::Migrated(LDObjHandle h, int waitBarrier)
 {
   // Object migrated, inform load balancers
@@ -338,6 +360,7 @@ void LBDB::Migrated(LDObjHandle h, int waitBarrier)
   
 }
 
+
 int LBDB::NotifyMigrated(LDMigratedFn fn, void* data)
 {
   // Save migration function
index 5c6236f10c7a048cd9ef067971f54c861e9ad1c9..eedeba4587e276cd27e72f556f6f9900640df20a 100644 (file)
@@ -136,6 +136,8 @@ public:
   inline void GetCommData(LDCommData *data) 
        { if (commTable) commTable->GetCommData(data); };
 
+  void MetaLBResumeWaitingChares(int lb_ideal_period);
+  void MetaLBCallLBOnChares();
   int  Migrate(LDObjHandle h, int dest);
   void Migrated(LDObjHandle h, int waitBarrier=1);
   int  NotifyMigrated(LDMigratedFn fn, void* data);
index ca2cc0667a991a39a1acf487b9b3743d33f9a59d..4ea9fdf65797a3219365b13aabc8b6b336bcd333 100644 (file)
@@ -41,7 +41,7 @@ private:
     int        shown;          // if 0, donot show in help page
     LBDBEntry(): name(0), cfn(0), afn(0), help(0), shown(1) {}
     LBDBEntry(int) {}
-    LBDBEntry(const char *n, LBCreateFn cf, LBAllocFn af, 
+    LBDBEntry(const char *n, LBCreateFn cf, LBAllocFn af,
               const char *h, int show=1):
       name(n), cfn(cf), afn(af), help(h), shown(show) {};
   };
@@ -63,10 +63,10 @@ public:
     lbtables.push_back(LBDBEntry(name, fn, afn, help, shown));
   }
   void addCompiletimeBalancer(const char *name) {
-    compile_lbs.push_back(name); 
+    compile_lbs.push_back(name);
   }
   void addRuntimeBalancer(const char *name) {
-    runtime_lbs.push_back(name); 
+    runtime_lbs.push_back(name);
   }
   LBCreateFn search(const char *name) {
     char *ptr = strpbrk((char *)name, ":,");
@@ -110,7 +110,7 @@ static void createLoadBalancer(const char *lbname)
       lbRegistry.displayLBs();    // display help page
       CkAbort("Abort");
     }
-    // invoke function to create load balancer 
+    // invoke function to create load balancer
     fn();
 }
 
@@ -136,7 +136,7 @@ LBDBInit::LBDBInit(CkArgMsg *m)
   else {
     // NullLB is the default when none of above lb created
     // note user may create his own load balancer in his code manually like
-    // in NAMD, but never mind NullLB can disable itself if there is 
+    // in NAMD, but never mind NullLB can disable itself if there is
     // a non NULL LB.
     createLoadBalancer("NullLB");
   }
@@ -164,7 +164,7 @@ void _loadbalancerInit()
   char *balancer = NULL;
   CmiArgGroup("Charm++","Load Balancer");
   while (CmiGetArgStringDesc(argv, "+balancer", &balancer, "Use this load balancer")) {
-    if (CkMyRank() == 0)                
+    if (CkMyRank() == 0)
       lbRegistry.addRuntimeBalancer(balancer);   /* lbRegistry is a static */
   }
 
@@ -223,22 +223,22 @@ void _loadbalancerInit()
   LBSimulation::simProcs = 0;
   CmiGetArgIntDesc(argv, "+LBSimProcs", &LBSimulation::simProcs, "Number of target processors.");
 
-  LBSimulation::showDecisionsOnly = 
+  LBSimulation::showDecisionsOnly =
     CmiGetArgFlagDesc(argv, "+LBShowDecisions",
                      "Write to File: Load Balancing Object to Processor Map decisions during LB Simulation");
 
   // force a global barrier after migration done
-  _lb_args.syncResume() = CmiGetArgFlagDesc(argv, "+LBSyncResume", 
+  _lb_args.syncResume() = CmiGetArgFlagDesc(argv, "+LBSyncResume",
                   "LB performs a barrier after migration is finished");
 
   // both +LBDebug and +LBDebug level should work
-  if (!CmiGetArgIntDesc(argv, "+LBDebug", &_lb_args.debug(), 
+  if (!CmiGetArgIntDesc(argv, "+LBDebug", &_lb_args.debug(),
                                           "Turn on LB debugging printouts"))
-    _lb_args.debug() = CmiGetArgFlagDesc(argv, "+LBDebug", 
+    _lb_args.debug() = CmiGetArgFlagDesc(argv, "+LBDebug",
                                             "Turn on LB debugging printouts");
 
   // getting the size of the team with +teamSize
-  if (!CmiGetArgIntDesc(argv, "+teamSize", &_lb_args.teamSize(), 
+  if (!CmiGetArgIntDesc(argv, "+teamSize", &_lb_args.teamSize(),
                                           "Team size"))
     _lb_args.teamSize() = 1;
 
@@ -247,23 +247,23 @@ void _loadbalancerInit()
                "Print load balancing result summary");
 
   // to ignore baclground load
-  _lb_args.ignoreBgLoad() = CmiGetArgFlagDesc(argv, "+LBNoBackground", 
+  _lb_args.ignoreBgLoad() = CmiGetArgFlagDesc(argv, "+LBNoBackground",
                       "Load balancer ignores the background load.");
 #ifdef __BIGSIM__
   _lb_args.ignoreBgLoad() = 1;
 #endif
-  _lb_args.migObjOnly() = CmiGetArgFlagDesc(argv, "+LBObjOnly", 
+  _lb_args.migObjOnly() = CmiGetArgFlagDesc(argv, "+LBObjOnly",
                       "Only load balancing migratable objects, ignoring all others.");
   if (_lb_args.migObjOnly()) _lb_args.ignoreBgLoad() = 1;
 
   // assume all CPUs are identical
-  _lb_args.testPeSpeed() = CmiGetArgFlagDesc(argv, "+LBTestPESpeed", 
+  _lb_args.testPeSpeed() = CmiGetArgFlagDesc(argv, "+LBTestPESpeed",
                       "Load balancer test all CPUs speed.");
-  _lb_args.samePeSpeed() = CmiGetArgFlagDesc(argv, "+LBSameCpus", 
+  _lb_args.samePeSpeed() = CmiGetArgFlagDesc(argv, "+LBSameCpus",
                       "Load balancer assumes all CPUs are of same speed.");
   if (!_lb_args.testPeSpeed()) _lb_args.samePeSpeed() = 1;
 
-  _lb_args.useCpuTime() = CmiGetArgFlagDesc(argv, "+LBUseCpuTime", 
+  _lb_args.useCpuTime() = CmiGetArgFlagDesc(argv, "+LBUseCpuTime",
                       "Load balancer uses CPU time instead of wallclock time.");
 
   // turn instrumentation off at startup
@@ -274,6 +274,10 @@ void _loadbalancerInit()
   _lb_args.traceComm() = !CmiGetArgFlagDesc(argv, "+LBCommOff",
                "Turn load balancer instrumentation of communication off");
 
+       // turn on MetaBalancer if set
+       _lb_args.metaLbOn() = CmiGetArgFlagDesc(argv, "+MetaLB",
+               "Turn on MetaBalancer");
+
   // set alpha and beeta
   _lb_args.alpha() = PER_MESSAGE_SEND_OVERHEAD_DEFAULT;
   _lb_args.beeta() = PER_BYTE_SEND_OVERHEAD_DEFAULT;
@@ -328,12 +332,15 @@ void LBDatabase::initnodeFn()
 }
 
 // called my constructor
-void LBDatabase::init(void) 
+void LBDatabase::init(void)
 {
   myLDHandle = LDCreate();
   mystep = 0;
   nloadbalancers = 0;
   new_ld_balancer = 0;
+       if (_lb_args.metaLbOn()) {
+               metabalancer = (MetaBalancer *)CkLocalBranch(_metalb);
+       }
 
   CkpvAccess(lbdatabaseInited) = 1;
 #if CMK_LBDB_ON
@@ -379,12 +386,12 @@ void LBDatabase::set_avail_vector(char * bitmap, int new_ld){
 // called in CreateFooLB() when multiple load balancers are created
 // on PE0, BaseLB of each load balancer applies a ticket number
 // and broadcast the ticket number to all processors
-int LBDatabase::getLoadbalancerTicket()  { 
+int LBDatabase::getLoadbalancerTicket()  {
   int seq = nloadbalancers;
   nloadbalancers ++;
-  loadbalancers.resize(nloadbalancers); 
+  loadbalancers.resize(nloadbalancers);
   loadbalancers[seq] = NULL;
-  return seq; 
+  return seq;
 }
 
 void LBDatabase::addLoadbalancer(BaseLB *lb, int seq) {
@@ -435,8 +442,8 @@ const char *LBDatabase::loadbalancer(int seq) {
 }
 
 void LBDatabase::pup(PUP::er& p)
-{ 
-       IrrGroup::pup(p); 
+{
+       IrrGroup::pup(p);
        // the memory should be already allocated
        int np;
        if (!p.isUnpacking()) np = CkNumPes();
@@ -452,7 +459,13 @@ void LBDatabase::pup(PUP::er& p)
        }
        p(avail_vector, np);
        p|mystep;
-       if(p.isUnpacking()) nloadbalancers = 0;
+       if(p.isUnpacking()) {
+    nloadbalancers = 0;
+               if (_lb_args.metaLbOn()) {
+      // if unpacking set metabalancer using the id
+      metabalancer = (MetaBalancer*)CkLocalBranch(_metalb);
+               }
+  }
 }
 
 
@@ -467,6 +480,71 @@ void LBDatabase::EstObjLoad(const LDObjHandle &_h, double cputime)
 #endif
 }
 
+void LBDatabase::ResetAdaptive() {
+#if CMK_LBDB_ON
+       if (_lb_args.metaLbOn()) {
+               if (metabalancer == NULL) {
+                       metabalancer = CProxy_MetaBalancer(_metalb).ckLocalBranch();
+               }
+               if (metabalancer != NULL) {
+                       metabalancer->ResetAdaptive();
+               }
+       }
+#endif
+}
+
+void LBDatabase::ResumeClients() {
+#if CMK_LBDB_ON
+       if (_lb_args.metaLbOn()) {
+               if (metabalancer == NULL) {
+                       metabalancer = CProxy_MetaBalancer(_metalb).ckLocalBranch();
+               }
+               if (metabalancer != NULL) {
+                       metabalancer->ResumeClients();
+               }
+       }
+#endif
+  LDResumeClients(myLDHandle);
+}
+
+void LBDatabase::SetMigrationCost(double cost) {
+#if CMK_LBDB_ON
+       if (_lb_args.metaLbOn()) {
+               if (metabalancer == NULL) {
+                       metabalancer = (MetaBalancer *)CkLocalBranch(_metalb);
+               }
+               if (metabalancer != NULL)  {
+                       metabalancer->SetMigrationCost(cost);
+               }
+       }
+#endif
+}
+
+void LBDatabase::SetStrategyCost(double cost) {
+#if CMK_LBDB_ON
+       if (_lb_args.metaLbOn()) {
+               if (metabalancer == NULL) {
+                       metabalancer = (MetaBalancer *)CkLocalBranch(_metalb);
+               }
+               if (metabalancer != NULL)  {
+                       metabalancer->SetStrategyCost(cost);
+               }
+       }
+#endif
+}
+
+void LBDatabase::UpdateDataAfterLB(double mLoad, double mCpuLoad, double avgLoad) {
+#if CMK_LBDB_ON
+       if (_lb_args.metaLbOn()) {
+               if (metabalancer == NULL) {
+                       metabalancer = (MetaBalancer *)CkLocalBranch(_metalb);
+               }
+               if (metabalancer != NULL)  {
+                       metabalancer->UpdateAfterLBData(mLoad, mCpuLoad, avgLoad);
+               }
+       }
+#endif
+}
 /*
   callable from user's code
 */
@@ -496,19 +574,19 @@ void TurnManualLBOff()
 #endif
 }
 
-extern "C" void LBTurnInstrumentOn() { 
+extern "C" void LBTurnInstrumentOn() {
 #if CMK_LBDB_ON
   if (CkpvAccess(lbdatabaseInited))
-    LBDatabase::Object()->CollectStatsOn(); 
+    LBDatabase::Object()->CollectStatsOn();
   else
     _lb_args.statsOn() = 1;
 #endif
 }
 
-extern "C" void LBTurnInstrumentOff() { 
+extern "C" void LBTurnInstrumentOff() {
 #if CMK_LBDB_ON
   if (CkpvAccess(lbdatabaseInited))
-    LBDatabase::Object()->CollectStatsOff(); 
+    LBDatabase::Object()->CollectStatsOff();
   else
     _lb_args.statsOn() = 0;
 #endif
@@ -528,7 +606,7 @@ extern "C" void LBTurnCommOff() {
 
 void LBClearLoads() {
 #if CMK_LBDB_ON
-  LBDatabase::Object()->ClearLoads(); 
+  LBDatabase::Object()->ClearLoads();
 #endif
 }
 
@@ -559,7 +637,7 @@ void LBChangePredictor(LBPredictorFunction *model) {
 void LBSetPeriod(double second) {
 #if CMK_LBDB_ON
   if (CkpvAccess(lbdatabaseInited))
-    LBDatabase::Object()->SetLBPeriod(second); 
+    LBDatabase::Object()->SetLBPeriod(second);
   else
     _lb_args.lbperiod() = second;
 #endif
index 32afce34576d8cb63c4f987a0ed83cb61cb4ebbd..030c3512efbc8dbabcf241ca024a2a41841527bd 100644 (file)
@@ -12,6 +12,7 @@
 
 #define LB_FORMAT_VERSION     2
 
+class MetaBalancer;
 extern int _lb_version;
 
 // command line options
@@ -35,6 +36,7 @@ private:
   int _lb_central_pe;           // processor number for centralized startegy
   int _lb_percentMovesAllowed; //Specifies restriction on num of chares to be moved(as a percentage of total number of chares). Used by RefineKLB
   int _lb_teamSize;            // specifies the team size for TeamLB
+  int _lb_metaLbOn;
 public:
   CkLBArgs() {
 #if CMK_BIGSIM_CHARM
@@ -49,6 +51,7 @@ public:
     _lb_loop = 0;
     _lb_central_pe = 0;
     _lb_teamSize = 1;
+    _lb_metaLbOn = 0;
   }
   inline double & lbperiod() { return _autoLbPeriod; }
   inline int & debug() { return _lb_debug; }
@@ -68,6 +71,7 @@ public:
   inline double & alpha() { return _lb_alpha; }
   inline double & beeta() { return _lb_beeta; }
   inline int & percentMovesAllowed() { return _lb_percentMovesAllowed;}
+  inline int & metaLbOn() {return _lb_metaLbOn;}
 };
 
 extern CkLBArgs _lb_args;
@@ -194,6 +198,8 @@ public:
     LDDoneRegisteringObjects(_om);
   };
 
+  void ResetAdaptive();
+
   inline LDObjHandle RegisterObj(LDOMHandle h, LDObjid id,
                          void *userptr,int migratable) {
     return LDRegisterObj(h,id,userptr,migratable);
@@ -321,7 +327,9 @@ public:
   inline void ClearLoads(void) { LDClearLoads(myLDHandle); };
   inline int Migrate(LDObjHandle h, int dest) { return LDMigrate(h,dest); };
 
-  inline void Migrated(LDObjHandle h, int waitBarrier=1) { LDMigrated(h, waitBarrier); };
+  inline void Migrated(LDObjHandle h, int waitBarrier=1) {
+    LDMigrated(h, waitBarrier);
+  };
 
   inline LDBarrierClient AddLocalBarrierClient(LDResumeFn fn, void* data) {
     return LDAddLocalBarrierClient(myLDHandle,fn,data);
@@ -339,15 +347,28 @@ public:
     LDRemoveLocalBarrierReceiver(myLDHandle,h);
   };
 
-  inline void AtLocalBarrier(LDBarrierClient h) { LDAtLocalBarrier(myLDHandle,h); }
+  inline void AtLocalBarrier(LDBarrierClient h) {
+    LDAtLocalBarrier(myLDHandle,h);
+  }
   inline void LocalBarrierOn(void) { LDLocalBarrierOn(myLDHandle); };
   inline void LocalBarrierOff(void) { LDLocalBarrierOn(myLDHandle); };
-  inline void ResumeClients() { LDResumeClients(myLDHandle); }
-
+  void ResumeClients();
   inline int ProcessorSpeed() { return LDProcessorSpeed(); };
   inline void SetLBPeriod(double s) { LDSetLBPeriod(myLDHandle, s);}
   inline double GetLBPeriod() { return LDGetLBPeriod(myLDHandle);}
 
+  inline void MetaLBResumeWaitingChares(int lb_period) {
+    LDOMMetaLBResumeWaitingChares(myLDHandle, lb_period);
+  }
+
+  inline void MetaLBCallLBOnChares() {
+    LDOMMetaLBCallLBOnChares(myLDHandle);
+  }
+
+  void SetMigrationCost(double cost);
+  void SetStrategyCost(double cost);
+       void UpdateDataAfterLB(double mLoad, double mCpuLoad, double avgLoad);
+
 private:
   int mystep;
   LDHandle myLDHandle;
@@ -355,6 +376,7 @@ private:
   int new_ld_balancer;         // for Node 0
   CkVec<BaseLB *>   loadbalancers;
   int nloadbalancers;
+  MetaBalancer* metabalancer;
 
 public:
   BaseLB** getLoadBalancers() {return loadbalancers.getVec();}
index 478b3aae283b47aeb7d91d23796afd10b83ac906..e1d4e49029de96f27c5985e00ccbbd93de6fe3ba 100644 (file)
@@ -35,6 +35,12 @@ private:
 
   void DepositHandle(LDOMHandle _h) { myhandle = _h; };
   void Migrate(LDObjHandle _h, int dest) { callbacks.migrate(_h,dest); };
+  void MetaLBResumeWaitingChares(LDObjHandle _h, int lb_ideal_period) {
+    callbacks.metaLBResumeWaitingChares(_h, lb_ideal_period);
+  }
+  void MetaLBCallLBOnChares(LDObjHandle _h) {
+    callbacks.metaLBCallLBOnChares(_h);
+  }
   CmiBool RegisteringObjs() { return registering_objs; };
   void SetRegisteringObjs(CmiBool _set) { registering_objs = _set; };
 
index e0500f115147b059fd27d0b07620ee66e84e589d..f92c86a110775409c07746a74af8aab82def4a0e 100644 (file)
@@ -189,30 +189,45 @@ void LBInfo::getInfo(BaseLB::LDStats* stats, int count, int considerComm)
 
 void LBInfo::print()
 {
-  int i;
-  double minLoad, maxLoad, maxProcObjLoad, maxComLoad, sum, average;
+  int i;  
+  double minLoad, maxLoad, maxProcObjLoad, avgProcObjLoad, maxComLoad, sum, average, avgComLoad;
+  double avgBgLoad;
+  int max_loaded_proc = 0;
   sum = .0;
   sum = minLoad = maxLoad = peLoads[0];
-  maxProcObjLoad = objLoads[0];
-  maxComLoad = comLoads[0];
+  avgProcObjLoad = maxProcObjLoad = objLoads[0];
+  avgComLoad = maxComLoad = comLoads[0];
+  avgBgLoad = bgLoads[0];
   for (i = 1; i < numPes; i++) {
     double load = peLoads[i];
-    if (load>maxLoad) maxLoad=load;
-    else if (peLoads[i]<minLoad) minLoad=load;
+    if (load>maxLoad) {
+      maxLoad=load;
+      max_loaded_proc = i;
+    } else if (peLoads[i]<minLoad) minLoad=load;
     if (objLoads[i]>maxProcObjLoad) maxProcObjLoad = objLoads[i];
     if (comLoads[i]>maxComLoad) maxComLoad = comLoads[i];
     sum += load;
+    avgProcObjLoad += objLoads[i];
+    avgBgLoad += bgLoads[i];
+    avgComLoad += comLoads[i];
   }
   average = sum/numPes;
+  avgProcObjLoad /= numPes; 
+  avgBgLoad /= numPes; 
+  avgComLoad /= numPes;
   CmiPrintf("The processor loads are: \n");
   CmiPrintf("PE   (Total Load) (Obj Load) (Comm Load) (BG Load)\n");
   if (_lb_args.debug() > 3)
     for(i = 0; i < numPes; i++)
       CmiPrintf("%-4d %10f %10f %10f %10f\n", i, peLoads[i], objLoads[i], comLoads[i], bgLoads[i]);
   CmiPrintf("max: %10f %10f %10f\n", maxLoad, maxProcObjLoad, maxComLoad);
-  CmiPrintf("Min : %f  Max : %f        Average: %f\n", minLoad, maxLoad, average);
-    // the min and max object (calculated in getLoadInfo)
-  CmiPrintf("MinObj : %f       MaxObj : %f\n", minObjLoad, maxObjLoad, average);
+  CmiPrintf("Min : %f Max : %f  Average: %f AvgBgLoad: %f\n", minLoad, maxLoad, average, avgBgLoad);
+  CmiPrintf("ProcObjLoad  Max : %f  Average: %f\n", maxProcObjLoad, avgProcObjLoad);
+  CmiPrintf("CommLoad  Max : %f  Average: %f\n", maxComLoad, avgComLoad);
+  CmiPrintf("[%d] is Maxloaded maxload: %f ObjLoad %f BgLoad %f\n",
+                       max_loaded_proc, peLoads[max_loaded_proc], objLoads[max_loaded_proc], bgLoads[max_loaded_proc]);
+  // the min and max object (calculated in getLoadInfo)
+  CmiPrintf("MinObj : %f  MaxObj : %f\n", minObjLoad, maxObjLoad, average);
   CmiPrintf("Non-local comm: %d msgs %lld bytes\n", msgCount, msgBytes);
 }
 
index 74131d577282d9332990994f2ea628e5cd9560a2..8c2439c2388b71a4e10bbbaab9647fdb5eee596c 100644 (file)
@@ -32,6 +32,7 @@ ALL_LDBS=\
    $(L)/libmoduleRefineTopoLB.a \
    $(L)/libmoduleTopoCentLB.a \
    $(L)/libmoduleTopoLB.a \
+   $(L)/libmoduleAdaptiveLB.a \
    manager.o
 
 
@@ -227,6 +228,12 @@ $(L)/libmoduleTopoLB.a: TopoLB.o
 LBHEADERS += TopoLB.h TopoLB.decl.h
 
 
+$(L)/libmoduleAdaptiveLB.a: AdaptiveLB.o
+       $(CHARMC) -o $(L)/libmoduleAdaptiveLB.a AdaptiveLB.o
+
+LBHEADERS += AdaptiveLB.h AdaptiveLB.decl.h
+
+
 $(L)/libmoduleTempAwareGreedyLB.a: TempAwareGreedyLB.o 
        $(CHARMC) -o $(L)/libmoduleTempAwareGreedyLB.a TempAwareGreedyLB.o 
        
@@ -291,6 +298,7 @@ ALL_LB_OBJS=EveryLB.o \
     RefineTopoLB.o \
     TopoCentLB.o \
     TopoLB.o \
+    AdaptiveLB.o \
     TempAwareGreedyLB.o \
     MetisLB.o \
     ScotchLB.o \
@@ -335,6 +343,7 @@ EVERYLB_DEPS=EveryLB.o \
     RefineTopoLB.o \
     TopoCentLB.o \
     TopoLB.o \
+    AdaptiveLB.o \
     manager.o \
     tm_tree.o  \
     tm_timings.o  \
index 0fdfd88139f14508c6274e3e04c112b2158cfe16..ed7947357d672650241f7c4743fbda1ec139449a 100755 (executable)
@@ -1,6 +1,6 @@
 #!/bin/sh
 UNCOMMON_LDBS="TempAwareGreedyLB MetisLB ScotchLB TeamLB WSLB"
-COMMON_LDBS="BlockLB CommLB DummyLB GreedyAgentLB GreedyCommLB GreedyLB NeighborCommLB NeighborLB OrbLB PhasebyArrayLB RandCentLB RecBipartLB RefineLB RefineCommLB RotateLB TreeMatchLB RefineSwapLB CommAwareRefineLB"
+COMMON_LDBS="BlockLB CommLB DummyLB GreedyAgentLB GreedyCommLB GreedyLB NeighborCommLB NeighborLB OrbLB PhasebyArrayLB RandCentLB RecBipartLB RefineLB RefineCommLB RotateLB TreeMatchLB RefineSwapLB CommAwareRefineLB AdaptiveLB"
 OTHER_LDBS="ComboCentLB GraphPartLB GraphBFTLB GridCommLB GridCommRefineLB GridHybridLB GridHybridSeedLB GridMetisLB HbmLB HybridLB RefineKLB RefineTopoLB TopoCentLB TopoLB"
 ALL_LDBS="$COMMON_LDBS $OTHER_LDBS"
 
diff --git a/src/ck-ldb/MetaBalancer.C b/src/ck-ldb/MetaBalancer.C
new file mode 100644 (file)
index 0000000..0ac2f5c
--- /dev/null
@@ -0,0 +1,858 @@
+/**
+ * 
+*/
+/*@{*/
+
+#include "converse.h"
+
+/*
+ */
+
+#include "MetaBalancer.h"
+#include "topology.h"
+
+#include "limits.h"
+
+#define VEC_SIZE 50
+#define IMB_TOLERANCE 1.1
+#define OUTOFWAY_TOLERANCE 2
+#define UTILIZATION_THRESHOLD 0.7
+#define NEGLECT_IDLE 2 // Should never be == 1
+#define MIN_STATS 6
+#define STATS_COUNT 8 // The number of stats collected during reduction
+
+#define DEBAD(x) /*CkPrintf x*/
+#define DEBADDETAIL(x) /*CkPrintf x*/
+#define EXTRA_FEATURE 0
+
+CkReductionMsg* lbDataCollection(int nMsg, CkReductionMsg** msgs) {
+  double lb_data[STATS_COUNT];
+  lb_data[1] = 0.0; // total number of processors contributing
+  lb_data[2] = 0.0; // total load
+  lb_data[3] = 0.0; // max load
+  lb_data[4] = 0.0; // idle time
+  lb_data[5] = 1.0; // utilization
+  lb_data[6] = 0.0; // total load with bg
+  lb_data[7] = 0.0; // max load with bg
+  for (int i = 0; i < nMsg; i++) {
+    CkAssert(msgs[i]->getSize() == STATS_COUNT*sizeof(double));
+    if (msgs[i]->getSize() != STATS_COUNT*sizeof(double)) {
+      CkPrintf("Error!!! Reduction not correct. Msg size is %d\n",
+          msgs[i]->getSize());
+      CkAbort("Incorrect Reduction size in MetaBalancer\n");
+    }
+    double* m = (double *)msgs[i]->getData();
+    // Total count
+    lb_data[1] += m[1];
+    // Avg load
+    lb_data[2] += m[2];
+    // Max load
+    lb_data[3] = ((m[3] > lb_data[3])? m[3] : lb_data[3]);
+    // Avg idle
+    lb_data[4] += m[4];
+    // Get least utilization
+    lb_data[5] = ((m[5] < lb_data[5]) ? m[5] : lb_data[5]);
+    // Get Avg load with bg
+    lb_data[6] += m[6];
+    // Get Max load with bg
+    lb_data[7] = ((m[7] > lb_data[7])? m[7] : lb_data[7]);
+    if (i == 0) {
+      // Iteration no
+      lb_data[0] = m[0];
+    }
+    if (m[0] != lb_data[0]) {
+      CkPrintf("Error!!! Reduction is intermingled between iteration %lf \
+        and %lf\n", lb_data[0], m[0]);
+      CkAbort("Intermingling iterations in MetaBalancer\n");
+    }
+  }
+  return CkReductionMsg::buildNew(STATS_COUNT*sizeof(double), lb_data);
+}
+
+/*global*/ CkReduction::reducerType lbDataCollectionType;
+/*initcall*/ void registerLBDataCollection(void) {
+  lbDataCollectionType = CkReduction::addReducer(lbDataCollection);
+}
+
+CkGroupID _metalb;
+CkGroupID _metalbred;
+
+CkpvDeclare(int, metalbInited);  /**< true if metabalancer is inited */
+
+// mainchare
+MetaLBInit::MetaLBInit(CkArgMsg *m) {
+#if CMK_LBDB_ON
+  _metalb = CProxy_MetaBalancer::ckNew();
+  _metalbred = CProxy_MetaBalancerRedn::ckNew();
+#endif
+  delete m;
+}
+
+// called from init.C
+void _metabalancerInit() {
+  CkpvInitialize(int, metalbInited);
+  CkpvAccess(metalbInited) = 0;
+}
+
+void MetaBalancer::initnodeFn() {
+}
+
+// called by my constructor
+void MetaBalancer::init(void) {
+  lbdatabase = (LBDatabase *)CkLocalBranch(_lbdb);
+  CkpvAccess(metalbInited) = 1;
+  total_load_vec.resize(VEC_SIZE, 0.0);
+  total_count_vec.resize(VEC_SIZE, 0);
+  prev_idle = 0.0;
+  alpha_beta_cost_to_load = 1.0; // Some random value. TODO: Find the actual
+
+  metaRdnGroup = (MetaBalancerRedn*)CkLocalBranch(_metalbred);
+
+  adaptive_lbdb.lb_iter_no = -1;
+
+  // If metabalancer enabled, initialize the variables
+  adaptive_struct.tentative_period =  INT_MAX;
+  adaptive_struct.final_lb_period =  INT_MAX;
+  adaptive_struct.lb_calculated_period = INT_MAX;
+  adaptive_struct.lb_iteration_no = -1;
+  adaptive_struct.finished_iteration_no = -1;
+  adaptive_struct.global_max_iter_no = 0;
+  adaptive_struct.tentative_max_iter_no = -1;
+  adaptive_struct.in_progress = false;
+  adaptive_struct.lb_strategy_cost = 0.0;
+  adaptive_struct.lb_migration_cost = 0.0;
+  adaptive_struct.lb_msg_send_no = 0;
+  adaptive_struct.lb_msg_recv_no = 0;
+  adaptive_struct.total_syncs_called = 0;
+  adaptive_struct.last_lb_type = -1;
+
+
+  // This is indicating if the load balancing strategy and migration started.
+  // This is mainly used to register callbacks for noobj pes. They would
+  // register as soon as resumefromsync is called. On receiving the handles at
+  // the central pe, it clears the previous handlers and sets lb_in_progress
+  // to false so that it doesn't clear the handles.
+  lb_in_progress = false;
+
+  is_prev_lb_refine = -1;
+  if (_lb_args.metaLbOn()) {
+    periodicCall((void *) this);
+  }
+}
+
+void MetaBalancer::pup(PUP::er& p) {
+       CBase_MetaBalancer::pup(p);
+  if (p.isUnpacking()) {
+    lbdatabase = (LBDatabase *)CkLocalBranch(_lbdb);
+    metaRdnGroup = (MetaBalancerRedn*)CkLocalBranch(_metalbred);
+  }
+  p|prev_idle;
+  p|alpha_beta_cost_to_load;
+  p|is_prev_lb_refine;
+  p|lb_in_progress;
+}
+
+
+void MetaBalancer::ResumeClients() {
+  // If metabalancer enabled, initialize the variables
+  adaptive_lbdb.history_data.clear();
+
+  adaptive_struct.tentative_period =  INT_MAX;
+  adaptive_struct.final_lb_period =  INT_MAX;
+  adaptive_struct.lb_calculated_period = INT_MAX;
+  adaptive_struct.lb_iteration_no = -1;
+  adaptive_struct.finished_iteration_no = -1;
+  adaptive_struct.global_max_iter_no = 0;
+  adaptive_struct.tentative_max_iter_no = -1;
+  adaptive_struct.in_progress = false;
+  adaptive_struct.lb_strategy_cost = 0.0;
+  adaptive_struct.lb_migration_cost = 0.0;
+  adaptive_struct.lb_msg_send_no = 0;
+  adaptive_struct.lb_msg_recv_no = 0;
+  adaptive_struct.total_syncs_called = 0;
+
+  prev_idle = 0.0;
+  if (lb_in_progress) {
+    lbdb_no_obj_callback.clear();
+    lb_in_progress = false;
+  }
+  HandleAdaptiveNoObj();
+}
+
+int MetaBalancer::get_iteration() {
+  return adaptive_struct.lb_iteration_no;
+}
+
+int MetaBalancer::get_finished_iteration() {
+  return adaptive_struct.finished_iteration_no;
+}
+
+bool MetaBalancer::AddLoad(int it_n, double load) {
+  int index = it_n % VEC_SIZE;
+  total_count_vec[index]++;
+  adaptive_struct.total_syncs_called++;
+  DEBADDETAIL(("At PE %d Total contribution for iteration %d is %d \
+      total objs %d\n", CkMyPe(), it_n, total_count_vec[index],
+      lbdatabase->getLBDB()->ObjDataCount()));
+
+  if (it_n <= adaptive_struct.finished_iteration_no) {
+    CkAbort("Error!! Received load for iteration that has contributed\n");
+  }
+  if (it_n > adaptive_struct.lb_iteration_no) {
+    adaptive_struct.lb_iteration_no = it_n;
+  }
+  total_load_vec[index] += load;
+  if (total_count_vec[index] > lbdatabase->getLBDB()->ObjDataCount()) {
+    CkPrintf("iteration %d received %d contributions and expected %d\n", it_n,
+        total_count_vec[index], lbdatabase->getLBDB()->ObjDataCount());
+    CkAbort("Abort!!! Received more contribution");
+  }
+
+  if (total_count_vec[index] == lbdatabase->getLBDB()->ObjDataCount()) {
+    double idle_time, bg_walltime, cpu_bgtime;
+    lbdatabase->IdleTime(&idle_time);
+    lbdatabase->BackgroundLoad(&bg_walltime, &cpu_bgtime);
+
+    int sync_for_bg = adaptive_struct.total_syncs_called +
+        lbdatabase->getLBDB()->ObjDataCount();
+    bg_walltime = bg_walltime * lbdatabase->getLBDB()->ObjDataCount() / sync_for_bg;
+
+    if (it_n < NEGLECT_IDLE) {
+      prev_idle = idle_time;
+    }
+    idle_time -= prev_idle;
+
+    // The chares do not contribute their 0th iteration load. So the total syncs
+    // in reality is total_syncs_called + obj_counts
+    int total_countable_syncs = adaptive_struct.total_syncs_called +
+        (1 - NEGLECT_IDLE) * lbdatabase->getLBDB()->ObjDataCount(); // TODO: Fix me!
+    if (total_countable_syncs != 0) {
+      idle_time = idle_time * lbdatabase->getLBDB()->ObjDataCount() / total_countable_syncs;
+    }
+
+    double lb_data[STATS_COUNT];
+    lb_data[0] = it_n;
+    lb_data[1] = 1;
+    lb_data[2] = total_load_vec[index]; // For average load
+    lb_data[3] = total_load_vec[index]; // For max load
+    lb_data[4] = idle_time;
+    // Set utilization
+    if (total_load_vec[index] == 0.0) {
+      lb_data[5] = 0.0;
+    } else {
+      lb_data[5] = total_load_vec[index]/(idle_time + total_load_vec[index]);
+    }
+    lb_data[6] = lb_data[2] + bg_walltime; // For Avg load with bg
+    lb_data[7] = lb_data[6]; // For Max load with bg
+    total_load_vec[index] = 0.0;
+    total_count_vec[index] = 0;
+
+    adaptive_struct.finished_iteration_no = it_n;
+    DEBADDETAIL(("[%d] sends total load %lf idle time %lf ratio of idle/load %lf at iter %d\n",
+        CkMyPe(), total_load_vec[index], idle_time,
+        idle_time/total_load_vec[index], adaptive_struct.finished_iteration_no));
+
+    CkCallback cb(CkIndex_MetaBalancer::ReceiveMinStats((CkReductionMsg*)NULL), thisProxy[0]);
+    contribute(STATS_COUNT*sizeof(double), lb_data, lbDataCollectionType, cb);
+  }
+  return true;
+}
+
+void MetaBalancer::ReceiveMinStats(CkReductionMsg *msg) {
+  double* load = (double *) msg->getData();
+  double avg = load[2]/load[1];
+  double max = load[3];
+  double avg_idle = load[4]/load[1];
+  double utilization = load[5];
+  int iteration_n = (int) load[0];
+  double avg_load_bg = load[6]/load[1];
+  double max_load_bg = load[7];
+  DEBAD(("** [%d] Iteration Avg load: %lf Max load: %lf Avg Idle : %lf \
+      Max Idle : %lf for %lf procs\n",iteration_n, avg, max, avg_idle,
+      utilization, load[1]));
+  delete msg;
+
+  // For processors with  no  objs, trigger MetaBalancer reduction
+  if (adaptive_struct.final_lb_period != iteration_n) {
+    for (int i = 0; i < lbdb_no_obj_callback.size(); i++) {
+      thisProxy[lbdb_no_obj_callback[i]].TriggerAdaptiveReduction();
+    }
+  }
+
+  // Store the data for this iteration
+  adaptive_lbdb.lb_iter_no = iteration_n;
+  AdaptiveData data;
+  data.iteration = adaptive_lbdb.lb_iter_no;
+  data.max_load = max;
+  data.avg_load = avg;
+  data.utilization = utilization;
+  data.idle_time = avg_idle;
+  adaptive_lbdb.history_data.push_back(data);
+
+  if (iteration_n == 1) {
+    adaptive_struct.info_first_iter.max_avg_ratio = max/avg;
+  }
+
+
+  if (adaptive_struct.final_lb_period == iteration_n) {
+    thisProxy.MetaLBCallLBOnChares();
+  }
+
+  // If lb period inform is in progress, dont inform again.
+  // If this is the lb data corresponding to the final lb period informed, then
+  // don't recalculate as some of the processors might have already gone into
+  // LB_STAGE.
+  if (adaptive_struct.in_progress || 
+      (adaptive_struct.final_lb_period == iteration_n)) {
+    return;
+  }
+
+  double utilization_threshold = UTILIZATION_THRESHOLD;
+
+#if EXTRA_FEATURE
+  DEBAD(("alpha_beta_to_load %lf\n", alpha_beta_cost_to_load));
+  if (alpha_beta_cost_to_load < 0.1) {
+    // Ignore the effect of idle time and there by lesser utilization. So we
+    // assign utilization threshold to be 0.0
+    DEBAD(("Changing the idle load tolerance coz this isn't \
+        communication intensive benchmark\n"));
+    utilization_threshold = 0.0;
+  }
+#endif
+
+  // First generate the lb period based on the cost of lb. Find out what is the
+  // expected imbalance at the calculated lb period.
+  int period;
+  // This is based on the new max load after load balancing. So technically, it
+  // is calculated based on the shifter up avg curve.
+  double ratio_at_t = 1.0;
+  int tmp_lb_type;
+  double tmp_max_avg_ratio, tmp_comm_ratio;
+  GetPrevLBData(tmp_lb_type, tmp_max_avg_ratio, tmp_comm_ratio);
+
+  double tolerate_imb = IMB_TOLERANCE * tmp_max_avg_ratio;
+
+  if (generatePlan(period, ratio_at_t)) {
+    DEBAD(("Generated period and calculated %d and period %d max iter %d\n",
+      adaptive_struct.lb_calculated_period, period,
+      adaptive_struct.tentative_max_iter_no));
+    // set the imbalance tolerance to be ratio_at_calculated_lb_period
+    if (ratio_at_t != 1.0) {
+      DEBAD(("Changed tolerance to %lf after line eq whereas max/avg is %lf\n",
+        ratio_at_t, max/avg));
+      // Since ratio_at_t is shifter up, max/(tmp_max_avg_ratio * avg) should be
+      // compared with the tolerance
+      tolerate_imb = ratio_at_t * tmp_max_avg_ratio * OUTOFWAY_TOLERANCE;
+    }
+
+    DEBAD(("Prev LB Data Type %d, max/avg %lf, local/remote %lf\n",
+      tmp_lb_type, tmp_max_avg_ratio, tmp_comm_ratio));
+
+    if ((utilization < utilization_threshold || max/avg >= tolerate_imb) &&
+          adaptive_lbdb.history_data.size() > MIN_STATS) {
+      DEBAD(("Trigger soon even though we calculated lbperiod max/avg(%lf) and utilization ratio (%lf)\n", max/avg, utilization));
+      TriggerSoon(iteration_n, max/avg, tolerate_imb);
+      return;
+    }
+
+    // If the new lb period from linear extrapolation is greater than maximum
+    // iteration known from previously collected data, then inform all the
+    // processors about the new calculated period.
+    if (period > adaptive_struct.tentative_max_iter_no && period !=
+          adaptive_struct.final_lb_period) {
+      adaptive_struct.doCommStrategy = false;
+      adaptive_struct.lb_calculated_period = period;
+      adaptive_struct.in_progress = true;
+      DEBAD(("Sticking to the calculated period %d\n",
+          adaptive_struct.lb_calculated_period));
+      thisProxy.LoadBalanceDecision(adaptive_struct.lb_msg_send_no++,
+        adaptive_struct.lb_calculated_period);
+      return;
+    }
+    return;
+  }
+
+  DEBAD(("Prev LB Data Type %d, max/avg %lf, local/remote %lf\n", tmp_lb_type,
+      tmp_max_avg_ratio, tmp_comm_ratio));
+
+  // This would be called when linear extrapolation did not provide suitable
+  // period provided there is enough  historical data 
+  if ((utilization < utilization_threshold || max/avg >= tolerate_imb) && adaptive_lbdb.history_data.size() > 4) {
+    DEBAD(("Carry out load balancing step at iter max/avg(%lf) and utilization \
+      ratio (%lf)\n", max/avg, utilization));
+    TriggerSoon(iteration_n, max/avg, tolerate_imb);
+    return;
+  }
+
+}
+
+void MetaBalancer::TriggerSoon(int iteration_n, double imbalance_ratio,
+    double tolerate_imb) {
+
+  // If the previously calculated_period (not the final decision) is greater
+  // than the iter +1 and if it is greater than the maximum iteration we have
+  // seen so far, then we can inform this
+  if ((iteration_n + 1 > adaptive_struct.tentative_max_iter_no) &&
+      (iteration_n+1 < adaptive_struct.lb_calculated_period) &&
+      (iteration_n + 1 != adaptive_struct.final_lb_period)) {
+    if (imbalance_ratio < tolerate_imb) {
+      adaptive_struct.doCommStrategy = true;
+      DEBAD(("No load imbalance but idle time\n"));
+    } else {
+      adaptive_struct.doCommStrategy = false;
+      DEBAD(("load imbalance \n"));
+    }
+    adaptive_struct.lb_calculated_period = iteration_n + 1;
+    adaptive_struct.in_progress = true;
+    DEBAD(("Informing everyone the lb period is %d\n",
+        adaptive_struct.lb_calculated_period));
+    thisProxy.LoadBalanceDecision(adaptive_struct.lb_msg_send_no++,
+        adaptive_struct.lb_calculated_period);
+  }
+}
+
+bool MetaBalancer::generatePlan(int& period, double& ratio_at_t) {
+  if (adaptive_lbdb.history_data.size() <= 4) {
+    return false;
+  }
+
+  // Some heuristics for lbperiod
+  // If constant load or almost constant,
+  // then max * new_lb_period > avg * new_lb_period + lb_cost
+  double max = 0.0;
+  double avg = 0.0;
+  AdaptiveData data;
+  for (int i = 0; i < adaptive_lbdb.history_data.size(); i++) {
+    data = adaptive_lbdb.history_data[i];
+    max += data.max_load;
+    avg += data.avg_load;
+    DEBAD(("max (%d, %lf) avg (%d, %lf)\n", i, data.max_load, i, data.avg_load));
+  }
+//  max /= (adaptive_struct.lb_iteration_no - adaptive_lbdb.history_data[0].iteration);
+//  avg /= (adaptive_struct.lb_iteration_no - adaptive_lbdb.history_data[0].iteration);
+
+  // If linearly varying load, then find lb_period
+  // area between the max and avg curve
+  // If we can attain perfect balance, then the new load is close to the
+  // average. Hence we pass 1, else pass in some other value which would be the
+  // new max_load after load balancing.
+  int tmp_lb_type;
+  double tmp_max_avg_ratio, tmp_comm_ratio;
+  double tolerate_imb;
+
+#if EXTRA_FEATURE
+  // First get the data for refine.
+  GetLBDataForLB(1, tmp_max_avg_ratio, tmp_comm_ratio);
+  tolerate_imb = tmp_max_avg_ratio;
+
+  // If RefineLB does a good job, then find the period considering RefineLB
+  if (tmp_max_avg_ratio <= 1.01) {
+    if (max/avg < tolerate_imb) {
+      DEBAD(("Resorting to imb = 1.0 coz max/avg (%lf) < imb(%lf)\n", max/avg,
+          tolerate_imb));
+      tolerate_imb = 1.0;
+    }
+    DEBAD(("Will generate plan for refine %lf imb and %lf overhead\n",
+        tolerate_imb, 0.2));
+    return getPeriodForStrategy(tolerate_imb, 0.2, period, ratio_at_t);
+  }
+
+  GetLBDataForLB(0, tmp_max_avg_ratio, tmp_comm_ratio);
+#endif
+
+  GetPrevLBData(tmp_lb_type, tmp_max_avg_ratio, tmp_comm_ratio);
+  tolerate_imb = tmp_max_avg_ratio;
+//  if (max/avg < tolerate_imb) {
+//    CkPrintf("Resorting to imb = 1.0 coz max/avg (%lf) < imb(%lf)\n", max/avg, tolerate_imb);
+//    tolerate_imb = 1.0;
+//  }
+  if (max/avg > tolerate_imb) {
+    if (getPeriodForStrategy(tolerate_imb, 1, period, ratio_at_t)) {
+      return true;
+    }
+  }
+
+  max = 0.0;
+  avg = 0.0;
+  for (int i = 0; i < adaptive_lbdb.history_data.size(); i++) {
+    data = adaptive_lbdb.history_data[i];
+    max += data.max_load;
+    avg += data.avg_load*tolerate_imb;
+  }
+  max /= adaptive_lbdb.history_data.size();
+  avg /= adaptive_lbdb.history_data.size();
+  double cost = adaptive_struct.lb_strategy_cost + adaptive_struct.lb_migration_cost;
+  period = (int) (cost/(max - avg));
+  DEBAD(("Obtained period %d from constant prediction tolerated \
+                       imbalance(%f)\n", period, tolerate_imb));
+  if (period < 0) { 
+    period = adaptive_struct.final_lb_period;
+    DEBAD(("Obtained -ve period from constant prediction so changing to prev %d\n", period));
+  } 
+  ratio_at_t = max / avg;
+  return true;
+}
+
+bool MetaBalancer::getPeriodForStrategy(double new_load_percent,
+    double overhead_percent, int& period, double& ratio_at_t) {
+  double mslope, aslope, mc, ac;
+  getLineEq(new_load_percent, aslope, ac, mslope, mc);
+  DEBAD(("new load percent %lf\n", new_load_percent));
+  DEBAD(("\n max: %fx + %f; avg: %fx + %f\n", mslope, mc, aslope, ac));
+  double a = (mslope - aslope)/2;
+  double b = (mc - ac);
+  double c = -(adaptive_struct.lb_strategy_cost +
+      adaptive_struct.lb_migration_cost) * overhead_percent;
+  DEBAD(("cost %f\n",
+      (adaptive_struct.lb_strategy_cost+adaptive_struct.lb_migration_cost)));
+  bool got_period = getPeriodForLinear(a, b, c, period);
+  if (!got_period) {
+    return false;
+  }
+
+  if (mslope < 0) {
+    if (period > (-mc/mslope)) {
+      DEBAD(("Max < 0 Period set when max load is -ve\n"));
+      return false;
+    }
+  }
+
+  if (aslope < 0) {
+    if (period > (-ac/aslope)) {
+      DEBAD(("Avg < 0 Period set when avg load is -ve\n"));
+      return false;
+    }
+  }
+
+  int intersection_t = (int) ((mc-ac) / (aslope - mslope));
+  if (intersection_t > 0 && period > intersection_t) {
+    DEBAD(("Avg | Max Period set when curves intersect\n"));
+    return false;
+  }
+  ratio_at_t = ((mslope*period + mc)/(aslope*period + ac));
+  DEBAD(("Ratio at t (%lf*%d + %lf) / (%lf*%d+%lf) = %lf\n", mslope, period, mc, aslope, period, ac, ratio_at_t));
+  return true;
+}
+
+bool MetaBalancer::getPeriodForLinear(double a, double b, double c, int& period) {
+  DEBAD(("Quadratic Equation %lf X^2 + %lf X + %lf\n", a, b, c));
+  if (a == 0.0) {
+    period = (int) (-c / b);
+    if (period < 0) {
+      DEBAD(("-ve period for -c/b (%d)\n", period));
+      return false;
+    }
+    DEBAD(("Ideal period for linear load %d\n", period));
+    return true;
+  }
+  int x;
+  double t = (b * b) - (4*a*c);
+  if (t < 0) {
+    DEBAD(("(b * b) - (4*a*c) is -ve sqrt : %lf\n", sqrt(t)));
+    return false;
+  }
+  t = (-b + sqrt(t)) / (2*a);
+  x = (int) t;
+  if (x < 0) {
+    DEBAD(("Oops!!! x (%d) < 0\n", x));
+    x = 0;
+    return false;
+  }
+  period = x;
+  DEBAD(("Ideal period for linear load %d\n", period));
+  return true;
+}
+
+bool MetaBalancer::getLineEq(double new_load_percent, double& aslope, double& ac, double& mslope, double& mc) {
+  int total = adaptive_lbdb.history_data.size();
+  int iterations = (int) (1 + adaptive_lbdb.history_data[total - 1].iteration -
+      adaptive_lbdb.history_data[0].iteration);
+  double a1 = 0;
+  double m1 = 0;
+  double a2 = 0;
+  double m2 = 0;
+  AdaptiveData data;
+  int i = 0;
+  for (i = 0; i < total/2; i++) {
+    data = adaptive_lbdb.history_data[i];
+    m1 += data.max_load;
+    a1 += data.avg_load;
+    DEBAD(("max (%d, %lf) avg (%d, %lf) adjusted_avg (%d, %lf)\n", i, data.max_load, i, data.avg_load, i, new_load_percent*data.avg_load));
+  }
+  m1 /= i;
+  a1 = (a1 * new_load_percent) / i;
+
+  for (i = total/2; i < total; i++) {
+    data = adaptive_lbdb.history_data[i];
+    m2 += data.max_load;
+    a2 += data.avg_load;
+    DEBAD(("max (%d, %lf) avg (%d, %lf) adjusted_avg (%d, %lf)\n", i, data.max_load, i, data.avg_load, i, new_load_percent*data.avg_load));
+  }
+  m2 /= (i - total/2);
+  a2 = (a2 * new_load_percent) / (i - total/2);
+
+  aslope = 2 * (a2 - a1) / iterations;
+  mslope = 2 * (m2 - m1) / iterations;
+  ac = adaptive_lbdb.history_data[0].avg_load * new_load_percent;
+  mc = adaptive_lbdb.history_data[0].max_load;
+
+  ac = a1 - ((aslope * total)/4);
+  mc = m1 - ((mslope * total)/4);
+
+  //ac = (adaptive_lbdb.history_data[1].avg_load * new_load_percent - aslope);
+  //mc = (adaptive_lbdb.history_data[1].max_load - mslope);
+
+  return true;
+}
+
+void MetaBalancer::LoadBalanceDecision(int req_no, int period) {
+  if (req_no < adaptive_struct.lb_msg_recv_no) {
+    DEBAD(("Error!!! Received a request which was already sent or old\n"));
+    return;
+  }
+  DEBADDETAIL(("[%d] Load balance decision made cur iteration: %d period:%d\n",
+                       CkMyPe(), adaptive_struct.lb_iteration_no, period));
+  adaptive_struct.tentative_period = period;
+  adaptive_struct.lb_msg_recv_no = req_no;
+  if (metaRdnGroup == NULL) {
+    metaRdnGroup = (MetaBalancerRedn*)CkLocalBranch(_metalbred);
+  }
+  if (metaRdnGroup != NULL) {
+    metaRdnGroup->getMaxIter(adaptive_struct.lb_iteration_no);
+  }
+}
+
+void MetaBalancer::LoadBalanceDecisionFinal(int req_no, int period) {
+  if (req_no < adaptive_struct.lb_msg_recv_no) {
+    return;
+  }
+  DEBADDETAIL(("[%d] Final Load balance decision made cur iteration: %d \
+                       period:%d \n",CkMyPe(), adaptive_struct.lb_iteration_no, period));
+  adaptive_struct.tentative_period = period;
+  adaptive_struct.final_lb_period = period;
+  lbdatabase->MetaLBResumeWaitingChares(period);
+}
+
+void MetaBalancer::MetaLBCallLBOnChares() {
+  lbdatabase->MetaLBCallLBOnChares();
+}
+
+void MetaBalancer::ReceiveIterationNo(int local_iter_no) {
+  CmiAssert(CkMyPe() == 0);
+
+  if (local_iter_no > adaptive_struct.global_max_iter_no) {
+    adaptive_struct.global_max_iter_no = local_iter_no;
+  }
+
+  int period;
+
+    if (adaptive_struct.global_max_iter_no > adaptive_struct.tentative_max_iter_no) {
+      adaptive_struct.tentative_max_iter_no = adaptive_struct.global_max_iter_no;
+    }
+    period = (adaptive_struct.tentative_period > adaptive_struct.global_max_iter_no) ?
+                               adaptive_struct.tentative_period : adaptive_struct.global_max_iter_no + 1;
+    // If no one has gone into load balancing stage, then we can safely change
+    // the period otherwise keep the old period.
+    if (adaptive_struct.global_max_iter_no < adaptive_struct.final_lb_period) {
+      adaptive_struct.tentative_period = period;
+      DEBAD(("Final lb_period CHANGED!%d\n", adaptive_struct.tentative_period));
+    } else {
+      adaptive_struct.tentative_period = adaptive_struct.final_lb_period;
+      DEBAD(("Final lb_period NOT CHANGED!%d\n", adaptive_struct.tentative_period));
+    }
+    thisProxy.LoadBalanceDecisionFinal(adaptive_struct.lb_msg_recv_no, adaptive_struct.tentative_period);
+    adaptive_struct.in_progress = false;
+}
+
+int MetaBalancer::getPredictedLBPeriod(bool& is_tentative) {
+  // If tentative and final_lb_period are the same, then the decision has been
+  // made but if not, they are in the middle of consensus, hence return the
+  // lease of the two
+  if (adaptive_struct.tentative_period != adaptive_struct.final_lb_period) {
+    is_tentative = true;
+  } else {
+    is_tentative = false;
+  }
+  if (adaptive_struct.tentative_period < adaptive_struct.final_lb_period) {
+    return adaptive_struct.tentative_period;
+   } else {
+     return adaptive_struct.final_lb_period;
+   }
+}
+
+// Called by CentralLB to indicate that the LB strategy and migration is in
+// progress.
+void MetaBalancer::ResetAdaptive() {
+  adaptive_lbdb.lb_iter_no = -1;
+  lb_in_progress = true;
+}
+
+// This is required for PEs with no objs
+void MetaBalancer::periodicCall(void *ad) {
+  MetaBalancer *s = (MetaBalancer *)ad;
+  CcdCallFnAfterOnPE((CcdVoidFn)checkForNoObj, (void *)s, 500, CkMyPe());
+}
+
+void MetaBalancer::checkForNoObj(void *ad) {
+  MetaBalancer *s = (MetaBalancer *) ad;
+  s->HandleAdaptiveNoObj();
+}
+
+// Called by LBDatabase to indicate that no objs are there in this processor
+void MetaBalancer::HandleAdaptiveNoObj() {
+  if (lbdatabase->getLBDB()->ObjDataCount() == 0) {
+    adaptive_struct.finished_iteration_no++;
+    adaptive_struct.lb_iteration_no++;
+    DEBAD(("(%d) --HandleAdaptiveNoObj %d\n", CkMyPe(),
+          adaptive_struct.finished_iteration_no));
+    thisProxy[0].RegisterNoObjCallback(CkMyPe());
+    TriggerAdaptiveReduction();
+  }
+}
+
+void MetaBalancer::RegisterNoObjCallback(int index) {
+  // If the load balancing process (migration) is going on and in the meantime
+  // one of the processor finishes everything and finds that there are no objs
+  // in it, then it registers a callback. So clear the old data in case it
+  // hasn't been done.
+  if (lb_in_progress) {
+    lbdb_no_obj_callback.clear();
+    lb_in_progress = false;
+  }
+  lbdb_no_obj_callback.push_back(index);
+  DEBAD(("Registered %d to have no objs.\n", index));
+
+  // If collection has already happened and this is second iteration, then
+  // trigger reduction.
+  if (adaptive_lbdb.lb_iter_no != -1) {
+    DEBAD(("Collection already started now %d so kick in\n",
+        adaptive_struct.finished_iteration_no));
+    //thisProxy[index].TriggerAdaptiveReduction();
+  }
+}
+
+void MetaBalancer::TriggerAdaptiveReduction() {
+  if (lbdatabase->getLBDB()->ObjDataCount() == 0) {
+    adaptive_struct.finished_iteration_no++;
+    adaptive_struct.lb_iteration_no++;
+    double lb_data[STATS_COUNT];
+    lb_data[0] = adaptive_struct.finished_iteration_no;
+    lb_data[1] = 1;
+    lb_data[2] = 0.0;
+    lb_data[3] = 0.0;
+    lb_data[4] = 0.0;
+    lb_data[5] = 0.0;
+    lb_data[6] = 0.0;
+    lb_data[7] = 0.0;
+
+    DEBAD(("[%d] Triggered adaptive reduction for noobj %d\n", CkMyPe(),
+          adaptive_struct.finished_iteration_no));
+
+    CkCallback cb(CkIndex_MetaBalancer::ReceiveMinStats((CkReductionMsg*)NULL),
+        thisProxy[0]);
+    contribute(STATS_COUNT*sizeof(double), lb_data, lbDataCollectionType, cb);
+  }
+}
+
+
+bool MetaBalancer::isStrategyComm() {
+  return adaptive_struct.doCommStrategy;
+}
+
+void MetaBalancer::SetMigrationCost(double lb_migration_cost) {
+  adaptive_struct.lb_migration_cost = lb_migration_cost;
+}
+
+void MetaBalancer::SetStrategyCost(double lb_strategy_cost) {
+  adaptive_struct.lb_strategy_cost = lb_strategy_cost;
+}
+
+void MetaBalancer::UpdateAfterLBData(int lb, double lb_max, double lb_avg, double
+    local_comm, double remote_comm) {
+  adaptive_struct.last_lb_type = lb;
+  if (lb == 0) {
+    adaptive_struct.greedy_info.max_avg_ratio = lb_max/lb_avg;
+  } else if (lb == 1) {
+    adaptive_struct.refine_info.max_avg_ratio = lb_max/lb_avg;
+  } else if (lb == 2) {
+    adaptive_struct.comm_info.remote_local_ratio = remote_comm/local_comm;
+  } else if (lb == 3) {
+    adaptive_struct.comm_refine_info.remote_local_ratio =
+    remote_comm/local_comm;
+  }
+}
+
+void MetaBalancer::UpdateAfterLBData(double max_load, double max_cpu,
+    double avg_load) {
+  if (adaptive_struct.last_lb_type == -1) {
+    adaptive_struct.last_lb_type = 0;
+  }
+  int lb = adaptive_struct.last_lb_type;
+  if (lb == 0) {
+    adaptive_struct.greedy_info.max_avg_ratio = max_load/avg_load;
+  } else if (lb == 1) {
+    adaptive_struct.refine_info.max_avg_ratio = max_load/avg_load;
+  } else if (lb == 2) {
+    adaptive_struct.comm_info.max_avg_ratio = max_load/avg_load;
+  } else if (lb == 3) {
+    adaptive_struct.comm_refine_info.max_avg_ratio = max_load/avg_load;
+  }
+}
+
+void MetaBalancer::UpdateAfterLBComm(double alpha_beta_to_load) {
+  DEBAD(("Setting alpha beta %lf\n", alpha_beta_to_load));
+  alpha_beta_cost_to_load = alpha_beta_to_load;
+}
+
+
+void MetaBalancer::GetPrevLBData(int& lb_type, double& lb_max_avg_ratio,
+    double& remote_local_comm_ratio) {
+  lb_type = adaptive_struct.last_lb_type;
+  lb_max_avg_ratio = 1;
+  remote_local_comm_ratio = 1;
+  GetLBDataForLB(lb_type, lb_max_avg_ratio, remote_local_comm_ratio);
+
+  // Based on the first iteration
+  lb_max_avg_ratio = adaptive_struct.info_first_iter.max_avg_ratio;
+}
+
+void MetaBalancer::GetLBDataForLB(int lb_type, double& lb_max_avg_ratio,
+    double& remote_local_comm_ratio) {
+  if (lb_type == 0) {
+    lb_max_avg_ratio = adaptive_struct.greedy_info.max_avg_ratio;
+  } else if (lb_type == 1) {
+    lb_max_avg_ratio = adaptive_struct.refine_info.max_avg_ratio;
+  } else if (lb_type == 2) {
+    remote_local_comm_ratio = adaptive_struct.comm_info.remote_local_ratio;
+  } else if (lb_type == 3) {
+    remote_local_comm_ratio =
+       adaptive_struct.comm_refine_info.remote_local_ratio;
+  }
+}
+
+void MetaBalancerRedn::init() {
+  metabalancer = (MetaBalancer *)CkLocalBranch(_metalb);
+}
+
+void MetaBalancerRedn::pup(PUP::er& p) {
+       CBase_MetaBalancerRedn::pup(p);
+}
+
+void MetaBalancerRedn::ReceiveIterNo(int max_iter) {
+  CkAssert(CkMyPe() == 0);
+  if (metabalancer == NULL) {
+    metabalancer = (MetaBalancer*)CkLocalBranch(_metalb);
+  }
+  if (metabalancer != NULL) {
+    metabalancer->ReceiveIterationNo(max_iter);
+  }
+}
+
+void MetaBalancerRedn::getMaxIter(int max_iter) {
+  CkCallback cb(CkReductionTarget(MetaBalancerRedn, ReceiveIterNo), thisProxy[0]);
+  contribute(sizeof(int), &max_iter, CkReduction::max_int, cb);
+}
+
+#include "MetaBalancer.def.h"
+
+/*@}*/
diff --git a/src/ck-ldb/MetaBalancer.ci b/src/ck-ldb/MetaBalancer.ci
new file mode 100644 (file)
index 0000000..f067fa9
--- /dev/null
@@ -0,0 +1,33 @@
+module MetaBalancer {
+  readonly CkGroupID _metalb;
+  readonly CkGroupID _metalbred;
+
+  mainchare MetaLBInit {
+    entry MetaLBInit(CkArgMsg *m);
+  };
+
+  initproc void registerLBDataCollection(void);
+  group [migratable] MetaBalancer {
+    entry void MetaBalancer(void);  
+    initnode void initnodeFn();
+
+    entry [immediate] void ReceiveMinStats(CkReductionMsg *msg);
+    entry [immediate] void LoadBalanceDecision(int req_no, int period);
+    entry [immediate] void LoadBalanceDecisionFinal(int req_no, int period);
+    entry [immediate] void ReceiveIterationNo(int);
+    entry [immediate] void RegisterNoObjCallback(int);
+    entry [immediate] void TriggerAdaptiveReduction();
+    entry [immediate] void MetaLBCallLBOnChares();
+  }
+
+  // This group is used only to handle reduction to obtain the maximum
+  // iteration. This reduction cannot incorporated in MetaBalancer class because
+  // there exists a reduction to collect minimum stats and this would overlap
+  // with that as there is no specific order.
+  group [migratable] MetaBalancerRedn {
+    entry void MetaBalancerRedn(void);
+    entry [immediate, reductiontarget] void ReceiveIterNo(int max_iter);
+    entry void getMaxIter(int);
+  }
+
+};
diff --git a/src/ck-ldb/MetaBalancer.h b/src/ck-ldb/MetaBalancer.h
new file mode 100644 (file)
index 0000000..378fa98
--- /dev/null
@@ -0,0 +1,200 @@
+/**
+* Meta-Balancer is for automating the load balancing decisions based on the
+* application characteristics. The decision of when to call the load balancer is
+* handled by the MetaBalancer if +MetaLB flag is set when launching the
+* application. AtSync should be called very often (every couple of iterations).
+*
+* Meta-Balancer is not aware of the application iteration so it depends on
+* AtSync calls to count the iterations. At every AtSync call, if +MetaLB is
+* set, the chare sends its object load to the MetaBalancer on its local
+* processor and resumes its work. Once all the chares residing on the processor
+* has contributed their load information, this information is collected at the
+* central processor(root) using reduction. The root calculates the ideal period
+* based on linear extrapolation and informs a tentative lb period to all the
+* processors via broadcast. The Meta-Balancer residing on each processor then
+* informs the root about the maximum iteration of any chare on their processor.
+* The root then informs the final lb period, which is the max of calculated and
+* max. Meanwhile, chares can be in various states. Chare goes to LOAD_BALANCE
+* state when it enters load balancing phase. It goes to PAUSE state when the
+* chare has reached the tentative period and is waiting for the final period to
+* be announced.
+*
+* To handle the case of no objects on a particular processor, a timer call is
+* set which checks for the number of objects and if found to be == 0,
+* contributes to the reduction which collects minimum statistics.
+*/
+
+#ifndef METABALANCER_H
+#define METABALANCER_H
+
+#include "LBDatabase.h"
+
+#include <vector>
+
+#include "MetaBalancer.decl.h"
+
+extern CkGroupID _metalb;
+extern CkGroupID _metalbred;
+
+CkpvExtern(int, metalbInited);
+
+void _MetaLBInit();
+
+// main chare
+class MetaLBInit : public Chare {
+  public:
+    MetaLBInit(CkArgMsg*);
+    MetaLBInit(CkMigrateMessage *m):Chare(m) {}
+};
+
+class MetaBalancer : public CBase_MetaBalancer {
+public:
+  MetaBalancer(void) { init(); }
+  MetaBalancer(CkMigrateMessage *m) : CBase_MetaBalancer(m) { init(); }
+  ~MetaBalancer()  {}
+private:
+  void init();
+  MetaBalancerRedn* metaRdnGroup;
+
+public:
+  inline static MetaBalancer * Object() {
+    return CkpvAccess(metalbInited)?(MetaBalancer *)CkLocalBranch(_metalb):NULL;
+  }
+
+  static void initnodeFn(void);
+
+  void pup(PUP::er& p);
+
+  void ResumeClients();
+
+  void ResetAdaptive();
+  int get_iteration();
+  int get_finished_iteration();
+  bool AddLoad(int iteration, double load);
+  void ReceiveMinStats(CkReductionMsg *);
+  void TriggerSoon(int iteration_no, double imbalance_ratio, double tolerate_imb);
+  void LoadBalanceDecision(int, int);
+  void LoadBalanceDecisionFinal(int, int);
+  void MetaLBCallLBOnChares();
+  void ReceiveIterationNo(int); // Receives the current iter no
+  static void periodicCall(void *ad);
+  static void checkForNoObj(void *ad);
+  void HandleAdaptiveNoObj();
+  void RegisterNoObjCallback(int index);
+  void TriggerAdaptiveReduction();
+
+  bool generatePlan(int& period, double& ratio_at_t);
+  bool getLineEq(double new_load_percent, double& aslope, double& ac,
+      double& mslope, double& mc);
+  bool getPeriodForLinear(double a, double b, double c, int& period);
+  bool getPeriodForStrategy(double new_load, double overhead_percent,
+      int& period, double& ratio_at_t);
+  int getPredictedLBPeriod(bool& is_tentative);
+
+  bool isStrategyComm();
+
+  void UpdateAfterLBData(int is_lb_refine, double lb_max, double lb_avg, double
+      local_comm, double remote_comm);
+
+  void UpdateAfterLBData(double max_load, double max_cpu, double avg_load);
+  void UpdateAfterLBComm(double alpha_beta_cost);
+  void GetPrevLBData(int& lb_type, double& lb_max_avg_ratio, double&
+      local_remote_comm_ratio);
+  void GetLBDataForLB(int lb_type, double& lb_max_avg_ratio, double&
+      local_remote_comm_ratio);
+
+  void SetMigrationCost(double lb_migration_cost);
+  void SetStrategyCost(double lb_strategy_cost);
+
+private:
+  //CProxy_MetaBalancer thisProxy;
+  LBDatabase* lbdatabase;
+  std::vector<double> total_load_vec;
+  // Keeps track of how many local chares contributed
+  std::vector<int> total_count_vec;
+  std::vector<int> lbdb_no_obj_callback;
+
+  double prev_idle;
+  double alpha_beta_cost_to_load;
+  int is_prev_lb_refine;
+
+  struct AdaptiveData {
+    double iteration;
+    double max_load;
+    double avg_load;
+    double utilization;
+    double idle_time;
+  };
+
+  struct AdaptiveMetaBalancer {
+    CkVec<AdaptiveData> history_data;
+    int lb_iter_no;
+  } adaptive_lbdb;
+
+  struct AdaptiveLBInfo {
+    AdaptiveLBInfo() {
+      max_avg_ratio = 1;
+      remote_local_ratio = 1;
+    }
+    double max_avg_ratio;
+    double remote_local_ratio;
+  };
+
+  // TODO: Separate out the datastructure required by just the central and on all
+  // processors
+  struct AdaptiveLBStructure {
+    int tentative_period;
+    int final_lb_period;
+    // This is based on the linear extrapolation
+    int lb_calculated_period;
+    // Current maximum iteration no of any chare on this processor
+    int lb_iteration_no;
+    // This corresponds to the last iteration that was contributed
+    int finished_iteration_no;
+    // This is set when all the processor sends the maximum iteration no
+    int global_max_iter_no;
+    // This keeps track of what was the max iteration no we had previously
+    // received. TODO: Mostly global_max_iter_no should be sufficied.
+    int tentative_max_iter_no;
+    // true indicates it is in Inform->ReceiveMaxIter->FinalLBPeriod stage.
+    bool in_progress;
+    double lb_strategy_cost;
+    double lb_migration_cost;
+    bool doCommStrategy;
+    int lb_msg_send_no;
+    int lb_msg_recv_no;
+    // Total AtSync calls from all the chares residing on the processor
+    int total_syncs_called;
+    int last_lb_type;
+    AdaptiveLBInfo greedy_info;
+    AdaptiveLBInfo refine_info;
+    AdaptiveLBInfo comm_info;
+    AdaptiveLBInfo comm_refine_info;
+    AdaptiveLBInfo info_first_iter;
+  } adaptive_struct;
+
+public:
+  bool lb_in_progress;
+
+};
+
+class MetaBalancerRedn : public CBase_MetaBalancerRedn {
+  public:
+    MetaBalancerRedn(void) {init();}
+    MetaBalancerRedn(CkMigrateMessage *m) : CBase_MetaBalancerRedn(m)  {init();}
+    ~MetaBalancerRedn()  {}
+    void pup(PUP::er& p);
+    void ReceiveIterNo(int max_iter);
+    void getMaxIter(int);
+
+  private:
+    MetaBalancer* metabalancer;
+    void init();
+};
+
+inline MetaBalancer* MetaBalancerObj() { return MetaBalancer::Object(); }
+
+#endif /* LDATABASE_H */
+
+/*@}*/
index ca41be6667bd8a96875d9e45ee15e0ec1507c26c..f0bc990484b13b17c3f6461784271f1b539930b6 100644 (file)
@@ -51,6 +51,16 @@ void RefineLB::work(LDStats* stats)
       }
   }
 
+  if (_lb_args.metaLbOn()) {
+    stats->is_prev_lb_refine = 1;
+    stats->after_lb_avg = refiner.computeAverageLoad();
+    stats->after_lb_max = refiner.computeMax();
+
+    if (_lb_args.debug() > 0)
+      CkPrintf("RefineLB> Max load %lf Avg load %lf\n", stats->after_lb_max,
+          stats->after_lb_avg);
+  }
+
   // Free the refine buffers
   Refiner::FreeProcs(from_procs);
   Refiner::FreeProcs(to_procs);
index e8079a7489c43e881a42afd8e81c7e1a25984249..e78b0be560a353d3268fa091d15caa395afd9d95 100644 (file)
@@ -83,6 +83,11 @@ void  Refiner::deAssign(computeInfo *c, processorInfo *p)
    p->load = p->computeLoad + p->backgroundLoad;
 }
 
+double Refiner::computeAverageLoad() {
+  computeAverage();
+  return averageLoad;
+}
+
 void Refiner::computeAverage()
 {
   int i;
index 388a0632bc3445fd5927d86018e9252db22629ea..7cf23762e0efaec04b82e1a50a00380916885744 100644 (file)
@@ -21,6 +21,9 @@ public:
   static void FreeProcs(int* bufs);
   void Refine(int count, BaseLB::LDStats* stats, int* cur_p, int* new_p);
 
+  double computeAverageLoad();
+  double computeMax();
+
 protected:
   void create(int count, BaseLB::LDStats* stats, int* cur_p);
   virtual int refine();
@@ -29,7 +32,6 @@ protected:
   void assign(computeInfo *c, processorInfo *p);
   void deAssign(computeInfo *c, processorInfo *pRec);
   virtual void computeAverage();
-  double computeMax();
   int isHeavy(processorInfo *p);
   int isLight(processorInfo *p);
   void removeComputes();
index 3876c028ad61ec32568c69d6d17034d7182549db..abc23438d08992cc0176a9549220f227159fcaa8 100644 (file)
@@ -29,6 +29,16 @@ extern "C" LDOMHandle LDRegisterOM(LDHandle _db, LDOMid _userID,
   return db->AddOM(_userID, _userptr, _callbacks);
 }
 
+extern "C" void LDOMMetaLBResumeWaitingChares(LDHandle _db, int lb_ideal_period) {
+  LBDB *const db = (LBDB*)(_db.handle);
+  db->MetaLBResumeWaitingChares(lb_ideal_period);
+}
+
+extern "C" void LDOMMetaLBCallLBOnChares(LDHandle _db) {
+  LBDB *const db = (LBDB*)(_db.handle);
+  db->MetaLBCallLBOnChares();
+}
+
 extern "C" void * LDOMUserData(LDOMHandle &_h)
 {
   LBDB *const db = (LBDB*)(_h.ldb.handle);
index ae7957f155b94a48b27e2458830c7e6a143cbfb7..2b8fbcd7d8443359012c9a94793c48cb41d185db 100644 (file)
@@ -225,11 +225,15 @@ void LBCollectStatsOff(void);
 typedef void (*LDMigrateFn)(LDObjHandle handle, int dest);
 typedef void (*LDStatsFn)(LDOMHandle h, int state);
 typedef void (*LDQueryEstLoadFn)(LDOMHandle h);
+typedef void (*LDMetaLBResumeWaitingCharesFn) (LDObjHandle handle, int lb_ideal_period);
+typedef void (*LDMetaLBCallLBOnCharesFn) (LDObjHandle handle);
 
 typedef struct {
   LDMigrateFn migrate;
   LDStatsFn setStats;
   LDQueryEstLoadFn queryEstLoad;
+  LDMetaLBResumeWaitingCharesFn metaLBResumeWaitingChares;
+  LDMetaLBCallLBOnCharesFn metaLBCallLBOnChares;
 } LDCallbacks;
 
 /*
@@ -243,6 +247,9 @@ LDHandle LDCreate(void);
 
 LDOMHandle LDRegisterOM(LDHandle _lbdb, LDOMid userID, 
                        void *userptr, LDCallbacks cb);
+
+void LDOMMetaLBResumeWaitingChares(LDHandle _h, int lb_ideal_period);
+void LDOMMetaLBCallLBOnChares(LDHandle _h);
 void * LDOMUserData(LDOMHandle &_h);
 void LDRegisteringObjects(LDOMHandle _h);
 void LDDoneRegisteringObjects(LDOMHandle _h);
index 63217d182ca28a00046d5ba8b502b6cd5adad123..5aa0ed93b6340e3e3d7c8a78f2a11e3a6905731e 100644 (file)
@@ -1,4 +1,5 @@
 #generated by make cidepends
+AdaptiveLB.decl.h AdaptiveLB.def.h: AdaptiveLB.ci.stamp
 BaseLB.decl.h BaseLB.def.h: BaseLB.ci.stamp
 BlockLB.decl.h BlockLB.def.h: BlockLB.ci.stamp
 BlueGene.decl.h BlueGene.def.h: BlueGene.ci.stamp
@@ -37,6 +38,7 @@ HbmLB.decl.h HbmLB.def.h: HbmLB.ci.stamp
 HybridBaseLB.decl.h HybridBaseLB.def.h: HybridBaseLB.ci.stamp
 HybridLB.decl.h HybridLB.def.h: HybridLB.ci.stamp
 LBDatabase.decl.h LBDatabase.def.h: LBDatabase.ci.stamp
+MetaBalancer.decl.h MetaBalancer.def.h: MetaBalancer.ci.stamp
 MetisLB.decl.h MetisLB.def.h: MetisLB.ci.stamp
 mpi_main.decl.h mpi_main.def.h: mpi-mainmodule.ci.stamp
 NborBaseLB.decl.h NborBaseLB.def.h: NborBaseLB.ci.stamp
index df0aac5039ddbfebd2a3a2ec12e4bc4b32750d58..c96c58fbb705459f094b11258fb217aa85f28103 100644 (file)
@@ -225,7 +225,7 @@ CKHEADERS=ck.h ckstream.h envelope.h init.h qd.h charm.h charm++.h \
          ckobjQ.h readonly.h charisma.h \
           comlib.h ComlibArrayListener.h ComlibStrategy.h \
          ComlibLearner.h $(UTILHEADERS) \
-         tempo.h waitqd.h LBDatabase.h lbdb.h lbdb++.h LBProfit.h $(LBHEADERS) \
+         tempo.h waitqd.h LBDatabase.h MetaBalancer.h lbdb.h lbdb++.h LBProfit.h $(LBHEADERS) \
           LBDBManager.h        LBComm.h LBOM.h LBObj.h LBMachineUtil.h LBAgent.h \
          Refiner.h RefinerApprox.h RefinerComm.h ckgraph.h ckheap.h \
           elements.h CommLBHeap.h topology.h manager.h \
@@ -237,7 +237,7 @@ CKHEADERS=ck.h ckstream.h envelope.h init.h qd.h charm.h charm++.h \
           CkReduction.decl.h CkArrayReductionMgr.decl.h\
           tempo.decl.h waitqd.decl.h \
           CkFutures.decl.h CkCheckpoint.decl.h CkMemCheckpoint.decl.h \
-          LBDatabase.decl.h CentralLB.decl.h NullLB.decl.h \
+          LBDatabase.decl.h MetaBalancer.decl.h CentralLB.decl.h NullLB.decl.h \
           BaseLB.decl.h \
          NborBaseLB.decl.h \
           HybridBaseLB.decl.h EveryLB.decl.h CommonLBs.decl.h \
@@ -712,7 +712,7 @@ CK_LIBS_CORE=$(L)/libck.a
 LIBCK_CORE=trace-common.o tracec.o tracef.o init.o register.o qd.o ck.o main.o \
           msgalloc.o ckfutures.o ckIgetControl.o debug-message.o debug-charm.o ckcallback.o \
           cklocation.o ckarray.o ckreduction.o ckarrayreductionmgr.o \
-           tempo.o waitqd.o LBDatabase.o lbdb.o lbdbf.o charisma.o ckobjQ.o  \
+           tempo.o waitqd.o LBDatabase.o MetaBalancer.o lbdb.o lbdbf.o charisma.o ckobjQ.o  \
           LBAgent.o LBProfit.o ckcheckpoint.o ckmemcheckpoint.o ckevacuation.o ckmessagelogging.o ckcausalmlog.o ckobjid.o\
            LBDBManager.o LBComm.o LBObj.o LBMachineUtil.o CentralPredictor.o \
           BaseLB.o CentralLB.o HybridBaseLB.o NborBaseLB.o \
@@ -773,8 +773,8 @@ libtrace-Tau.o: trace-Tau.C charm++.h charm.h converse.h conv-config.h \
   conv-ccs.h sockRoutines.h ccs-server.h ckobjQ.h ckreduction.h \
   CkReduction.decl.h CkArrayReductionMgr.decl.h \
   ckmemcheckpoint.h CkMemCheckpoint.decl.h readonly.h ckarray.h \
-  cklocation.h LBDatabase.h lbdb.h LBDBManager.h LBObj.h LBOM.h LBComm.h \
-  LBMachineUtil.h lbdb++.h LBDatabase.decl.h NullLB.decl.h BaseLB.decl.h \
+  cklocation.h LBDatabase.h MetaBalancer.h lbdb.h LBDBManager.h LBObj.h LBOM.h LBComm.h \
+  LBMachineUtil.h lbdb++.h LBDatabase.decl.h MetaBalancer.decl.h NullLB.decl.h BaseLB.decl.h \
   CkLocation.decl.h CkArray.decl.h ComlibArrayListener.h ComlibStrategy.h \
   convcomlibstrategy.h ComlibLearner.h envelope.h envelope-path.h CkFutures.decl.h \
   charisma.h charisma.decl.h tempo.h tempo.decl.h waitqd.h waitqd.decl.h \