Merging
authorHarshitha <gplkrsh2@illinois.edu>
Mon, 2 Apr 2012 17:52:01 +0000 (12:52 -0500)
committerHarshitha <gplkrsh2@illinois.edu>
Mon, 2 Apr 2012 17:52:01 +0000 (12:52 -0500)
27 files changed:
examples/charm++/jacobi1d/Makefile
examples/charm++/jacobi1d/jacobi1d.C
examples/charm++/jacobi1d/jacobi1d.ci
examples/charm++/load_balancing/kNeighbor/Makefile
examples/charm++/load_balancing/kNeighbor/kNeighbor.ci
src/ck-core/cklocation.C
src/ck-core/cklocation.h
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.ci
src/ck-ldb/CentralLB.h
src/ck-ldb/GreedyLB.C
src/ck-ldb/LBDBManager.C
src/ck-ldb/LBDBManager.h
src/ck-ldb/LBDatabase.C
src/ck-ldb/LBDatabase.ci
src/ck-ldb/LBDatabase.h
src/ck-ldb/LBOM.h
src/ck-ldb/MetisLB.C
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

index a51c5dd822a12fbd48fe4a505f7ffe7c33d5468a..9cda60e8b70a037b88c54366185cc6c72e576c3e 100644 (file)
@@ -1,4 +1,5 @@
-OPTS   = -g
+OPTS   = -O3
+#CHARMC        = $(HOME)/charm/bin/charmc $(OPTS)
 CHARMC = ../../../bin/charmc $(OPTS)
 
 OBJS = jacobi1d.o
@@ -6,7 +7,8 @@ OBJS = jacobi1d.o
 all: jacobi1d
 
 jacobi1d: $(OBJS)
-       $(CHARMC) -language charm++ -o jacobi1d $(OBJS)
+       $(CHARMC) -language charm++ -module CommonLBs -o jacobi1d  $(OBJS)
+       #$(CHARMC) -language charm++ -module CommonLBs -module AdaptiveLB -module MetisLB -o jacobi1d  $(OBJS)
 
 proj: $(OBJS)
        $(CHARMC) -language charm++ -tracemode projections -o jacobi1d.prj $(OBJS)
index ffcd1a2c5fed014c99a2f7f0ffac56e0e1074b24..8a29328621cfafe32bf43063eb6c8ef61b02ca31 100644 (file)
 // We want to wrap entries around, and because mod operator % 
 // sometimes misbehaves on negative values. -1 maps to the highest value.
 #define wrap_y(a)  (((a)+num_chares)%num_chares)
+#define index(a,b) ((b) + (a)*(arrayDimY))
 
-#define MAX_ITER       26
+#define MAX_ITER       100
 #define WARM_ITER      5
 #define TOP            1
 #define BOTTOM         2
+#define LBPERIOD 5
 
 double startTime;
 double endTime;
@@ -81,14 +83,18 @@ class Main : public CBase_Main
     void report(CkReductionMsg *msg) {
       iterations++;
       if(iterations == WARM_ITER)
-       startTime = CmiWallTimer();
+        startTime = CmiWallTimer();
       double error = *((double *)msg->getData());
 
       if(iterations < MAX_ITER) {
-       CkPrintf("Start of iteration %d\n", iterations);
-       array.begin_iteration();
+        if (iterations % LBPERIOD == 0) {
+          array.pause_for_lb();
+        } else {
+          CkPrintf("Start of iteration %d\n", iterations);
+          array.begin_iteration();
+        }
       } else {
-       CkPrintf("Completed %d iterations\n", MAX_ITER-1);
+        CkPrintf("Completed %d iterations\n", MAX_ITER-1);
         endTime = CmiWallTimer();
         CkPrintf("Time elapsed per iteration: %f\n", (endTime - startTime)/(MAX_ITER-1-WARM_ITER));
         CkExit();
@@ -102,129 +108,158 @@ class Jacobi: public CBase_Jacobi {
     int arrived_top;
     int arrived_bottom;
 
-    double **temperature;
-    double **new_temperature;
+    double *temperature;
+    double *new_temperature;
     void *sendLogs[4];
     void *ackLogs[5];
-    int iterations;
+    int work;
 
     // Constructor, initialize values
     Jacobi() {
+      usesAtSync=CmiTrue;
       int i,j;
       // allocate two dimensional arrays
-      temperature = new double*[blockDimX+2];
-      new_temperature = new double*[blockDimX+2];
-      for (i=0; i<blockDimX+2; i++) {
-       temperature[i] = new double[arrayDimY];
-       new_temperature[i] = new double[arrayDimY];
-      }
+      temperature = new double[(blockDimX+2) * arrayDimY];
+      new_temperature = new double[(blockDimX+2) * arrayDimY];
+     // for (i=0; i<blockDimX+2; i++) {
+     //   temperature[i] = new double[arrayDimY];
+     //   new_temperature[i] = new double[arrayDimY];
+     // }
       for(i=0;i<blockDimX+2; i++) {
-       for(j=0;j<arrayDimY; j++) {
-         temperature[i][j] = 0.5;
-         new_temperature[i][j] = 0.5;
-       }
+        for(j=0;j<arrayDimY; j++) {
+          temperature[index(i,j)] = 0.5;
+          new_temperature[index(i,j)] = 0.5;
+        }
       }
 
       arrived_top = 0;
       arrived_bottom = 0;
-      iterations = 0;
+
+      work = thisIndex/num_chares * 10 + 1;
+      work = 1;
       constrainBC();
     }
 
     Jacobi(CkMigrateMessage* m) {}
 
     ~Jacobi() { 
-      for (int i=0; i<blockDimX+2; i++) {
-        delete [] temperature[i];
-        delete [] new_temperature[i];
-      }
+     // for (int i=0; i<blockDimX+2; i++) {
+     //   delete [] temperature[i];
+     //   delete [] new_temperature[i];
+     // }
       delete [] temperature; 
       delete [] new_temperature; 
     }
 
+    void pup(PUP::er &p) {
+      CBase_Jacobi::pup(p);
+      if (p.isUnpacking()) {
+        temperature = new double[(blockDimX+2) * arrayDimY];
+        new_temperature = new double[(blockDimX+2) * arrayDimY];
+      }
+      p|arrived_top;
+      p|arrived_bottom;
+      p(temperature, (blockDimX+2) * arrayDimY);
+      p(new_temperature, (blockDimX+2) * arrayDimY);
+
+      p|work;
+    }
+
+    void ResumeFromSync() {
+      double max_error = 0.0;
+      contribute(sizeof(double), &max_error, CkReduction::max_double,
+          CkCallback(CkIndex_Main::report(NULL), mainProxy));
+    }
+
     // Perform one iteration of work
     void begin_iteration(void) {
-      iterations++;
-       
       // Send my top edge
-      thisProxy(wrap_y(thisIndex)).receiveGhosts(BOTTOM, arrayDimY, &temperature[1][1]);
-      // Send my bottom edge
-      thisProxy(wrap_y(thisIndex)).receiveGhosts(TOP, arrayDimY, &temperature[blockDimX][1]);
+    //  thisProxy(wrap_y(thisIndex)).receiveGhosts(BOTTOM, arrayDimY, &temperature[index(1, 1)]);
+    //  // Send my bottom edge
+    //  thisProxy(wrap_y(thisIndex)).receiveGhosts(TOP, arrayDimY, &temperature[index(blockDimX,1)]);
+    check_and_compute();
     }
 
     void receiveGhosts(int dir, int size, double gh[]) {
       int i, j;
 
       switch(dir) {
-       case TOP:
-         arrived_top++;
-         for(j=0; j<size; j++)
-            temperature[0][j+1] = gh[j];
-         break;
-       case BOTTOM:
-         arrived_bottom++;
-         for(j=0; j<size; j++)
-            temperature[blockDimX+1][j+1] = gh[j];
+        case TOP:
+          arrived_top++;
+          for(j=0; j<(size-1); j++)
+            temperature[index(0,j+1)] = gh[j];
+          break;
+        case BOTTOM:
+          arrived_bottom++;
+          for(j=0; j<(size-1); j++)
+            temperature[index(blockDimX+1,j+1)] = gh[j];
           break;
-       default:
-         CkAbort("ERROR\n");
+        default:
+          CkAbort("ERROR\n");
       }
       check_and_compute();
     }
 
+    void pause_for_lb() {
+      AtSync();
+    }
+
     void check_and_compute() {
       double error = 0.0, max_error = 0.0;
+      arrived_top = 1; arrived_bottom = 1;
 
       if (arrived_top >=1 && arrived_bottom >= 1) {
-       arrived_top--;
-       arrived_bottom--;
-
-       compute_kernel();       
-
-       for(int i=1; i<blockDimX+1; i++) {
-         for(int j=0; j<arrayDimY; j++) {
-           error = fabs(new_temperature[i][j] - temperature[i][j]);
-           if(error > max_error) {
-             max_error = error;
-           }
-         }
-       }
-
-       double **tmp;
-       tmp = temperature;
-       temperature = new_temperature;
-       new_temperature = tmp;
-
-       constrainBC();
-
-       contribute(sizeof(double), &max_error, CkReduction::max_double,
-             CkCallback(CkIndex_Main::report(NULL), mainProxy));
+        arrived_top--;
+        arrived_bottom--;
+
+        compute_kernel();      
+
+        for(int k = 0; k< work; k++) {
+          for(int i=1; i<blockDimX+1; i++) {
+            for(int j=0; j<arrayDimY; j++) {
+              error = fabs(new_temperature[index(i,j)] - temperature[index(i,j)]);
+              if(error > max_error) {
+                max_error = error;
+              }
+            }
+          }
+        }
+
+        double *tmp;
+        tmp = temperature;
+        temperature = new_temperature;
+        new_temperature = tmp;
+
+        constrainBC();
+
+        contribute(sizeof(double), &max_error, CkReduction::max_double,
+            CkCallback(CkIndex_Main::report(NULL), mainProxy));
       }
-    }
-
+    } 
     // Check to see if we have received all neighbor values yet
     // If all neighbor values have been received, we update our values and proceed
     void compute_kernel()
     {
       for(int i=1; i<blockDimX+1; i++) {
-       for(int j=0; j<arrayDimY; j++) {
-         // update my value based on the surrounding values
-         new_temperature[i][j] = (temperature[i-1][j]+temperature[i+1][j]+temperature[i][j-1]+temperature[i][j+1]+temperature[i][j]) * 0.2;
-       }
+        for(int j=0; j<arrayDimY; j++) {
+          // update my value based on the surrounding values
+          new_temperature[index(i,j)] =
+          (temperature[index(i-1,j)]+temperature[index(i+1,j)]+temperature[index(i,j-1)]+temperature[index(i,j+1)]+temperature[index(i,j)]) * 0.2;
+        }
       }
     }
 
     // Enforce some boundary conditions
     void constrainBC()
     {
-     if(thisIndex <= num_chares/2) {
-       for(int i=1; i<=blockDimX; i++)
-         temperature[i][1] = 1.0;
+      if(thisIndex <= num_chares/2) {
+        for(int i=1; i<=blockDimX; i++)
+          temperature[index(i,1)] = 1.0;
       }
 
       if(thisIndex == num_chares-1) {
-       for(int j=arrayDimY/2; j<arrayDimY; j++)
-         temperature[blockDimX][j] = 0.0;
+        for(int j=arrayDimY/2; j<arrayDimY; j++)
+          temperature[index(blockDimX,j)] = 0.0;
       }
     }
 
index e46b0ebfe958445750dd2e44d8566524cd274e1a..04a240de493dafe70da31c03cd63d6f693429d1f 100644 (file)
@@ -14,6 +14,7 @@ mainmodule jacobi1d {
     entry Jacobi(void);
     entry void begin_iteration(void);
     entry void receiveGhosts(int dir, int size, double gh[size]);
+    entry void pause_for_lb(void);
   };
 
 };
index 592dd96a728ebc556cc7eb74536e37abf7776c61..f957eb9bb38698f9f9732344418a953b27e8ca42 100644 (file)
@@ -1,5 +1,6 @@
-OPTS   = -O3
+OPTS   = -g
 CHARMC = ../../../../bin/charmc $(OPTS)
+#CHARMC        = $(HOME)/charm/bin/charmc $(OPTS)
 
 OBJS   = kNeighbor.o
 
index 58b6f1c18876d792137a578f57a615a41d36997e..3144754c0a0e854c0a0db73cbdad1115e86883c9 100644 (file)
@@ -3,6 +3,7 @@ mainmodule kNeighbor {
   readonly int num_chares;
   readonly int gMsgSize;
   readonly int gLBFreq;
+  readonly int numSteps;
 
   message toNeighborMsg {
     int data[];
index 82872b3d38e2bba1b35f83f137dfe5ee49d9f4ed..6a297f81543503c6b2be02b2ed064b0831636f0c 100644 (file)
@@ -55,8 +55,6 @@ static const char *idx2str(const CkArrayMessage *m) {
 #   define DEBUG(x)   /**/
 #endif
 
-
-
 #if CMK_LBDB_ON
 /*LBDB object handles are fixed-sized, and not necc.
 the same size as ArrayIndices.
@@ -973,6 +971,10 @@ void CkMigratable::commonInit(void) {
        usesAtSync=CmiFalse;
        usesAutoMeasure=CmiTrue;
        barrierRegistered=CmiFalse;
+  atsync_iteration = -1;
+  //CkPrintf("%s in init and off\n", idx2str(thisIndexMax));
+  local_state = OFF;
+  prev_load = 0.0;
        /*
        FAULT_EVAC
        */
@@ -1072,6 +1074,31 @@ double CkMigratable::getObjTime() {
        return myRec->getObjTime();
 }
 
+void CkMigratable::recvLBPeriod(void *data) {
+  int lb_period = *((int *) data);
+  //CkPrintf("--[pe %s] Received the LB Period %d current iter %d state %d\n",
+   //   idx2str(thisIndexMax), lb_period, atsync_iteration, local_state);
+  if (local_state == PAUSE) {
+    if (atsync_iteration < lb_period) {
+    //  CkPrintf("---[pe %s] pause and decided\n", idx2str(thisIndexMax));
+      local_state = DECIDED;
+      ResumeFromSync();
+      return;
+    }
+   // CkPrintf("---[pe %s] load balance\n", idx2str(thisIndexMax));
+    local_state = LOAD_BALANCE;
+
+    local_state = OFF;
+    atsync_iteration = -1;
+    prev_load = 0.0;
+
+    myRec->getLBDB()->AtLocalBarrier(ldBarrierHandle);
+    return;
+  }
+ // CkPrintf("---[pe %s] decided\n", idx2str(thisIndexMax));
+  local_state = DECIDED;
+}
+
 void CkMigratable::ckFinishConstruction(void)
 {
 //     if ((!usesAtSync) || barrierRegistered) return;
@@ -1086,6 +1113,7 @@ void CkMigratable::ckFinishConstruction(void)
                (LDBarrierFn)staticResumeFromSync,(void*)(this));
        barrierRegistered=CmiTrue;
 }
+
 void CkMigratable::AtSync(int waitForMigration)
 {
        if (!usesAtSync)
@@ -1096,11 +1124,47 @@ 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();
+  //   myRec->getLBDB()->AtLocalBarrier(ldBarrierHandle);
+
+  atsync_iteration++;
+  // CkPrintf("[pe %s] atsync_iter %d && predicted period %d state: %d\n",
+  //     idx2str(thisIndexMax), atsync_iteration,
+  //     myRec->getLBDB()->getPredictedLBPeriod(), local_state);
+  double tmp = prev_load;
+  prev_load = myRec->getObjTime();
+  double current_load = prev_load - tmp;
+
+  if (atsync_iteration != 0) {
+    myRec->getLBDB()->AddLoad(atsync_iteration, current_load);
+  }
+
+//
+//  if (atsync_iteration == 3) {
+//    myRec->getLBDB()->AtLocalBarrier(ldBarrierHandle);
+//    return;
+//  } else {
+//    ResumeFromSync();
+//    return;
+//  }
+
+  if (atsync_iteration < myRec->getLBDB()->getPredictedLBPeriod()) {
+    ResumeFromSync();
+  } else if (local_state == DECIDED) {
+//    CkPrintf("[pe %s] Went to load balance\n", idx2str(thisIndexMax));
+    local_state = LOAD_BALANCE;
+    local_state = OFF;
+    atsync_iteration = -1;
+    prev_load = 0.0;
+    myRec->getLBDB()->AtLocalBarrier(ldBarrierHandle);
+  } else {
+//    CkPrintf("[pe %s] Went to pause state\n", idx2str(thisIndexMax));
+    local_state = PAUSE;
+  }
 }
+
 void CkMigratable::ReadyMigrate(CmiBool ready)
 {
        myRec->ReadyMigrate(ready);
@@ -1266,6 +1330,10 @@ 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);
+}
+
 #if CMK_LBDB_ON
 void CkLocRec_local::startTiming(int ignore_running) {
        if (!ignore_running) running=CmiTrue;
@@ -1484,6 +1552,17 @@ CmiBool CkLocRec_local::deliver(CkArrayMessage *msg,CkDeliver_t type,int opts)
 }
 
 #if CMK_LBDB_ON
+
+void CkLocRec_local::staticAdaptResumeSync(LDObjHandle h, int lb_ideal_period) {
+       CkLocRec_local *el=(CkLocRec_local *)LDObjUserData(h);
+       DEBL((AA"Load balancer wants to migrate %s to %d\n"AB,idx2str(el->idx),dest));
+       el->adaptResumeSync(lb_ideal_period);
+}
+
+void CkLocRec_local::adaptResumeSync(int lb_ideal_period) {
+  informIdealLBPeriod(lb_ideal_period);
+}
+
 void CkLocRec_local::staticMigrate(LDObjHandle h, int dest)
 {
        CkLocRec_local *el=(CkLocRec_local *)LDObjUserData(h);
@@ -2534,6 +2613,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)
 {
@@ -2636,6 +2725,10 @@ 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);
+}
+
 /**
   Migrating array element is arriving on this processor.
 */
@@ -2926,6 +3019,8 @@ void CkLocMgr::initLB(CkGroupID lbdbID_)
        myCallbacks.migrate = (LDMigrateFn)CkLocRec_local::staticMigrate;
        myCallbacks.setStats = NULL;
        myCallbacks.queryEstLoad = NULL;
+  myCallbacks.adaptResumeSync =
+      (LDAdaptResumeSyncFn)CkLocRec_local::staticAdaptResumeSync;
        myLBHandle = the_lbdb->RegisterOM(myId,this,myCallbacks);
 
        // Tell the lbdb that I'm registering objects
index fd67729b1060018dcfc05726e9618fc0ee7cf476..c074b8f6ed936646dc6351cbcb2bea7900d297fa 100644 (file)
@@ -48,6 +48,8 @@ typedef enum {
        CkDeliver_inline=1  //Deliver via a regular call
 } CkDeliver_t;
 
+
+
 #include "CkLocation.decl.h"
 
 /************************** Array Messages ****************************/
@@ -173,6 +175,7 @@ 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 destroy(void); //User called destructor
   virtual ~CkLocRec_local();
 
@@ -215,6 +218,8 @@ public:
   inline LBDatabase *getLBDB(void) const {return the_lbdb;}
   inline LDObjHandle getLdHandle() const{return ldHandle;}
   static void staticMigrate(LDObjHandle h, int dest);
+  static void staticAdaptResumeSync(LDObjHandle h, int lb_ideal_period);
+  void adaptResumeSync(int lb_ideal_period);
   void recvMigrate(int dest);
   void setMigratable(int migratable);  /// set migratable
   void AsyncMigrate(CmiBool use);
@@ -271,6 +276,17 @@ 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;
+
 public:
   CkArrayIndex thisIndexMax;
 
@@ -305,6 +321,8 @@ public:
   virtual void ckAboutToMigrate(void); /*default is empty*/
   virtual void ckJustMigrated(void); /*default is empty*/
 
+  void recvLBPeriod(void *data);
+
   //used for out-of-core emulation
   virtual void ckJustRestored(void); /*default is empty*/
 
@@ -580,6 +598,7 @@ public:
 
        //Migrate us to another processor
        void emigrate(CkLocRec_local *rec,int toPe);
+  void informLBPeriod(CkLocRec_local *rec, int lb_ideal_period);
 
 #if CMK_LBDB_ON
        LBDatabase *getLBDB(void) const { return the_lbdb; }
@@ -671,6 +690,9 @@ private:
        typedef void (CkMigratable::* CkMigratable_voidfn_t)(void);
        void callMethod(CkLocRec_local *rec,CkMigratable_voidfn_t fn);
 
+       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.
diff --git a/src/ck-ldb/AdaptiveLB.C b/src/ck-ldb/AdaptiveLB.C
new file mode 100644 (file)
index 0000000..ea92b2f
--- /dev/null
@@ -0,0 +1,153 @@
+/**
+ * \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";
+
+  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;
+}
+
+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(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..98d2d7a
--- /dev/null
@@ -0,0 +1,39 @@
+/**
+ * \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;
+};
+
+#endif /* CENTRAL_ADAPTIVE_LB_H */
+
+/*@}*/
+
+
index 36456dc750116c7dac1e95bdac18fcbd482d990a..e2bc817fea7f961bf76aa00f50f4c0e0add0e883 100644 (file)
@@ -102,6 +102,12 @@ public:
     int complete_flag;         // if this ocg is complete, eg in HybridLB,
                                // this LDStats may not be complete
 
+    int is_prev_lb_refine;
+    double after_lb_max;
+    double after_lb_avg;
+    double local_comm;
+    double remote_comm;
+
     LDStats(int c=0, int complete_flag=1);
     /// the functions below should be used to obtain the number of processors
     /// instead of accessing count directly
index 22d856c778d3665102d1f9b57ceb795e7caa67a7..ba78bef06e254b0112293ddfd99bacf55fa79da3 100644 (file)
@@ -1,3 +1,4 @@
+
 /**
  * \addtogroup CkLdb
 */
@@ -10,6 +11,9 @@
 #include "LBDBManager.h"
 #include "LBSimulation.h"
 
+//#include "limits.h"
+#include <vector>
+
 #define  DEBUGF(x)       // CmiPrintf x;
 #define  DEBUG(x)        // x;
 
@@ -42,11 +46,71 @@ CkGroupID loadbalancer;
 int * lb_ptr;
 int load_balancer_created;
 
+//struct AdaptiveData {
+//  int iteration;
+//  double max_load;
+//  double avg_load;
+//};
+//
+//struct AdaptiveLBDatabase {
+//  std::vector<AdaptiveData> history_data;
+//} adaptive_lbdb;
+//
+//enum state {
+//  OFF,
+//  ON,
+//  PAUSE,
+//  DECIDED,
+//  LOAD_BALANCE
+//} local_state;
+//
+//struct AdaptiveLBStructure {
+//  int lb_ideal_period;
+//  int lb_calculated_period;
+//  int lb_no_iterations;
+//  int global_max_iter_no;
+//  int global_recv_iter_counter;
+//  bool in_progress;
+//  double prev_load;
+//  double lb_strategy_cost;
+//  double lb_migration_cost;
+//  bool lb_period_informed;
+//  int lb_msg_send_no;
+//  int lb_msg_recv_no;
+//} adaptive_struct;
+
 CreateLBFunc_Def(CentralLB, "CentralLB base class")
 
 static void getPredictedLoadWithMsg(BaseLB::LDStats* stats, int count, 
                             LBMigrateMsg *, LBInfo &info, int considerComm);
 
+//CkReductionMsg* lbDataCollection(int nMsg, CkReductionMsg** msgs) {
+//  double lb_data[4];
+//  lb_data[0] = 0;
+//  lb_data[1] = 0;
+//  lb_data[2] = 0;
+//  for (int i = 0; i < nMsg; i++) {
+//    CkAssert(msgs[i]->getSize() == 4*sizeof(double));
+//    double* m = (double *)msgs[i]->getData();
+//    lb_data[0] += m[0];
+//    lb_data[1] = ((m[1] > lb_data[1])? m[1] : lb_data[1]);
+//    lb_data[2] += m[2];
+//    if (i == 0) {
+//      lb_data[3] = m[3];
+//    }
+//    if (m[3] != lb_data[3]) {
+//      CkPrintf("Error!!! Reduction is intermingled between iteration %lf and\
+//      %lf\n", lb_data[3], m[3]);
+//    }
+//  }
+//  return CkReductionMsg::buildNew(4*sizeof(double), lb_data);
+//}
+//
+///*global*/ CkReduction::reducerType lbDataCollectionType;
+///*initcall*/ void registerLBDataCollection(void) {
+//  lbDataCollectionType = CkReduction::addReducer(lbDataCollection);
+//}
+
 /*
 void CreateCentralLB()
 {
@@ -117,6 +181,20 @@ void CentralLB::initLB(const CkLBOptions &opt)
   if (_lb_args.statsOn()) theLbdb->CollectStatsOn();
 
   load_balancer_created = 1;
+
+  // If metabalancer enabled, initialize the variables
+ // adaptive_struct.lb_ideal_period =  INT_MAX;
+ // adaptive_struct.lb_calculated_period = INT_MAX;
+ // adaptive_struct.lb_no_iterations = -1;
+ // adaptive_struct.global_max_iter_no = 0;
+ // adaptive_struct.global_recv_iter_counter = 0;
+ // adaptive_struct.in_progress = false;
+ // adaptive_struct.prev_load = 0.0;
+ // 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;
+ // local_state = OFF;
 #endif
 }
 
@@ -161,8 +239,9 @@ void CentralLB::turnOff()
 
 void CentralLB::AtSync()
 {
+//  CkPrintf("AtSync CEntral LB [%d]\n", CkMyPe());
 #if CMK_LBDB_ON
-  DEBUGF(("[%d] CentralLB AtSync step %d!!!!!\n",CkMyPe(),step()));
+//  DEBUGF(("[%d] CentralLB AtSync step %d!!!!!\n",CkMyPe(),step()));
 
 #if (defined(_FAULT_MLOG_) || defined(_FAULT_CAUSAL_))
        CpvAccess(_currentObj)=this;
@@ -183,6 +262,9 @@ void CentralLB::AtSync()
 
 void CentralLB::ProcessAtSync()
 {
+
+
+
 #if CMK_LBDB_ON
   if (reduction_started) return;              // reducton in progress
 
@@ -190,6 +272,14 @@ void CentralLB::ProcessAtSync()
   if (CkMyPe() == cur_ld_balancer) {
     start_lb_time = CkWallTimer();
   }
+ double total_load;
+ double idle_time;
+ double bg_walltime;
+ theLbdb->GetTime(&total_load,&total_load, &idle_time, &bg_walltime, &bg_walltime);
+ theLbdb->IdleTime(&idle_time);
+ CkPrintf("Total walltime [%d] %lf: %lf: %lf final laod: %lf\n", CkMyPe(),
+    total_load, idle_time, bg_walltime, (total_load - idle_time - bg_walltime));
+
 
 
 #if (defined(_FAULT_MLOG_) || defined(_FAULT_CAUSAL_))
@@ -216,6 +306,340 @@ void CentralLB::ProcessAtSync()
 #endif
 }
 
+//void CentralLB::ProcessAtSyncMin()
+//{
+//#if CMK_LBDB_ON
+//  if (reduction_started) return;              // reducton in progress
+//
+//  CmiAssert(CmiNodeAlive(CkMyPe()));
+//  if (CkMyPe() == cur_ld_balancer) {
+//    start_lb_time = CkWallTimer();
+//  }
+//
+//
+//#if (defined(_FAULT_MLOG_) || defined(_FAULT_CAUSAL_))
+//     initMlogLBStep(thisgroup);
+//#endif
+//  
+//  adaptive_struct.lb_no_iterations++;
+// // CkPrintf("[%d] ProcessAtSyncMin lb_iteration [%d] adaptive_struct.lb_ideal_period [%d]\n", CkMyPe(),
+// //     adaptive_struct.lb_no_iterations, adaptive_struct.lb_ideal_period);
+//
+//  // If decision has been made and has reached the lb_period, then do load
+//  // balancing, else if hasn't reached ideal_period, then resume.
+//  if (local_state == DECIDED) {
+//    if (adaptive_struct.lb_no_iterations < adaptive_struct.lb_ideal_period) {
+// //     CkPrintf("[%d] Decision is made but lagging\n", CkMyPe());
+//      SendMinStats();
+//      ResumeClients(0);
+//    } else {
+//      local_state = LOAD_BALANCE;
+// //     CkPrintf("[%d] Decision is made and do LB\n", CkMyPe());
+//      ProcessAtSync();
+//    }
+//    return;
+//  }
+//   
+//  // If the state is ON and not DECIDED, then if havn't reached lb_period, then
+//  // move ahead. If has reached lb_ideal_period, then change state to PAUSE and
+//  // dont resume client.
+//  if (local_state == ON) {
+//    if (adaptive_struct.lb_no_iterations < adaptive_struct.lb_ideal_period) {
+//      SendMinStats();
+//      ResumeClients(0);
+//    } else {
+//      local_state = PAUSE;
+//    }
+//    return;
+//  }
+//
+//  SendMinStats();
+//  ResumeClients(0);
+//#endif
+//}
+//
+//void CentralLB::SendMinStats() {
+//
+// double total_load;
+// double idle_time;
+// double bg_walltime;
+//  theLbdb->GetTime(&total_load,&total_load, &idle_time, &bg_walltime, &bg_walltime);
+// // CkPrintf("Total walltime [%d] %lf: %lf: %lf final laod: %lf\n", CkMyPe(), total_load, idle_time, bg_walltime, (total_load - idle_time));
+//
+//  // Since the total_load is cumulative since the last load balancing stage,
+//  // Hence it is subtracted from the previous load.
+//  total_load -= idle_time;
+//  double tmp = total_load;
+//  total_load -= adaptive_struct.prev_load;
+//  adaptive_struct.prev_load = tmp; 
+//
+//  double lb_data[4];
+//  lb_data[0] = total_load;
+//  lb_data[1] = total_load;
+//  lb_data[2] = 1;
+//  lb_data[3] = adaptive_struct.lb_no_iterations;
+//  //CkPrintf("[%d] sends total load %lf at iter %d\n", CkMyPe(), total_load, adaptive_struct.lb_no_iterations);
+//
+//  if (adaptive_struct.lb_no_iterations != 0) {
+//    CkCallback cb(CkIndex_CentralLB::ReceiveMinStats((CkReductionMsg*)NULL), 
+//        thisProxy[0]);
+////    contribute(4*sizeof(double), lb_data, lbDataCollectionType, cb);
+//  }
+//
+////    int tmp1 = adaptive_struct.lb_no_iterations;
+////    CkPrintf("[%d] contribution iteration_no: %d\n",CkMyPe(), tmp1);
+////    // Send the current iteration no
+////    CkCallback cb1(CkIndex_CentralLB::ReceiveIterationNo((CkReductionMsg*)NULL), 
+////        thisProxy[0]);
+////    contribute(sizeof(int), &tmp1, CkReduction::max_int, cb1);
+//}
+//
+//void CentralLB::ReceiveMinStats(CkReductionMsg *msg) {
+//  CmiAssert(CkMyPe() == 0);
+//  double* load = (LBRealType *) msg->getData();
+//  double max = load[1];
+//  double avg = load[0]/load[2];
+//  int iteration_n = load[3];
+//  CkPrintf("Iteration %d Total load : %lf Avg load: %lf Max load: %lf for %lf procs\n",iteration_n, load[0], load[0]/load[2], load[1], load[2]);
+//  CkPrintf("Current calculated period %d\n", adaptive_struct.lb_calculated_period);
+//  delete msg;
+//
+//  // Store the data for this iteration
+//  AdaptiveData data;
+//  data.iteration = adaptive_struct.lb_no_iterations;
+//  data.max_load = max;
+//  data.avg_load = avg;
+//  adaptive_lbdb.history_data.push_back(data);
+//
+//  // If lb period inform is in progress, dont inform again
+//  if (adaptive_struct.in_progress) {
+//    return;
+//  }
+//
+////  if (adaptive_struct.lb_period_informed) {
+////    return;
+////  }
+//
+//  // If the max/avg ratio is greater than the threshold and also this is not the
+//  // step immediately after load balancing, carry out load balancing
+//  //if (max/avg >= 1.1 && adaptive_lbdb.history_data.size() > 4) {
+//  if (max/avg >= 1.5 && adaptive_lbdb.history_data.size() > 4) {
+//    CkPrintf("Carry out load balancing step at iter max/avg(%lf) > 1.1\n", max/avg);
+////    if (!adaptive_struct.lb_period_informed) {
+////      // Just for testing
+////      adaptive_struct.lb_calculated_period = 40;
+////      adaptive_struct.lb_period_informed = true;
+////      thisProxy.LoadBalanceDecision(adaptive_struct.lb_calculated_period);
+////      return;
+////    }
+//
+//    // If the new lb period is less than current set lb period
+//    if (adaptive_struct.lb_calculated_period > iteration_n + 1) {
+//      adaptive_struct.lb_calculated_period = iteration_n + 1;
+//      adaptive_struct.lb_period_informed = true;
+//      adaptive_struct.in_progress = true;
+//      CkPrintf("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);
+//    }
+//    return;
+//  }
+//
+//  // Generate the plan for the adaptive strategy
+//  int period;
+//  if (generatePlan(period)) {
+//    //CkPrintf("Carry out load balancing step at iter\n");
+//
+//    // If the new lb period is less than current set lb period
+//    if (adaptive_struct.lb_calculated_period > period) {
+//      adaptive_struct.lb_calculated_period = period;
+//      adaptive_struct.in_progress = true;
+//      adaptive_struct.lb_period_informed = true;
+//      CkPrintf("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 CentralLB::generatePlan(int& period) {
+//  if (adaptive_lbdb.history_data.size() <= 8) {
+//    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;
+//    CkPrintf("max (%d, %lf) avg (%d, %lf)\n", i, data.max_load, i, data.avg_load);
+//  }
+////  max /= (adaptive_struct.lb_no_iterations - adaptive_lbdb.history_data[0].iteration);
+////  avg /= (adaptive_struct.lb_no_iterations - adaptive_lbdb.history_data[0].iteration);
+////
+////  adaptive_struct.lb_ideal_period = (adaptive_struct.lb_strategy_cost +
+////  adaptive_struct.lb_migration_cost) / (max - avg);
+////  CkPrintf("max : %lf, avg: %lf, strat cost: %lf, migration_cost: %lf, idealperiod : %d \n",
+////      max, avg, adaptive_struct.lb_strategy_cost, adaptive_struct.lb_migration_cost, adaptive_struct.lb_ideal_period);
+////
+//  // If linearly varying load, then find lb_period
+//  // area between the max and avg curve 
+//  double mslope, aslope, mc, ac;
+//  getLineEq(aslope, ac, mslope, mc);
+//  CkPrintf("\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);
+//  //c = -2.5;
+//  bool got_period = getPeriodForLinear(a, b, c, period);
+//  if (!got_period) {
+//    return false;
+//  }
+//  
+//  if (mslope < 0) {
+//    if (period > (-mc/mslope)) {
+//      CkPrintf("Max < 0 Period set when max load is -ve\n");
+//      return false;
+//    }
+//  }
+//
+//  if (aslope < 0) {
+//    if (period > (-ac/aslope)) {
+//      CkPrintf("Avg < 0 Period set when avg load is -ve\n");
+//      return false;
+//    }
+//  }
+//
+//  int intersection_t = (mc-ac) / (aslope - mslope);
+//  if (intersection_t > 0 && period > intersection_t) {
+//    CkPrintf("Avg | Max Period set when curves intersect\n");
+//    return false;
+//  }
+//  return true;
+//}
+//
+//bool CentralLB::getPeriodForLinear(double a, double b, double c, int& period) {
+//  CkPrintf("Quadratic Equation %lf X^2 + %lf X + %lf\n", a, b, c);
+//  if (a == 0.0) {
+//    period = (-c / b);
+//    CkPrintf("Ideal period for linear load %d\n", period);
+//    return true;
+//  }
+//  int x;
+//  double t = (b * b) - (4*a*c);
+//  if (t < 0) {
+//    CkPrintf("(b * b) - (4*a*c) is -ve sqrt : %lf\n", sqrt(t));
+//    return false;
+//  }
+//  t = (-b + sqrt(t)) / (2*a);
+//  x = t;
+//  if (x < 0) {
+//    CkPrintf("boo!!! x (%d) < 0\n", x);
+//    x = 0;
+//    return false;
+//  }
+//  period = x;
+//  CkPrintf("Ideal period for linear load %d\n", period);
+//  return true;
+//}
+//
+//bool CentralLB::getLineEq(double& aslope, double& ac, double& mslope, double& mc) {
+//  int total = adaptive_lbdb.history_data.size();
+//  int iterations = 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;
+//  }
+//  m1 /= i;
+//  a1 /= i;
+//
+//  for (i = total/2; i < total; i++) {
+//    data = adaptive_lbdb.history_data[i];
+//    m2 += data.max_load;
+//    a2 += data.avg_load;
+//  }
+//  m2 /= (i - total/2);
+//  a2 /= (i - total/2);
+//
+//  aslope = 2 * (a2 - a1) / iterations;
+//  mslope = 2 * (m2 - m1) / iterations;
+//  ac = adaptive_lbdb.history_data[0].avg_load;
+//  mc = adaptive_lbdb.history_data[0].max_load;
+//  return true;
+//}
+//
+//void CentralLB::LoadBalanceDecision(int req_no, int period) {
+//  if (req_no < adaptive_struct.lb_msg_recv_no) {
+//    CkPrintf("Error!!! Received a request which was already sent or old\n");
+//    return;
+//  }
+//  //CkPrintf("[%d] Load balance decision made cur iteration: %d period:%d state: %d\n",CkMyPe(), adaptive_struct.lb_no_iterations, period, local_state);
+//  adaptive_struct.lb_ideal_period = period;
+//  local_state = ON;
+//  adaptive_struct.lb_msg_recv_no = req_no;
+//  thisProxy[0].ReceiveIterationNo(req_no, adaptive_struct.lb_no_iterations);
+//}
+//
+//void CentralLB::LoadBalanceDecisionFinal(int req_no, int period) {
+//  if (req_no < adaptive_struct.lb_msg_recv_no) {
+//    return;
+//  }
+//  //CkPrintf("[%d] Final Load balance decision made cur iteration: %d period:%d state: %d\n",CkMyPe(), adaptive_struct.lb_no_iterations, period, local_state);
+//  adaptive_struct.lb_ideal_period = period;
+//
+//  if (local_state == ON) {
+//    local_state = DECIDED;
+//    return;
+//  }
+//
+//  // If the state is PAUSE, then its waiting for the final decision from central
+//  // processor. If the decision is that the ideal period is in the future,
+//  // resume. If the ideal period is now, then carry out load balancing.
+//  if (local_state == PAUSE) {
+//    if (adaptive_struct.lb_no_iterations < adaptive_struct.lb_ideal_period) {
+//      local_state = DECIDED;
+//      SendMinStats();
+//      ResumeClients(0);
+//    } else {
+//      local_state = LOAD_BALANCE;
+//      ProcessAtSync();
+//    }
+//    return;
+//  }
+//  CkPrintf("Error!!! Final decision received but the state is invalid %d\n", local_state);
+//}
+//
+//
+//void CentralLB::ReceiveIterationNo(int req_no, int local_iter_no) {
+//  CmiAssert(CkMyPe() == 0);
+//
+//  adaptive_struct.global_recv_iter_counter++;
+//  if (local_iter_no > adaptive_struct.global_max_iter_no) {
+//    adaptive_struct.global_max_iter_no = local_iter_no;
+//  }
+//  if (CkNumPes() == adaptive_struct.global_recv_iter_counter) {
+//    adaptive_struct.lb_ideal_period = (adaptive_struct.lb_ideal_period > adaptive_struct.global_max_iter_no) ? adaptive_struct.lb_ideal_period : adaptive_struct.global_max_iter_no + 1;
+//    thisProxy.LoadBalanceDecisionFinal(req_no, adaptive_struct.lb_ideal_period);
+//    CkPrintf("Final lb_period %d\n", adaptive_struct.lb_ideal_period);
+//    adaptive_struct.in_progress = false;
+//    adaptive_struct.global_max_iter_no = 0;
+//    adaptive_struct.global_recv_iter_counter = 0;
+//  }
+//}
+
 // called only on 0
 void CentralLB::ReceiveCounts(CkReductionMsg  *msg)
 {
@@ -288,6 +712,7 @@ void CentralLB::BuildStatsMsg()
 #endif
 }
 
+
 // called on every processor
 void CentralLB::SendStats()
 {
@@ -770,6 +1195,7 @@ void CentralLB::ReceiveMigration(LBMigrateMsg *m)
   CkCallback cb(CkIndex_CentralLB::ProcessReceiveMigration((CkReductionMsg*)NULL),
                   thisProxy);
   contribute(0, NULL, CkReduction::max_int, cb);
+
 #endif
 }
 
@@ -986,6 +1412,7 @@ void CentralLB::ResumeClients(int balancing)
 
   theLbdb->ResumeClients();
   if (balancing)  {
+
     CheckMigrationComplete();
     if (future_migrates_expected == 0 || 
             future_migrates_expected == future_migrates_completed) {
@@ -1014,9 +1441,15 @@ void CentralLB::CheckMigrationComplete()
                 lbname, cur_ld_balancer, step()-1, end_lb_time,
                end_lb_time-start_lb_time);
     }
+
+    //FIX ME!!! adaptive_struct.lb_migration_cost = (CkWallTimer() - start_lb_time);
+    theLbdb->SetMigrationCost(CkWallTimer() - 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;
@@ -1066,8 +1499,10 @@ 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);
+    // FIX ME!!! adaptive_struct.lb_strategy_cost = (strat_end_time - strat_start_time);
+    //CkPrintf("Strategy cost %f %f %f\n", strat_end_time, strat_start_time, adaptive_struct.lb_strategy_cost);
+    theLbdb->SetStrategyCost(strat_end_time - strat_start_time);
   }
-
   return msg;
 #else
   return NULL;
index 92806016babd64a12f95c112b23dee8d9939c311..4988c848d2440d91299343f04112be43cba3b617 100644 (file)
@@ -11,19 +11,28 @@ readonly CkGroupID loadbalancer;
 
 initnode void lbinit(void);
 
+//initcall void registerLBDataCollection(void);
+
 group [migratable] CentralLB : BaseLB {
   entry void CentralLB(const CkLBOptions &);  
+ // entry [immediate] void ProcessAtSyncMin(void);
   entry void ProcessAtSync(void);
   entry void SendStats();
+ // entry [immediate] void SendMinStats();
   entry void ReceiveStats(CkMarshalledCLBStatsMessage data);
+ // entry [immediate] void ReceiveMinStats(CkReductionMsg *msg);
   entry void ReceiveStatsViaTree(CkMarshalledCLBStatsMessage data);
   entry void ReceiveCounts(CkReductionMsg *);
+ // entry [immediate] void LoadBalanceDecision(int req_no, int period);
+ // entry [immediate] void LoadBalanceDecisionFinal(int req_no, int period);
+ // entry [immediate] void ReceiveIterationNo(int, int);
   entry void LoadBalance(void);
   entry void ResumeClients(int);
   entry void ResumeClients(CkReductionMsg *);
   entry void ReceiveMigration(LBMigrateMsg*);  
   entry void ProcessReceiveMigration(CkReductionMsg  *);
   entry void MissMigrate(int);
+
 };
 
 };
index 0d70342590dc44c9abb365803aeae93929ca8970..31e0d5a3f6fc4b2555823aec353600c6f8d85086 100644 (file)
@@ -84,17 +84,23 @@ 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 ProcessAtSyncMin(void);
   void SendStats();
+  //void SendMinStats();
   void ReceiveCounts(CkReductionMsg *);
+  //void ReceiveMinStats(CkReductionMsg *);
   void ReceiveStats(CkMarshalledCLBStatsMessage &msg); // Receive stats on PE 0
   void ReceiveStatsViaTree(CkMarshalledCLBStatsMessage &msg); // Receive stats using a tree structure  
   
   void depositData(CLBStatsMsg *m);
   void LoadBalance(void); 
   void ResumeClients(int);                      // Resuming clients needs
-                                               // to be resumed via message
-  void ResumeClients(CkReductionMsg *);
+
+ // void LoadBalanceDecision(int, int);
+ // void LoadBalanceDecisionFinal(int, int);
+ // void ReceiveIterationNo(int, int); // Receives the current iter no
+
+  void ResumeClients(CkReductionMsg *); // to be resumed via message
   void ReceiveMigration(LBMigrateMsg *);       // Receive migration data
   void ProcessReceiveMigration(CkReductionMsg  *);
 #if (defined(_FAULT_MLOG_) || defined(_FAULT_CAUSAL_))
@@ -233,6 +239,24 @@ protected:
                       LBMigrateMsg* msg, LBSimulation* simResults);
   void removeNonMigratable(LDStats* statsDataList, int count);
 
+  virtual void UpdateLBDBWithData(int is_prev_lb_refine, double lb_max,
+      double lb_avg, double local_comm, double remote_comm) {
+    theLbdb->UpdateAfterLBData(is_prev_lb_refine, lb_max, lb_avg, local_comm,
+        remote_comm);
+  }
+
+  virtual void GetPrevLBData(int& is_prev_lb_refine, double& lb_max_avg_ratio,
+      double& local_remote_comm_ratio) {
+    theLbdb->GetPrevLBData(is_prev_lb_refine, lb_max_avg_ratio,
+        local_remote_comm_ratio);
+  }
+
+  virtual void GetLBDataForLB(int prev_lb, double& lb_max_avg_ratio, double&
+      local_remote_comm_ratio) {
+    theLbdb->GetLBDataForLB(prev_lb, lb_max_avg_ratio, local_remote_comm_ratio);
+  }
+
+
 private:  
   CProxy_CentralLB thisProxy;
   int myspeed;
@@ -248,10 +272,14 @@ private:
   LBMigrateMsg   *storedMigrateMsg;
   int  reduction_started;
 
+
   FutureModel *predicted_model;
 
   void BuildStatsMsg();
   void buildStats();
+  bool generatePlan(int& period);
+  bool getLineEq(double& aslope, double& ac, double& mslope, double& mc);
+  bool getPeriodForLinear(double a, double b, double c, int& period);
 
 public:
   int useMem();
index 06a128541bc2780c313d4d700384e518f72ec667..aba514543cba5615a3ebb722929885760f73314e 100644 (file)
@@ -57,12 +57,16 @@ void GreedyLB::work(LDStats* stats)
   int n_pes = stats->nprocs();
   int *map = new int[n_pes];
 
+  ProcArray *parr = new ProcArray(stats);
+  double bg_load = 0.0;
+
   std::vector<ProcInfo>  procs;
   for(pe = 0; pe < n_pes; pe++) {
     map[pe] = -1;
     if (stats->procs[pe].available) {
       map[pe] = procs.size();
       procs.push_back(ProcInfo(pe, stats->procs[pe].bg_walltime, 0.0, stats->procs[pe].pe_speed, true));
+      bg_load = stats->procs[pe].bg_walltime;
     }
   }
 
@@ -86,6 +90,16 @@ void GreedyLB::work(LDStats* stats)
     procs[pe].totalLoad() *= procs[pe].pe_speed();
   }
 
+  double max_load = 0;
+  double avg_load = 0;
+  for (pe = 0; pe<parr->procs.size(); pe++) {
+    if (parr->procs[pe].totalLoad() > max_load) {
+      max_load = parr->procs[pe].totalLoad();
+    }
+    avg_load += parr->procs[pe].totalLoad();
+  }
+  CkPrintf("Before GreedyLB max load: %lf avg load: %lf bg load: %lf\n", max_load, avg_load/procs.size(), bg_load/procs.size());
+
   // build object array
   std::vector<Vertex> objs;
 
@@ -140,6 +154,16 @@ void GreedyLB::work(LDStats* stats)
   if (_lb_args.debug()>0) 
     CkPrintf("[%d] %d objects migrating.\n", CkMyPe(), nmoves);
 
+  max_load = 0;
+  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();
+  }
+  CkPrintf("GreedyLB> After lb max load: %lf avg load: %lf\n", max_load, avg_load/procs.size());
+
   if (_lb_args.debug()>1)  {
     CkPrintf("CharmLB> Min obj: %f  Max obj: %f\n", objs[objs.size()-1].getVertexLoad(), objs[0].getVertexLoad());
     CkPrintf("CharmLB> PE speed:\n");
@@ -152,6 +176,10 @@ void GreedyLB::work(LDStats* stats)
     CkPrintf("\n");
   }
 
+  stats->after_lb_max = max_load;
+  stats->after_lb_avg = avg_load/procs.size();
+  stats->is_prev_lb_refine = 0;
+
 }
 
 #include "GreedyLB.def.h"
index f13d0200768bd84ae8d6a1c9fd420895ac8b8db7..253a262b24e9180fdc19be516c792aa32322a94c 100644 (file)
@@ -324,6 +324,17 @@ int LBDB::Migrate(LDObjHandle h, int dest)
   return 1;
 }
 
+void LBDB::AdaptResumeSync(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->AdaptResumeSync(h, lb_ideal_period);
+    }
+  }
+}
+
 void LBDB::Migrated(LDObjHandle h, int waitBarrier)
 {
   // Object migrated, inform load balancers
@@ -338,6 +349,7 @@ void LBDB::Migrated(LDObjHandle h, int waitBarrier)
   
 }
 
+
 int LBDB::NotifyMigrated(LDMigratedFn fn, void* data)
 {
   // Save migration function
index 5c6236f10c7a048cd9ef067971f54c861e9ad1c9..7870209caacf74b912ab0085dd705afc9232f7e5 100644 (file)
@@ -78,6 +78,8 @@ public:
   void insert(LBOM *om);
 
   LDOMHandle AddOM(LDOMid _userID, void* _userData, LDCallbacks _callbacks);
+  
+
   LDObjHandle AddObj(LDOMHandle _h, LDObjid _id, void *_userData,
                     CmiBool _migratable);
   void UnregisterObj(LDObjHandle _h);
@@ -136,6 +138,7 @@ public:
   inline void GetCommData(LDCommData *data) 
        { if (commTable) commTable->GetCommData(data); };
 
+  void AdaptResumeSync(int lb_ideal_period);
   int  Migrate(LDObjHandle h, int dest);
   void Migrated(LDObjHandle h, int waitBarrier=1);
   int  NotifyMigrated(LDMigratedFn fn, void* data);
index 5ff8559ef4b3d5d2316d2892af57c87e3f6ebab1..0db4e75d6fcfbde3b40989bf31edc3a2773db063 100644 (file)
 #include "LBSimulation.h"
 #include "topology.h"
 
+#include "limits.h"
+
 #include "NullLB.h"
 
+#define VEC_SIZE 500
+#define IMB_TOLERANCE 1.1
+#define IDLE_LOAD_TOLERANCE 0.3
+
+struct AdaptiveData {
+  int iteration;
+  double max_load;
+  double avg_load;
+  double max_idle_load_ratio;
+  double idle_time;
+};
+
+struct AdaptiveLBDatabase {
+  std::vector<AdaptiveData> history_data;
+} adaptive_lbdb;
+
+struct AdaptiveLBInfo {
+  double max_avg_ratio;
+  double local_remote_ratio;
+};
+
+struct AdaptiveLBStructure {
+  int lb_ideal_period;
+  int lb_calculated_period;
+  int lb_no_iterations;
+  int global_max_iter_no;
+  int global_recv_iter_counter;
+  bool in_progress;
+  double lb_strategy_cost;
+  double lb_migration_cost;
+  bool lb_period_informed;
+  bool doCommStrategy;
+  int lb_msg_send_no;
+  int lb_msg_recv_no;
+  int total_syncs_called;
+  int last_lb_type;
+  AdaptiveLBInfo greedy_info;
+  AdaptiveLBInfo refine_info;
+  AdaptiveLBInfo comm_info;
+  AdaptiveLBInfo comm_refine_info;
+} adaptive_struct;
+
+
+CkReductionMsg* lbDataCollection(int nMsg, CkReductionMsg** msgs) {
+  double lb_data[6];
+  lb_data[1] = 0.0;
+  lb_data[2] = 0.0;
+  lb_data[3] = 0.0;
+  lb_data[4] = 0.0;
+  lb_data[5] = 0.0;
+  for (int i = 0; i < nMsg; i++) {
+    CkAssert(msgs[i]->getSize() == 6*sizeof(double));
+    if (msgs[i]->getSize() != 6*sizeof(double)) {
+      CkPrintf("Error!!! Reduction not correct. Msg size is %d\n", msgs[i]->getSize());
+    }
+    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];
+    // Max idle
+    lb_data[5] = ((m[5] > lb_data[5]) ? m[5] : lb_data[5]);
+    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]);
+    }
+  }
+  return CkReductionMsg::buildNew(6*sizeof(double), lb_data);
+}
+
+/*global*/ CkReduction::reducerType lbDataCollectionType;
+/*initcall*/ void registerLBDataCollection(void) {
+  lbDataCollectionType = CkReduction::addReducer(lbDataCollection);
+}
+
 CkGroupID _lbdb;
 
 CkpvDeclare(int, numLoadBalancers);  /**< num of lb created */
@@ -101,6 +186,9 @@ LBAllocFn getLBAllocFn(char *lbname) {
     return lbRegistry.getLBAllocFn(lbname);
 }
 
+LBCreateFn getLBCreateFn(const char *lbname) {
+    return lbRegistry.search(lbname);
+}
 // create a load balancer group using the strategy name
 static void createLoadBalancer(const char *lbname)
 {
@@ -330,6 +418,7 @@ void LBDatabase::initnodeFn()
 // called my constructor
 void LBDatabase::init(void) 
 {
+  //thisProxy = CProxy_LBDatabase(thisgroup);
   myLDHandle = LDCreate();
   mystep = 0;
   nloadbalancers = 0;
@@ -339,6 +428,27 @@ void LBDatabase::init(void)
 #if CMK_LBDB_ON
   if (manualOn) TurnManualLBOn();
 #endif
+  
+  max_load_vec.resize(VEC_SIZE, 0.0);
+  total_load_vec.resize(VEC_SIZE, 0.0);
+  total_contrib_vec.resize(VEC_SIZE, 0.0);
+  max_iteration = -1;
+
+  // If metabalancer enabled, initialize the variables
+  adaptive_struct.lb_ideal_period =  INT_MAX;
+  adaptive_struct.lb_calculated_period = INT_MAX;
+  adaptive_struct.lb_no_iterations = -1;
+  adaptive_struct.global_max_iter_no = 0;
+  adaptive_struct.global_recv_iter_counter = 0;
+  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;
+
+  is_prev_lb_refine = -1;
 }
 
 LBDatabase::LastLBInfo::LastLBInfo()
@@ -467,6 +577,447 @@ void LBDatabase::EstObjLoad(const LDObjHandle &_h, double cputime)
 #endif
 }
 
+void LBDatabase::ResumeClients() {
+  // If metabalancer enabled, initialize the variables
+  adaptive_lbdb.history_data.clear();
+
+  adaptive_struct.lb_ideal_period =  INT_MAX;
+  adaptive_struct.lb_calculated_period = INT_MAX;
+  adaptive_struct.lb_no_iterations = -1;
+  adaptive_struct.global_max_iter_no = 0;
+  adaptive_struct.global_recv_iter_counter = 0;
+  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;
+  
+  max_load_vec.clear();
+  total_load_vec.clear();
+  total_contrib_vec.clear();
+
+  max_load_vec.resize(VEC_SIZE, 0.0);
+  total_load_vec.resize(VEC_SIZE, 0.0);
+  total_contrib_vec.resize(VEC_SIZE, 0.0);
+
+  LDResumeClients(myLDHandle);
+}
+
+bool LBDatabase::AddLoad(int iteration, double load) {
+  total_contrib_vec[iteration]++;
+  adaptive_struct.total_syncs_called++;
+  //CkPrintf("At PE %d Total contribution for iteration %d is %lf total objs %d\n", CkMyPe(), iteration,
+  //total_contrib_vec[iteration], getLBDB()->ObjDataCount());
+
+  if (iteration > adaptive_struct.lb_no_iterations) {
+    adaptive_struct.lb_no_iterations = iteration;
+  }
+  total_load_vec[iteration] += load;
+ // if (max_load_vec[iteration] < load) {
+ //   max_load_vec[iteration] = load;
+ // }
+  if (total_contrib_vec[iteration] == getLBDB()->ObjDataCount()) {
+    double idle_time;
+    IdleTime(&idle_time);
+    //CkPrintf("[%d] Idle time %lf for iteration %d\n", CkMyPe(), idle_time, iteration);
+    // Skips the 0th iteration collection of stats hence...
+    idle_time = idle_time * getLBDB()->ObjDataCount() /
+       (adaptive_struct.total_syncs_called + getLBDB()->ObjDataCount());
+
+    double lb_data[6];
+    lb_data[0] = iteration;
+    lb_data[1] = 1;
+    lb_data[2] = total_load_vec[iteration];
+    //lb_data[2] = max_load_vec[iteration];
+    lb_data[3] = total_load_vec[iteration];
+    //lb_data[3] = getLBDB()->ObjDataCount();
+    lb_data[4] = idle_time;
+    if (total_load_vec[iteration] == 0.0) {
+      lb_data[5] = idle_time;
+    } else {
+      lb_data[5] = idle_time/total_load_vec[iteration];
+    }
+
+   // CkPrintf("[%d] sends total load %lf idle time %lf ratio of idle/load %lf at iter %d\n", CkMyPe(),
+   //     total_load_vec[iteration], idle_time,
+   //     idle_time/total_load_vec[iteration], adaptive_struct.lb_no_iterations);
+
+    CkCallback cb(CkIndex_LBDatabase::ReceiveMinStats((CkReductionMsg*)NULL), thisProxy[0]);
+    contribute(6*sizeof(double), lb_data, lbDataCollectionType, cb);
+  }
+  return true;
+}
+
+void LBDatabase::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 max_idle_load_ratio = load[5];
+  int iteration_n = load[0];
+  CkPrintf("** [%d] Iteration Avg load: %lf Max load: %lf Avg Idle : %lf Max Idle : %lf for %lf procs\n",iteration_n, avg, max, avg_idle, max_idle_load_ratio, load[1]);
+  delete msg;
+  // Store the data for this iteration
+  adaptive_struct.lb_no_iterations = iteration_n;
+  AdaptiveData data;
+  data.iteration = adaptive_struct.lb_no_iterations;
+  data.max_load = max;
+  data.avg_load = avg;
+  data.max_idle_load_ratio = max_idle_load_ratio;
+  data.idle_time = avg_idle;
+  adaptive_lbdb.history_data.push_back(data);
+
+  // If lb period inform is in progress, dont inform again
+  if (adaptive_struct.in_progress) {
+    return;
+  }
+
+//  if (adaptive_struct.lb_period_informed) {
+//    return;
+//  }
+
+  // If the max/avg ratio is greater than the threshold and also this is not the
+  // step immediately after load balancing, carry out load balancing
+  //if (max/avg >= 1.1 && adaptive_lbdb.history_data.size() > 4) {
+  int tmp1;
+  double tmp2, tmp3;
+  GetPrevLBData(tmp1, tmp2, tmp3);
+  double tolerate_imb = IMB_TOLERANCE * tmp2;
+
+  if ((max_idle_load_ratio >= IDLE_LOAD_TOLERANCE || max/avg >= tolerate_imb) && adaptive_lbdb.history_data.size() > 4) {
+    CkPrintf("Carry out load balancing step at iter max/avg(%lf) and max_idle_load_ratio ratio (%lf)\n", max/avg, max_idle_load_ratio);
+//    if (!adaptive_struct.lb_period_informed) {
+//      // Just for testing
+//      adaptive_struct.lb_calculated_period = 40;
+//      adaptive_struct.lb_period_informed = true;
+//      thisProxy.LoadBalanceDecision(adaptive_struct.lb_calculated_period);
+//      return;
+//    }
+
+
+
+    // If the new lb period is less than current set lb period
+    if (adaptive_struct.lb_calculated_period > iteration_n + 1) {
+      if (max/avg < tolerate_imb) {
+        adaptive_struct.doCommStrategy = true;
+        CkPrintf("No load imbalance but idle time\n");
+      } else {
+        adaptive_struct.doCommStrategy = false;
+        CkPrintf("load imbalance \n");
+      }
+      adaptive_struct.lb_calculated_period = iteration_n + 1;
+      adaptive_struct.lb_period_informed = true;
+      adaptive_struct.in_progress = true;
+      CkPrintf("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);
+    }
+    return;
+  }
+
+  // Generate the plan for the adaptive strategy
+  int period;
+  if (generatePlan(period)) {
+    //CkPrintf("Carry out load balancing step at iter\n");
+
+    // If the new lb period is less than current set lb period
+    if (adaptive_struct.lb_calculated_period > period) {
+      adaptive_struct.doCommStrategy = false;
+      adaptive_struct.lb_calculated_period = period;
+      adaptive_struct.in_progress = true;
+      adaptive_struct.lb_period_informed = true;
+      CkPrintf("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 LBDatabase::generatePlan(int& period) {
+  if (adaptive_lbdb.history_data.size() <= 8) {
+    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;
+    CkPrintf("max (%d, %lf) avg (%d, %lf)\n", i, data.max_load, i, data.avg_load);
+  }
+//  max /= (adaptive_struct.lb_no_iterations - adaptive_lbdb.history_data[0].iteration);
+//  avg /= (adaptive_struct.lb_no_iterations - adaptive_lbdb.history_data[0].iteration);
+//
+//  adaptive_struct.lb_ideal_period = (adaptive_struct.lb_strategy_cost +
+//  adaptive_struct.lb_migration_cost) / (max - avg);
+//  CkPrintf("max : %lf, avg: %lf, strat cost: %lf, migration_cost: %lf, idealperiod : %d \n",
+//      max, avg, adaptive_struct.lb_strategy_cost, adaptive_struct.lb_migration_cost, adaptive_struct.lb_ideal_period);
+//
+
+  // 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 tmp1;
+  double tmp2, tmp3;
+  GetPrevLBData(tmp1, tmp2, tmp3);
+  
+  double tolerate_imb = tmp2;
+  if (max/avg < tolerate_imb) {
+    tolerate_imb = 1.0;
+  }
+
+  return getPeriodForStrategy(tolerate_imb, 1, period);
+
+//  int refine_period, scratch_period;
+//  bool obtained_refine, obtained_scratch;
+//  obtained_refine = getPeriodForStrategy(1, 1, refine_period);
+//  obtained_scratch = getPeriodForStrategy(1, 1, scratch_period);
+//
+//  if (obtained_refine) {
+//    if (!obtained_scratch) {
+//      period = refine_period;
+//      adaptive_struct.isRefine = true;
+//      return true;
+//    }
+//    if (scratch_period < 1.1*refine_period) {
+//      adaptive_struct.isRefine = false;
+//      period = scratch_period;
+//      return true;
+//    }
+//    period = refine_period;
+//    adaptive_struct.isRefine = true;
+//    return true;
+//  }
+//
+//  if (obtained_scratch) {
+//    period = scratch_period;
+//    adaptive_struct.isRefine = false;
+//    return true;
+//  }
+//  return false;
+}
+
+bool LBDatabase::getPeriodForStrategy(double new_load_percent, double overhead_percent, int& period) {
+  double mslope, aslope, mc, ac;
+  getLineEq(new_load_percent, aslope, ac, mslope, mc);
+  CkPrintf("new load percent %lf\n", new_load_percent);
+  CkPrintf("\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;
+  //c = -2.5;
+  bool got_period = getPeriodForLinear(a, b, c, period);
+  if (!got_period) {
+    return false;
+  }
+  
+  if (mslope < 0) {
+    if (period > (-mc/mslope)) {
+      CkPrintf("Max < 0 Period set when max load is -ve\n");
+      return false;
+    }
+  }
+
+  if (aslope < 0) {
+    if (period > (-ac/aslope)) {
+      CkPrintf("Avg < 0 Period set when avg load is -ve\n");
+      return false;
+    }
+  }
+
+  int intersection_t = (mc-ac) / (aslope - mslope);
+  if (intersection_t > 0 && period > intersection_t) {
+    CkPrintf("Avg | Max Period set when curves intersect\n");
+    return false;
+  }
+  return true;
+}
+
+bool LBDatabase::getPeriodForLinear(double a, double b, double c, int& period) {
+  CkPrintf("Quadratic Equation %lf X^2 + %lf X + %lf\n", a, b, c);
+  if (a == 0.0) {
+    period = (-c / b);
+    CkPrintf("Ideal period for linear load %d\n", period);
+    return true;
+  }
+  int x;
+  double t = (b * b) - (4*a*c);
+  if (t < 0) {
+    CkPrintf("(b * b) - (4*a*c) is -ve sqrt : %lf\n", sqrt(t));
+    return false;
+  }
+  t = (-b + sqrt(t)) / (2*a);
+  x = t;
+  if (x < 0) {
+    CkPrintf("boo!!! x (%d) < 0\n", x);
+    x = 0;
+    return false;
+  }
+  period = x;
+  CkPrintf("Ideal period for linear load %d\n", period);
+  return true;
+}
+
+bool LBDatabase::getLineEq(double new_load_percent, double& aslope, double& ac, double& mslope, double& mc) {
+  int total = adaptive_lbdb.history_data.size();
+  int iterations = 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;
+  }
+  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;
+  }
+  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 = (adaptive_lbdb.history_data[1].avg_load * new_load_percent - aslope);
+  //mc = (adaptive_lbdb.history_data[1].max_load - mslope);
+
+  return true;
+}
+
+void LBDatabase::LoadBalanceDecision(int req_no, int period) {
+  if (req_no < adaptive_struct.lb_msg_recv_no) {
+    CkPrintf("Error!!! Received a request which was already sent or old\n");
+    return;
+  }
+  //CkPrintf("[%d] Load balance decision made cur iteration: %d period:%d state: %d\n",CkMyPe(), adaptive_struct.lb_no_iterations, period, local_state);
+  adaptive_struct.lb_ideal_period = period;
+  //local_state = ON;
+  adaptive_struct.lb_msg_recv_no = req_no;
+  thisProxy[0].ReceiveIterationNo(req_no, adaptive_struct.lb_no_iterations);
+}
+
+void LBDatabase::LoadBalanceDecisionFinal(int req_no, int period) {
+  if (req_no < adaptive_struct.lb_msg_recv_no) {
+    return;
+  }
+//  CkPrintf("[%d] Final Load balance decision made cur iteration: %d period:%d \n",CkMyPe(), adaptive_struct.lb_no_iterations, period);
+  adaptive_struct.lb_ideal_period = period;
+  LDOMAdaptResumeSync(myLDHandle, period);
+
+//  if (local_state == ON) {
+//    local_state = DECIDED;
+//    return;
+//  }
+
+  // If the state is PAUSE, then its waiting for the final decision from central
+  // processor. If the decision is that the ideal period is in the future,
+  // resume. If the ideal period is now, then carry out load balancing.
+//  if (local_state == PAUSE) {
+//    if (adaptive_struct.lb_no_iterations < adaptive_struct.lb_ideal_period) {
+//      local_state = DECIDED;
+//      //SendMinStats();
+//      //FIX ME!!! ResumeClients(0);
+//    } else {
+//      local_state = LOAD_BALANCE;
+//      //FIX ME!!! ProcessAtSync();
+//    }
+//    return;
+//  }
+//  CkPrintf("Error!!! Final decision received but the state is invalid %d\n", local_state);
+}
+
+
+void LBDatabase::ReceiveIterationNo(int req_no, int local_iter_no) {
+  CmiAssert(CkMyPe() == 0);
+
+  adaptive_struct.global_recv_iter_counter++;
+  if (local_iter_no > adaptive_struct.global_max_iter_no) {
+    adaptive_struct.global_max_iter_no = local_iter_no;
+  }
+  if (CkNumPes() == adaptive_struct.global_recv_iter_counter) {
+    adaptive_struct.lb_ideal_period = (adaptive_struct.lb_ideal_period > adaptive_struct.global_max_iter_no) ? adaptive_struct.lb_ideal_period : adaptive_struct.global_max_iter_no + 1;
+    thisProxy.LoadBalanceDecisionFinal(req_no, adaptive_struct.lb_ideal_period);
+    CkPrintf("Final lb_period %d\n", adaptive_struct.lb_ideal_period);
+    adaptive_struct.in_progress = false;
+    adaptive_struct.global_max_iter_no = 0;
+    adaptive_struct.global_recv_iter_counter = 0;
+  }
+}
+
+int LBDatabase::getPredictedLBPeriod() {
+  return adaptive_struct.lb_ideal_period;
+}
+
+bool LBDatabase::isStrategyComm() {
+  return adaptive_struct.doCommStrategy;
+}
+
+void LBDatabase::SetMigrationCost(double lb_migration_cost) {
+  adaptive_struct.lb_migration_cost = lb_migration_cost;
+}
+
+void LBDatabase::SetStrategyCost(double lb_strategy_cost) {
+  adaptive_struct.lb_strategy_cost = lb_strategy_cost;
+}
+
+void LBDatabase::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.local_remote_ratio = local_comm/remote_comm;
+  } else if (lb == 3) {
+    adaptive_struct.comm_refine_info.local_remote_ratio =
+    local_comm/remote_comm;
+  }
+}
+
+void LBDatabase::GetPrevLBData(int& lb_type, double& lb_max_avg_ratio, double&
+    local_remote_comm_ratio) {
+  lb_type = adaptive_struct.last_lb_type;
+  lb_max_avg_ratio = 1;
+  local_remote_comm_ratio = 1;
+  GetLBDataForLB(lb_type, lb_max_avg_ratio, local_remote_comm_ratio);
+}
+
+void LBDatabase::GetLBDataForLB(int lb_type, double& lb_max_avg_ratio, double&
+    local_remote_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) {
+    local_remote_comm_ratio = adaptive_struct.comm_info.local_remote_ratio;
+  } else if (lb_type == 3) {
+    local_remote_comm_ratio =
+       adaptive_struct.comm_refine_info.local_remote_ratio;
+  }
+}
+
 /*
   callable from user's code
 */
index 4cf9425eb7fdb4c2b4743eddb1b459e65f693d89..b597a8d050a3f9ebf6d78dbb3473aa8f3aabfdeb 100644 (file)
@@ -8,9 +8,15 @@ module LBDatabase {
     entry LBDBInit(CkArgMsg *m);
   };
 
+  initcall void registerLBDataCollection(void);
   group [migratable] LBDatabase {
     entry void LBDatabase(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, int);
+  }
 
 };
index 9b02f0d67c03076ad8e0db0d97f2de2ec3228b7e..9c7f048fd6a64086c5a9a3fdcc3322170c9bbe43 100644 (file)
@@ -6,14 +6,21 @@
 #ifndef LBDATABASE_H
 #define LBDATABASE_H
 
+
+//#include <charm++.h>
+//#include "ckreduction.h" 
 #include "lbdb.h"
 #include "LBDBManager.h"
 #include "lbdb++.h"
 
+#include <vector>
+
 #define LB_FORMAT_VERSION     2
 
 extern int _lb_version;
 
+
+
 // command line options
 class CkLBArgs
 {
@@ -161,7 +168,7 @@ class DefaultFunction : public LBPredictorFunction {
 };
 
 
-class LBDatabase : public IrrGroup {
+class LBDatabase : public CBase_LBDatabase {
 public:
   LBDatabase(void)  { init(); }
   LBDatabase(CkMigrateMessage *m)  { init(); }
@@ -321,7 +328,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);
@@ -342,19 +351,53 @@ public:
   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);}
 
+  bool AddLoad(int iteration, double load);
+  void ReceiveMinStats(CkReductionMsg *);
+  void LoadBalanceDecision(int, int);
+  void LoadBalanceDecisionFinal(int, int);
+  void ReceiveIterationNo(int, int); // Receives the current iter no
+
+  bool generatePlan(int& period);
+  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);
+  int getPredictedLBPeriod();
+
+  bool isStrategyComm();
+
+  void UpdateAfterLBData(int is_lb_refine, double lb_max, double lb_avg, double
+      local_comm, double remote_comm);
+  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_LBDatabase thisProxy;
   int mystep;
   LDHandle myLDHandle;
   static char *avail_vector;   // processor bit vector
   int new_ld_balancer;         // for Node 0
   CkVec<BaseLB *>   loadbalancers;
   int nloadbalancers;
+  std::vector<double> max_load_vec;
+  std::vector<double> total_load_vec;
+  std::vector<double> total_contrib_vec;
+  std::vector<int> total_msg_vec;
+  std::vector<int> total_bytes_vec;
+  int max_iteration;
+
+  double after_lb_max;
+  double after_lb_avg;
+  int is_prev_lb_refine;
 
 public:
   BaseLB** getLoadBalancers() {return loadbalancers.getVec();}
index 478b3aae283b47aeb7d91d23796afd10b83ac906..4d61d5605e755e71d43da9d91339b86405c78981 100644 (file)
@@ -35,6 +35,9 @@ private:
 
   void DepositHandle(LDOMHandle _h) { myhandle = _h; };
   void Migrate(LDObjHandle _h, int dest) { callbacks.migrate(_h,dest); };
+  void AdaptResumeSync(LDObjHandle _h, int lb_ideal_period) {
+    callbacks.adaptResumeSync(_h, lb_ideal_period);
+  }
   CmiBool RegisteringObjs() { return registering_objs; };
   void SetRegisteringObjs(CmiBool _set) { registering_objs = _set; };
 
index 9c7b7338e23877dfd1b307f7d1ee979102f8d8e4..6061cd0c5c825da32e0931299074358cc0529259 100644 (file)
 
 #include "MetisLB.h"
 #include "ckgraph.h"
-#include "metis.h"
+//#include "metis.h"
 
-/*extern "C" void METIS_PartGraphRecursive(int*, int*, int*, int*, int*,
+typedef int idxtype;
+
+extern "C" void METIS_PartGraphRecursive(int*, int*, int*, int*, int*,
                              int*, int*, int*, int*, int*, int*);
 extern "C" void METIS_PartGraphKway(int*, int*, int*, int*, int*,
                               int*, int*, int*, int*, int*, int*);
@@ -31,7 +33,7 @@ extern "C" void METIS_mCPartGraphRecursive(int*, int*, int*, int*, int*, int*,
                              int*, int*, int*, int*, int*, int*);
 extern "C" void METIS_mCPartGraphKway(int*, int*, int*, int*, int*, int*,
                               int*, int*, int*, int*, int*, int*, int*);
-*/
+
 
 CreateLBFunc_Def(MetisLB, "Use Metis(tm) to partition object graph")
 
@@ -170,6 +172,9 @@ void MetisLB::work(LDStats* stats)
     if(pemap[i] != ogr->vertices[i].getCurrentPe())
       ogr->vertices[i].setNewPe(pemap[i]);
   }
+  stats->is_prev_lb_refine = 3;
+  stats->after_lb_max = 0;
+  stats->after_lb_avg = 0;
 
   delete[] pemap;
 
index ca41be6667bd8a96875d9e45ee15e0ec1507c26c..9a1da5ded1e38ed2dd5e146b0feeb5c2a220b794 100644 (file)
@@ -12,7 +12,7 @@ CreateLBFunc_Def(RefineLB, "Move objects away from overloaded processor to reach
 RefineLB::RefineLB(const CkLBOptions &opt): CentralLB(opt)
 {
   lbname = (char *)"RefineLB";
-  if (CkMyPe() == 0)
+//  if (CkMyPe() == 0)
     CkPrintf("[%d] RefineLB created\n",CkMyPe());
 }
 
@@ -51,6 +51,12 @@ void RefineLB::work(LDStats* stats)
       }
   }
 
+  stats->is_prev_lb_refine = 1;
+  stats->after_lb_avg = refiner.computeAverageLoad();
+  stats->after_lb_max = refiner.computeMax();
+
+  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 ee5e620a1f95b513df7c6664560bea9fb730e031..357241708398852af5b5b00a7ec7c53caebf9f61 100644 (file)
@@ -29,6 +29,11 @@ extern "C" LDOMHandle LDRegisterOM(LDHandle _db, LDOMid _userID,
   return db->AddOM(_userID, _userptr, _callbacks);
 }
 
+extern "C" void LDOMAdaptResumeSync(LDHandle _db, int lb_ideal_period) {
+  LBDB *const db = (LBDB*)(_db.handle);
+  db->AdaptResumeSync(lb_ideal_period);
+}
+
 extern "C" void * LDOMUserData(LDOMHandle &_h)
 {
   LBDB *const db = (LBDB*)(_h.ldb.handle);
index e0d1a6d34e1fdd4a635819a5cb46691573294843..6c1cce5014bcb0f56228851480b3c2007afd0c28 100644 (file)
@@ -219,11 +219,13 @@ void LBCollectStatsOff(void);
 typedef void (*LDMigrateFn)(LDObjHandle handle, int dest);
 typedef void (*LDStatsFn)(LDOMHandle h, int state);
 typedef void (*LDQueryEstLoadFn)(LDOMHandle h);
+typedef void (*LDAdaptResumeSyncFn) (LDObjHandle handle, int lb_ideal_period);
 
 typedef struct {
   LDMigrateFn migrate;
   LDStatsFn setStats;
   LDQueryEstLoadFn queryEstLoad;
+  LDAdaptResumeSyncFn adaptResumeSync;
 } LDCallbacks;
 
 /*
@@ -237,6 +239,8 @@ LDHandle LDCreate(void);
 
 LDOMHandle LDRegisterOM(LDHandle _lbdb, LDOMid userID, 
                        void *userptr, LDCallbacks cb);
+
+void LDOMAdaptResumeSync(LDHandle _h, int lb_ideal_period);
 void * LDOMUserData(LDOMHandle &_h);
 void LDRegisteringObjects(LDOMHandle _h);
 void LDDoneRegisteringObjects(LDOMHandle _h);