bb049fe679636fb2f50758acf7a03fe19c5d477c
[charm.git] / src / ck-ldb / LBDatabase.C
1 /**
2  * \addtogroup CkLdb
3 */
4 /*@{*/
5
6 #include "converse.h"
7
8 /*
9  * This C++ file contains the Charm stub functions
10  */
11
12 #include "LBDatabase.h"
13 #include "LBSimulation.h"
14 #include "topology.h"
15
16 #include "limits.h"
17
18 #include "NullLB.h"
19
20 #define VEC_SIZE 500
21 #define IMB_TOLERANCE 1.1
22 #define OUTOFWAY_TOLERANCE 2
23 #define UTILIZATION_THRESHOLD 0.7
24 #define NEGLECT_IDLE 2 // Should never be == 1
25
26 #   define DEBAD(x) /*CkPrintf x*/
27 #   define EXTRA_FEATURE 0
28
29 struct AdaptiveData {
30   double iteration;
31   double max_load;
32   double avg_load;
33   double utilization;
34   double idle_time;
35 };
36
37 struct AdaptiveLBDatabase {
38   std::vector<AdaptiveData> history_data;
39 } adaptive_lbdb;
40
41 struct AdaptiveLBInfo {
42   AdaptiveLBInfo() {
43     max_avg_ratio = 1;
44     remote_local_ratio = 1;
45   }
46   double max_avg_ratio;
47   double remote_local_ratio;
48 };
49
50 // TODO: Separate out the datastructure required by just the central and on all
51 // processors
52 struct AdaptiveLBStructure {
53   int tentative_period;
54   int final_lb_period;
55   // This is based on the linear extrapolation
56   int lb_calculated_period;
57   int lb_iteration_no;
58   // This is set when all the processor sends the maximum iteration no
59   int global_max_iter_no;
60   // This keeps track of what was the max iteration no we had previously
61   // received. TODO: Mostly global_max_iter_no should be sufficied.
62   int tentative_max_iter_no;
63   // TODO: Use reduction to collect max iteration. Then we don't need this
64   // counter.
65   int global_recv_iter_counter;
66   // true indicates it is in Inform->ReceiveMaxIter->FinalLBPeriod stage.
67   bool in_progress;
68   double lb_strategy_cost;
69   double lb_migration_cost;
70   bool doCommStrategy;
71   int lb_msg_send_no;
72   int lb_msg_recv_no;
73   // Total AtSync calls from all the chares residing on the processor
74   int total_syncs_called;
75   int last_lb_type;
76   AdaptiveLBInfo greedy_info;
77   AdaptiveLBInfo refine_info;
78   AdaptiveLBInfo comm_info;
79   AdaptiveLBInfo comm_refine_info;
80 } adaptive_struct;
81
82
83 CkReductionMsg* lbDataCollection(int nMsg, CkReductionMsg** msgs) {
84   double lb_data[8];
85   lb_data[1] = 0.0; // total number of processors contributing
86   lb_data[2] = 0.0; // total load
87   lb_data[3] = 0.0; // max load
88   lb_data[4] = 0.0; // idle time
89   lb_data[5] = 1.0; // utilization
90   lb_data[6] = 0.0; // total load with bg
91   lb_data[7] = 0.0; // max load with bg
92   for (int i = 0; i < nMsg; i++) {
93     CkAssert(msgs[i]->getSize() == 8*sizeof(double));
94     if (msgs[i]->getSize() != 8*sizeof(double)) {
95       CkPrintf("Error!!! Reduction not correct. Msg size is %d\n", msgs[i]->getSize());
96     }
97     double* m = (double *)msgs[i]->getData();
98     // Total count
99     lb_data[1] += m[1];
100     // Avg load
101     lb_data[2] += m[2];
102     // Max load
103     lb_data[3] = ((m[3] > lb_data[3])? m[3] : lb_data[3]);
104     // Avg idle
105     lb_data[4] += m[4];
106     // Get least utilization
107     lb_data[5] = ((m[5] < lb_data[5]) ? m[5] : lb_data[5]);
108     // Get Avg load with bg
109     lb_data[6] += m[6];
110     // Get Max load with bg
111     lb_data[7] = ((m[7] > lb_data[7])? m[7] : lb_data[7]);
112     if (i == 0) {
113       // Iteration no
114       lb_data[0] = m[0];
115     }
116     if (m[0] != lb_data[0]) {
117       CkPrintf("Error!!! Reduction is intermingled between iteration %lf and\
118       %lf\n", lb_data[0], m[0]);
119     }
120   }
121   return CkReductionMsg::buildNew(8*sizeof(double), lb_data);
122 }
123
124 /*global*/ CkReduction::reducerType lbDataCollectionType;
125 /*initcall*/ void registerLBDataCollection(void) {
126   lbDataCollectionType = CkReduction::addReducer(lbDataCollection);
127 }
128
129 CkGroupID _lbdb;
130
131 CkpvDeclare(int, numLoadBalancers);  /**< num of lb created */
132 CkpvDeclare(int, hasNullLB);         /**< true if NullLB is created */
133 CkpvDeclare(int, lbdatabaseInited);  /**< true if lbdatabase is inited */
134
135 // command line options
136 CkLBArgs _lb_args;
137 int _lb_predict=0;
138 int _lb_predict_delay=10;
139 int _lb_predict_window=20;
140
141 // registry class stores all load balancers linked and created at runtime
142 class LBDBRegistry {
143 friend class LBDBInit;
144 friend class LBDatabase;
145 private:
146   // table for all available LBs linked in
147   struct LBDBEntry {
148     const char *name;
149     LBCreateFn  cfn;
150     LBAllocFn   afn;
151     const char *help;
152     int         shown;          // if 0, donot show in help page
153     LBDBEntry(): name(0), cfn(0), afn(0), help(0), shown(1) {}
154     LBDBEntry(int) {}
155     LBDBEntry(const char *n, LBCreateFn cf, LBAllocFn af,
156               const char *h, int show=1):
157       name(n), cfn(cf), afn(af), help(h), shown(show) {};
158   };
159   CkVec<LBDBEntry> lbtables;            // a list of available LBs linked
160   CkVec<const char *>   compile_lbs;    // load balancers at compile time
161   CkVec<const char *>   runtime_lbs;    // load balancers at run time
162 public:
163   LBDBRegistry() {}
164   void displayLBs()
165   {
166     CmiPrintf("\nAvailable load balancers:\n");
167     for (int i=0; i<lbtables.length(); i++) {
168       LBDBEntry &entry = lbtables[i];
169       if (entry.shown) CmiPrintf("* %s: %s\n", entry.name, entry.help);
170     }
171     CmiPrintf("\n");
172   }
173   void addEntry(const char *name, LBCreateFn fn, LBAllocFn afn, const char *help, int shown) {
174     lbtables.push_back(LBDBEntry(name, fn, afn, help, shown));
175   }
176   void addCompiletimeBalancer(const char *name) {
177     compile_lbs.push_back(name);
178   }
179   void addRuntimeBalancer(const char *name) {
180     runtime_lbs.push_back(name);
181   }
182   LBCreateFn search(const char *name) {
183     char *ptr = strpbrk((char *)name, ":,");
184     int slen = ptr!=NULL?ptr-name:strlen(name);
185     for (int i=0; i<lbtables.length(); i++)
186       if (0==strncmp(name, lbtables[i].name, slen)) return lbtables[i].cfn;
187     return NULL;
188   }
189   LBAllocFn getLBAllocFn(const char *name) {
190     char *ptr = strpbrk((char *)name, ":,");
191     int slen = ptr-name;
192     for (int i=0; i<lbtables.length(); i++)
193       if (0==strncmp(name, lbtables[i].name, slen)) return lbtables[i].afn;
194     return NULL;
195   }
196 };
197
198 static LBDBRegistry lbRegistry;
199
200 void LBDefaultCreate(const char *lbname)
201 {
202   lbRegistry.addCompiletimeBalancer(lbname);
203 }
204
205 // default is to show the helper
206 void LBRegisterBalancer(const char *name, LBCreateFn fn, LBAllocFn afn, const char *help, int shown)
207 {
208   lbRegistry.addEntry(name, fn, afn, help, shown);
209 }
210
211 LBAllocFn getLBAllocFn(char *lbname) {
212     return lbRegistry.getLBAllocFn(lbname);
213 }
214
215 LBCreateFn getLBCreateFn(const char *lbname) {
216     return lbRegistry.search(lbname);
217 }
218 // create a load balancer group using the strategy name
219 static void createLoadBalancer(const char *lbname)
220 {
221     LBCreateFn fn = lbRegistry.search(lbname);
222     if (!fn) {    // invalid lb name
223       CmiPrintf("Abort: Unknown load balancer: '%s'!\n", lbname);
224       lbRegistry.displayLBs();    // display help page
225       CkAbort("Abort");
226     }
227     // invoke function to create load balancer
228     fn();
229 }
230
231 // mainchare
232 LBDBInit::LBDBInit(CkArgMsg *m)
233 {
234 #if CMK_LBDB_ON
235   _lbdb = CProxy_LBDatabase::ckNew();
236
237   // runtime specified load balancer
238   if (lbRegistry.runtime_lbs.size() > 0) {
239     for (int i=0; i<lbRegistry.runtime_lbs.size(); i++) {
240       const char *balancer = lbRegistry.runtime_lbs[i];
241       createLoadBalancer(balancer);
242     }
243   }
244   else if (lbRegistry.compile_lbs.size() > 0) {
245     for (int i=0; i<lbRegistry.compile_lbs.size(); i++) {
246       const char* balancer = lbRegistry.compile_lbs[i];
247       createLoadBalancer(balancer);
248     }
249   }
250   else {
251     // NullLB is the default when none of above lb created
252     // note user may create his own load balancer in his code manually like
253     // in NAMD, but never mind NullLB can disable itself if there is
254     // a non NULL LB.
255     createLoadBalancer("NullLB");
256   }
257
258   // simulation mode
259   if (LBSimulation::doSimulation) {
260     CmiPrintf("Charm++> Entering Load Balancer Simulation Mode ... \n");
261     CProxy_LBDatabase(_lbdb).ckLocalBranch()->StartLB();
262   }
263 #endif
264   delete m;
265 }
266
267 // called from init.C
268 void _loadbalancerInit()
269 {
270   CkpvInitialize(int, lbdatabaseInited);
271   CkpvAccess(lbdatabaseInited) = 0;
272   CkpvInitialize(int, numLoadBalancers);
273   CkpvAccess(numLoadBalancers) = 0;
274   CkpvInitialize(int, hasNullLB);
275   CkpvAccess(hasNullLB) = 0;
276
277   char **argv = CkGetArgv();
278   char *balancer = NULL;
279   CmiArgGroup("Charm++","Load Balancer");
280   while (CmiGetArgStringDesc(argv, "+balancer", &balancer, "Use this load balancer")) {
281     if (CkMyRank() == 0)
282       lbRegistry.addRuntimeBalancer(balancer);   /* lbRegistry is a static */
283   }
284
285   // set up init value for LBPeriod time in seconds
286   // it can also be set by calling LDSetLBPeriod()
287   CmiGetArgDoubleDesc(argv,"+LBPeriod", &_lb_args.lbperiod(),"the minimum time period in seconds allowed for two consecutive automatic load balancing");
288   _lb_args.loop() = CmiGetArgFlagDesc(argv, "+LBLoop", "Use multiple load balancing strategies in loop");
289
290   // now called in cldb.c: CldModuleGeneralInit()
291   // registerLBTopos();
292   CmiGetArgStringDesc(argv, "+LBTopo", &_lbtopo, "define load balancing topology");
293   //Read the K parameter for RefineKLB
294   CmiGetArgIntDesc(argv, "+LBNumMoves", &_lb_args.percentMovesAllowed() , "Percentage of chares to be moved (used by RefineKLB) [0-100]");
295
296   /**************** FUTURE PREDICTOR ****************/
297   _lb_predict = CmiGetArgFlagDesc(argv, "+LBPredictor", "Turn on LB future predictor");
298   CmiGetArgIntDesc(argv, "+LBPredictorDelay", &_lb_predict_delay, "Number of balance steps before learning a model");
299   CmiGetArgIntDesc(argv, "+LBPredictorWindow", &_lb_predict_window, "Number of steps to use to learn a model");
300   if (_lb_predict_window < _lb_predict_delay) {
301     CmiPrintf("LB> [%d] Argument LBPredictorWindow (%d) less than LBPredictorDelay (%d) , fixing\n", CkMyPe(), _lb_predict_window, _lb_predict_delay);
302     _lb_predict_delay = _lb_predict_window;
303   }
304
305   /******************* SIMULATION *******************/
306   // get the step number at which to dump the LB database
307   CmiGetArgIntDesc(argv, "+LBVersion", &_lb_args.lbversion(), "LB database file version number");
308   CmiGetArgIntDesc(argv, "+LBCentPE", &_lb_args.central_pe(), "CentralLB processor");
309   int _lb_dump_activated = 0;
310   if (CmiGetArgIntDesc(argv, "+LBDump", &LBSimulation::dumpStep, "Dump the LB state from this step"))
311     _lb_dump_activated = 1;
312   if (_lb_dump_activated && LBSimulation::dumpStep < 0) {
313     CmiPrintf("LB> Argument LBDump (%d) negative, setting to 0\n",LBSimulation::dumpStep);
314     LBSimulation::dumpStep = 0;
315   }
316   CmiGetArgIntDesc(argv, "+LBDumpSteps", &LBSimulation::dumpStepSize, "Dump the LB state for this amount of steps");
317   if (LBSimulation::dumpStepSize <= 0) {
318     CmiPrintf("LB> Argument LBDumpSteps (%d) too small, setting to 1\n",LBSimulation::dumpStepSize);
319     LBSimulation::dumpStepSize = 1;
320   }
321   CmiGetArgStringDesc(argv, "+LBDumpFile", &LBSimulation::dumpFile, "Set the LB state file name");
322   // get the simulation flag and number. Now the flag can also be avoided by the presence of the number
323   LBSimulation::doSimulation = CmiGetArgIntDesc(argv, "+LBSim", &LBSimulation::simStep, "Read LB state from LBDumpFile since this step");
324   // check for stupid LBSim parameter
325   if (LBSimulation::doSimulation && LBSimulation::simStep < 0) {
326     CmiPrintf("LB> Argument LBSim (%d) invalid, should be >= 0\n");
327     CkExit();
328     return;
329   }
330   CmiGetArgIntDesc(argv, "+LBSimSteps", &LBSimulation::simStepSize, "Read LB state for this number of steps");
331   if (LBSimulation::simStepSize <= 0) {
332     CmiPrintf("LB> Argument LBSimSteps (%d) too small, setting to 1\n",LBSimulation::simStepSize);
333     LBSimulation::simStepSize = 1;
334   }
335
336
337   LBSimulation::simProcs = 0;
338   CmiGetArgIntDesc(argv, "+LBSimProcs", &LBSimulation::simProcs, "Number of target processors.");
339
340   LBSimulation::showDecisionsOnly =
341     CmiGetArgFlagDesc(argv, "+LBShowDecisions",
342                       "Write to File: Load Balancing Object to Processor Map decisions during LB Simulation");
343
344   // force a global barrier after migration done
345   _lb_args.syncResume() = CmiGetArgFlagDesc(argv, "+LBSyncResume",
346                   "LB performs a barrier after migration is finished");
347
348   // both +LBDebug and +LBDebug level should work
349   if (!CmiGetArgIntDesc(argv, "+LBDebug", &_lb_args.debug(),
350                                           "Turn on LB debugging printouts"))
351     _lb_args.debug() = CmiGetArgFlagDesc(argv, "+LBDebug",
352                                              "Turn on LB debugging printouts");
353
354   // getting the size of the team with +teamSize
355   if (!CmiGetArgIntDesc(argv, "+teamSize", &_lb_args.teamSize(),
356                                           "Team size"))
357     _lb_args.teamSize() = 1;
358
359   // ask to print summary/quality of load balancer
360   _lb_args.printSummary() = CmiGetArgFlagDesc(argv, "+LBPrintSummary",
361                 "Print load balancing result summary");
362
363   // to ignore baclground load
364   _lb_args.ignoreBgLoad() = CmiGetArgFlagDesc(argv, "+LBNoBackground",
365                       "Load balancer ignores the background load.");
366 #ifdef __BIGSIM__
367   _lb_args.ignoreBgLoad() = 1;
368 #endif
369   _lb_args.migObjOnly() = CmiGetArgFlagDesc(argv, "+LBObjOnly",
370                       "Only load balancing migratable objects, ignoring all others.");
371   if (_lb_args.migObjOnly()) _lb_args.ignoreBgLoad() = 1;
372
373   // assume all CPUs are identical
374   _lb_args.testPeSpeed() = CmiGetArgFlagDesc(argv, "+LBTestPESpeed",
375                       "Load balancer test all CPUs speed.");
376   _lb_args.samePeSpeed() = CmiGetArgFlagDesc(argv, "+LBSameCpus",
377                       "Load balancer assumes all CPUs are of same speed.");
378   if (!_lb_args.testPeSpeed()) _lb_args.samePeSpeed() = 1;
379
380   _lb_args.useCpuTime() = CmiGetArgFlagDesc(argv, "+LBUseCpuTime",
381                       "Load balancer uses CPU time instead of wallclock time.");
382
383   // turn instrumentation off at startup
384   _lb_args.statsOn() = !CmiGetArgFlagDesc(argv, "+LBOff",
385                         "Turn load balancer instrumentation off");
386
387   // turn instrumentation of communicatin off at startup
388   _lb_args.traceComm() = !CmiGetArgFlagDesc(argv, "+LBCommOff",
389                 "Turn load balancer instrumentation of communication off");
390
391   // set alpha and beeta
392   _lb_args.alpha() = PER_MESSAGE_SEND_OVERHEAD_DEFAULT;
393   _lb_args.beeta() = PER_BYTE_SEND_OVERHEAD_DEFAULT;
394   CmiGetArgDoubleDesc(argv,"+LBAlpha", &_lb_args.alpha(),
395                            "per message send overhead");
396   CmiGetArgDoubleDesc(argv,"+LBBeta", &_lb_args.beeta(),
397                            "per byte send overhead");
398
399   if (CkMyPe() == 0) {
400     if (_lb_args.debug()) {
401       CmiPrintf("CharmLB> Verbose level %d, load balancing period: %g seconds\n", _lb_args.debug(), _lb_args.lbperiod());
402     }
403     if (_lb_args.debug() > 1) {
404       CmiPrintf("CharmLB> Topology %s alpha: %es beta: %es.\n", _lbtopo, _lb_args.alpha(), _lb_args.beeta());
405     }
406     if (_lb_args.printSummary())
407       CmiPrintf("CharmLB> Load balancer print summary of load balancing result.\n");
408     if (_lb_args.ignoreBgLoad())
409       CmiPrintf("CharmLB> Load balancer ignores processor background load.\n");
410     if (_lb_args.samePeSpeed())
411       CmiPrintf("CharmLB> Load balancer assumes all CPUs are same.\n");
412     if (_lb_args.useCpuTime())
413       CmiPrintf("CharmLB> Load balancer uses CPU time instead of wallclock time.\n");
414     if (LBSimulation::doSimulation)
415       CmiPrintf("CharmLB> Load balancer running in simulation mode on file '%s' version %d.\n", LBSimulation::dumpFile, _lb_args.lbversion());
416     if (_lb_args.statsOn()==0)
417       CkPrintf("CharmLB> Load balancing instrumentation is off.\n");
418     if (_lb_args.traceComm()==0)
419       CkPrintf("CharmLB> Load balancing instrumentation for communication is off.\n");
420     if (_lb_args.migObjOnly())
421       CkPrintf("LB> Load balancing strategy ignores non-migratable objects.\n");
422   }
423 }
424
425 int LBDatabase::manualOn = 0;
426 char *LBDatabase::avail_vector = NULL;
427 CmiNodeLock avail_vector_lock;
428
429 static LBRealType * _expectedLoad = NULL;
430
431 void LBDatabase::initnodeFn()
432 {
433   int proc;
434   int num_proc = CkNumPes();
435   avail_vector= new char[num_proc];
436   for(proc = 0; proc < num_proc; proc++)
437       avail_vector[proc] = 1;
438   avail_vector_lock = CmiCreateLock();
439
440   _expectedLoad = new LBRealType[num_proc];
441   for (proc=0; proc<num_proc; proc++) _expectedLoad[proc]=0.0;
442
443   //CkPrintf("Total objs in %d is %d\n", CkMyPe(), getLBDB()->ObjDataCount());
444 }
445
446 // called my constructor
447 void LBDatabase::init(void)
448 {
449   //thisProxy = CProxy_LBDatabase(thisgroup);
450   myLDHandle = LDCreate();
451   mystep = 0;
452   nloadbalancers = 0;
453   new_ld_balancer = 0;
454
455   CkpvAccess(lbdatabaseInited) = 1;
456 #if CMK_LBDB_ON
457   if (manualOn) TurnManualLBOn();
458 #endif
459
460   total_load_vec.resize(VEC_SIZE, 0.0);
461   total_count_vec.resize(VEC_SIZE, 0);
462   max_iteration = -1;
463   prev_idle = 0.0;
464   alpha_beta_cost_to_load = 1.0; // Some random value. TODO: Find the actual
465
466   // If metabalancer enabled, initialize the variables
467   adaptive_struct.tentative_period =  INT_MAX;
468   adaptive_struct.final_lb_period =  INT_MAX;
469   adaptive_struct.lb_calculated_period = INT_MAX;
470   adaptive_struct.lb_iteration_no = -1;
471   adaptive_struct.global_max_iter_no = 0;
472   adaptive_struct.tentative_max_iter_no = -1;
473   adaptive_struct.global_recv_iter_counter = 0;
474   adaptive_struct.in_progress = false;
475   adaptive_struct.lb_strategy_cost = 0.0;
476   adaptive_struct.lb_migration_cost = 0.0;
477   adaptive_struct.lb_msg_send_no = 0;
478   adaptive_struct.lb_msg_recv_no = 0;
479   adaptive_struct.total_syncs_called = 0;
480   adaptive_struct.last_lb_type = -1;
481
482   // This is indicating if the load balancing strategy and migration started.
483   // This is mainly used to register callbacks for noobj pes. They would
484   // register as soon as resumefromsync is called. On receiving the handles at
485   // the central pe, it clears the previous handlers and sets lb_in_progress
486   // to false so that it doesn't clear the handles.
487   lb_in_progress = false;
488
489   is_prev_lb_refine = -1;
490 }
491
492 LBDatabase::LastLBInfo::LastLBInfo()
493 {
494   expectedLoad = _expectedLoad;
495 }
496
497 void LBDatabase::get_avail_vector(char * bitmap) {
498     CmiAssert(bitmap && avail_vector);
499     const int num_proc = CkNumPes();
500     for(int proc = 0; proc < num_proc; proc++){
501       bitmap[proc] = avail_vector[proc];
502     }
503 }
504
505 // new_ld == -1(default) : calcualte a new ld
506 //           -2 : ignore new ld
507 //           >=0: given a new ld
508 void LBDatabase::set_avail_vector(char * bitmap, int new_ld){
509     int assigned = 0;
510     const int num_proc = CkNumPes();
511     if (new_ld == -2) assigned = 1;
512     else if (new_ld >= 0) {
513       CmiAssert(new_ld < num_proc);
514       new_ld_balancer = new_ld;
515       assigned = 1;
516     }
517     CmiAssert(bitmap && avail_vector);
518     for(int count = 0; count < num_proc; count++){
519         avail_vector[count] = bitmap[count];
520         if((bitmap[count] == 1) && !assigned){
521             new_ld_balancer = count;
522             assigned = 1;
523         }
524     }
525 }
526
527 // called in CreateFooLB() when multiple load balancers are created
528 // on PE0, BaseLB of each load balancer applies a ticket number
529 // and broadcast the ticket number to all processors
530 int LBDatabase::getLoadbalancerTicket()  {
531   int seq = nloadbalancers;
532   nloadbalancers ++;
533   loadbalancers.resize(nloadbalancers);
534   loadbalancers[seq] = NULL;
535   return seq;
536 }
537
538 void LBDatabase::addLoadbalancer(BaseLB *lb, int seq) {
539 //  CmiPrintf("[%d] addLoadbalancer for seq %d\n", CkMyPe(), seq);
540   if (seq == -1) return;
541   if (CkMyPe() == 0) {
542     CmiAssert(seq < nloadbalancers);
543     if (loadbalancers[seq]) {
544       CmiPrintf("Duplicate load balancer created at %d\n", seq);
545       CmiAbort("LBDatabase");
546     }
547   }
548   else
549     nloadbalancers ++;
550   loadbalancers.resize(seq+1);
551   loadbalancers[seq] = lb;
552 }
553
554 // switch strategy in order
555 void LBDatabase::nextLoadbalancer(int seq) {
556   if (seq == -1) return;                // -1 means this is the only LB
557   int next = seq+1;
558   if (_lb_args.loop()) {
559     if (next == nloadbalancers) next = 0;
560   }
561   else {
562     if (next == nloadbalancers) next --;  // keep using the last one
563   }
564   if (seq != next) {
565     loadbalancers[seq]->turnOff();
566     CmiAssert(loadbalancers[next]);
567     loadbalancers[next]->turnOn();
568   }
569 }
570
571 // return the seq-th load balancer string name of
572 // it can be specified in either compile time or runtime
573 // runtime has higher priority
574 const char *LBDatabase::loadbalancer(int seq) {
575   if (lbRegistry.runtime_lbs.length()) {
576     CmiAssert(seq < lbRegistry.runtime_lbs.length());
577     return lbRegistry.runtime_lbs[seq];
578   }
579   else {
580     CmiAssert(seq < lbRegistry.compile_lbs.length());
581     return lbRegistry.compile_lbs[seq];
582   }
583 }
584
585 void LBDatabase::pup(PUP::er& p)
586 {
587         IrrGroup::pup(p);
588         // the memory should be already allocated
589         int np;
590         if (!p.isUnpacking()) np = CkNumPes();
591         p|np;
592         CmiAssert(avail_vector);
593         // in case number of processors changes
594         if (p.isUnpacking() && np > CkNumPes()) {
595                 CmiLock(avail_vector_lock);
596                 delete [] avail_vector;
597                 avail_vector = new char[np];
598                 for (int i=0; i<np; i++) avail_vector[i] = 1;
599                 CmiUnlock(avail_vector_lock);
600         }
601         p(avail_vector, np);
602         p|mystep;
603         if(p.isUnpacking()) nloadbalancers = 0;
604 }
605
606
607 void LBDatabase::EstObjLoad(const LDObjHandle &_h, double cputime)
608 {
609 #if CMK_LBDB_ON
610   LBDB *const db = (LBDB*)(_h.omhandle.ldb.handle);
611   LBObj *const obj = db->LbObj(_h);
612
613   CmiAssert(obj != NULL);
614   obj->setTiming(cputime);
615 #endif
616 }
617
618 void LBDatabase::ResumeClients() {
619   // If metabalancer enabled, initialize the variables
620   adaptive_lbdb.history_data.clear();
621
622   adaptive_struct.tentative_period =  INT_MAX;
623   adaptive_struct.final_lb_period =  INT_MAX;
624   adaptive_struct.lb_calculated_period = INT_MAX;
625   adaptive_struct.lb_iteration_no = -1;
626   adaptive_struct.global_max_iter_no = 0;
627   adaptive_struct.tentative_max_iter_no = -1;
628   adaptive_struct.global_recv_iter_counter = 0;
629   adaptive_struct.in_progress = false;
630   adaptive_struct.lb_strategy_cost = 0.0;
631   adaptive_struct.lb_migration_cost = 0.0;
632   adaptive_struct.lb_msg_send_no = 0;
633   adaptive_struct.lb_msg_recv_no = 0;
634   adaptive_struct.total_syncs_called = 0;
635
636   total_load_vec.clear();
637   total_count_vec.clear();
638   prev_idle = 0.0;
639   if (lb_in_progress) {
640     lbdb_no_obj_callback.clear();
641     lb_in_progress = false;
642   }
643
644   total_load_vec.resize(VEC_SIZE, 0.0);
645   total_count_vec.resize(VEC_SIZE, 0);
646
647   // While resuming client, if we find that there are no objects, then handle
648   // the case accordingly.
649   if (getLBDB()->ObjDataCount() == 0) {
650     HandleAdaptiveNoObj();
651   }
652   LDResumeClients(myLDHandle);
653 }
654
655 bool LBDatabase::AddLoad(int iteration, double load) {
656   total_count_vec[iteration]++;
657   adaptive_struct.total_syncs_called++;
658   DEBAD(("At PE %d Total contribution for iteration %d is %d total objs %d\n", CkMyPe(), iteration,
659     total_count_vec[iteration], getLBDB()->ObjDataCount()));
660
661   if (iteration > adaptive_struct.lb_iteration_no) {
662     adaptive_struct.lb_iteration_no = iteration;
663   }
664   total_load_vec[iteration] += load;
665   if (total_count_vec[iteration] == getLBDB()->ObjDataCount()) {
666     double idle_time, bg_walltime, cpu_bgtime;
667     IdleTime(&idle_time);
668     BackgroundLoad(&bg_walltime, &cpu_bgtime);
669
670     int sync_for_bg = adaptive_struct.total_syncs_called +
671         getLBDB()->ObjDataCount();
672     bg_walltime = bg_walltime * getLBDB()->ObjDataCount() / sync_for_bg;
673
674     if (iteration < NEGLECT_IDLE) {
675       prev_idle = idle_time;
676     }
677     idle_time -= prev_idle;
678
679     // The chares do not contribute their 0th iteration load. So the total syncs
680     // in reality is total_syncs_called + obj_counts
681     int total_countable_syncs = adaptive_struct.total_syncs_called +
682         (1 - NEGLECT_IDLE) * getLBDB()->ObjDataCount(); // TODO: Fix me! weird!
683     if (total_countable_syncs != 0) {
684       idle_time = idle_time * getLBDB()->ObjDataCount() / total_countable_syncs;
685     }
686     //CkPrintf("[%d] Idle time %lf and countable %d for iteration %d\n", CkMyPe(), idle_time, total_countable_syncs, iteration);
687
688     double lb_data[8];
689     lb_data[0] = iteration;
690     lb_data[1] = 1;
691     lb_data[2] = total_load_vec[iteration]; // For average load
692     lb_data[3] = total_load_vec[iteration]; // For max load
693     lb_data[4] = idle_time;
694     // Set utilization
695     if (total_load_vec[iteration] == 0.0) {
696       lb_data[5] = 0.0;
697     } else {
698       lb_data[5] = total_load_vec[iteration]/(idle_time + total_load_vec[iteration]);
699     }
700     lb_data[6] = lb_data[2] + bg_walltime; // For Avg load with bg
701     lb_data[7] = lb_data[6]; // For Max load with bg
702
703     //CkPrintf("   [%d] sends total load %lf idle time %lf ratio of idle/load %lf at iter %d\n", CkMyPe(),
704     //    total_load_vec[iteration], idle_time,
705     //    idle_time/total_load_vec[iteration], adaptive_struct.lb_iteration_no);
706
707     CkCallback cb(CkIndex_LBDatabase::ReceiveMinStats((CkReductionMsg*)NULL), thisProxy[0]);
708     contribute(8*sizeof(double), lb_data, lbDataCollectionType, cb);
709   }
710   return true;
711 }
712
713 void LBDatabase::ReceiveMinStats(CkReductionMsg *msg) {
714   double* load = (double *) msg->getData();
715   double avg = load[2]/load[1];
716   double max = load[3];
717   double avg_idle = load[4]/load[1];
718   double utilization = load[5];
719   int iteration_n = load[0];
720   double avg_load_bg = load[6]/load[1];
721   double max_load_bg = load[7];
722   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]));
723   CkPrintf("** [%d] Iteration Avg load: %lf Max load: %lf With bg Avg load: %lf Max load: %lf Avg Idle : %lf Max Idle : %lf for %lf procs\n",iteration_n, avg, max, avg_load_bg, max_load_bg, avg_idle, utilization, load[1]);
724   delete msg;
725
726 #if EXTRA_FEATURE
727   if (adaptive_struct.final_lb_period != iteration_n) {
728     for (int i = 0; i < lbdb_no_obj_callback.size(); i++) {
729       thisProxy[lbdb_no_obj_callback[i]].TriggerAdaptiveReduction();
730     }
731   }
732 #endif
733
734   // Store the data for this iteration
735   adaptive_struct.lb_iteration_no = iteration_n;
736   AdaptiveData data;
737   data.iteration = adaptive_struct.lb_iteration_no;
738   data.max_load = max;
739   data.avg_load = avg;
740   data.utilization = utilization;
741   data.idle_time = avg_idle;
742   adaptive_lbdb.history_data.push_back(data);
743
744   // If lb period inform is in progress, dont inform again.
745   // If this is the lb data corresponding to the final lb period informed, then
746   // don't recalculate as some of the processors might have already gone into
747   // LB_STAGE.
748   if (adaptive_struct.in_progress || (adaptive_struct.final_lb_period == iteration_n)) {
749     return;
750   }
751
752   double utilization_threshold = UTILIZATION_THRESHOLD;
753
754 #if EXTRA_FEATURE
755   CkPrintf("alpha_beta_to_load %lf\n", alpha_beta_cost_to_load);
756   if (alpha_beta_cost_to_load < 0.1) {
757     // Ignore the effect of idle time and there by lesser utilization. So we
758     // assign utilization threshold to be 0.0
759     CkPrintf("Changing the idle load tolerance coz this isn't communication intensive benchmark\n");
760     utilization_threshold = 0.0;
761   }
762 #endif
763
764   // First generate the lb period based on the cost of lb. Find out what is the
765   // expected imbalance at the calculated lb period.
766   int period;
767   // This is based on the new max load after load balancing. So technically, it
768   // is calculated based on the shifter up avg curve.
769   double ratio_at_t = 1.0;
770   int tmp_lb_type;
771   double tmp_max_avg_ratio, tmp_comm_ratio;
772   GetPrevLBData(tmp_lb_type, tmp_max_avg_ratio, tmp_comm_ratio);
773   double tolerate_imb = IMB_TOLERANCE * tmp_max_avg_ratio;
774
775   if (generatePlan(period, ratio_at_t)) {
776     DEBAD(("Generated period and calculated %d and period %d max iter %d\n",
777       adaptive_struct.lb_calculated_period, period,
778       adaptive_struct.tentative_max_iter_no));
779     // set the imbalance tolerance to be ratio_at_calculated_lb_period
780     if (ratio_at_t != 1.0) {
781       CkPrintf("Changed tolerance to %lf after line eq whereas max/avg is %lf\n", ratio_at_t, max/avg);
782       // Since ratio_at_t is shifter up, max/(tmp_max_avg_ratio * avg) should be
783       // compared with the tolerance
784       tolerate_imb = ratio_at_t * tmp_max_avg_ratio * OUTOFWAY_TOLERANCE;
785     }
786
787     CkPrintf("Prev LB Data Type %d, max/avg %lf, local/remote %lf\n", tmp_lb_type, tmp_max_avg_ratio, tmp_comm_ratio);
788
789     if ((utilization < utilization_threshold || max/avg >= tolerate_imb) && adaptive_lbdb.history_data.size() > 6) {
790       CkPrintf("Trigger soon even though we calculated lbperiod max/avg(%lf) and utilization ratio (%lf)\n", max/avg, utilization);
791       TriggerSoon(iteration_n, max/avg, tolerate_imb);
792       return;
793     }
794
795     // If the new lb period from linear extrapolation is greater than maximum
796     // iteration known from previously collected data, then inform all the
797     // processors about the new calculated period.
798     if (period > adaptive_struct.tentative_max_iter_no) {
799       adaptive_struct.doCommStrategy = false;
800       adaptive_struct.lb_calculated_period = period;
801       adaptive_struct.in_progress = true;
802       CkPrintf("Sticking to the calculated period %d\n",
803         adaptive_struct.lb_calculated_period);
804       thisProxy.LoadBalanceDecision(adaptive_struct.lb_msg_send_no++,
805         adaptive_struct.lb_calculated_period);
806       return;
807     }
808     // TODO: Shouldn't we return from here??
809   }
810
811   CkPrintf("Prev LB Data Type %d, max/avg %lf, local/remote %lf\n", tmp_lb_type, tmp_max_avg_ratio, tmp_comm_ratio);
812
813   // This would be called when the datasize is not enough to calculate lb period
814   if ((utilization < utilization_threshold || max/avg >= tolerate_imb) && adaptive_lbdb.history_data.size() > 4) {
815     CkPrintf("Carry out load balancing step at iter max/avg(%lf) and utilization ratio (%lf)\n", max/avg, utilization);
816     TriggerSoon(iteration_n, max/avg, tolerate_imb);
817     return;
818   }
819
820 }
821
822 void LBDatabase::TriggerSoon(int iteration_n, double imbalance_ratio,
823     double tolerate_imb) {
824
825   // If the previously calculated_period (not the final decision) is greater
826   // than the iter +1 and if it is greater than the maximum iteration we have
827   // seen so far, then we can inform this
828   if ((iteration_n + 1 > adaptive_struct.tentative_max_iter_no) &&
829       (iteration_n+1 < adaptive_struct.lb_calculated_period)) {
830     if (imbalance_ratio < tolerate_imb) {
831       adaptive_struct.doCommStrategy = true;
832       CkPrintf("No load imbalance but idle time\n");
833     } else {
834       adaptive_struct.doCommStrategy = false;
835       CkPrintf("load imbalance \n");
836     }
837     adaptive_struct.lb_calculated_period = iteration_n + 1;
838     adaptive_struct.in_progress = true;
839     CkPrintf("Informing everyone the lb period is %d\n",
840         adaptive_struct.lb_calculated_period);
841     thisProxy.LoadBalanceDecision(adaptive_struct.lb_msg_send_no++,
842         adaptive_struct.lb_calculated_period);
843   }
844 }
845
846 bool LBDatabase::generatePlan(int& period, double& ratio_at_t) {
847   if (adaptive_lbdb.history_data.size() <= 4) {
848     return false;
849   }
850
851   // Some heuristics for lbperiod
852   // If constant load or almost constant,
853   // then max * new_lb_period > avg * new_lb_period + lb_cost
854   double max = 0.0;
855   double avg = 0.0;
856   AdaptiveData data;
857   for (int i = 0; i < adaptive_lbdb.history_data.size(); i++) {
858     data = adaptive_lbdb.history_data[i];
859     max += data.max_load;
860     avg += data.avg_load;
861     //DEBAD(("max (%d, %lf) avg (%d, %lf)\n", i, data.max_load, i, data.avg_load));
862     //CkPrintf("max (%d, %lf) avg (%d, %lf)\n", i, data.max_load, i, data.avg_load);
863   }
864 //  max /= (adaptive_struct.lb_iteration_no - adaptive_lbdb.history_data[0].iteration);
865 //  avg /= (adaptive_struct.lb_iteration_no - adaptive_lbdb.history_data[0].iteration);
866
867   // If linearly varying load, then find lb_period
868   // area between the max and avg curve
869   // If we can attain perfect balance, then the new load is close to the
870   // average. Hence we pass 1, else pass in some other value which would be the
871   // new max_load after load balancing.
872   int tmp_lb_type;
873   double tmp_max_avg_ratio, tmp_comm_ratio;
874   double tolerate_imb;
875
876 #if EXTRA_FEATURE
877   // First get the data for refine.
878   GetLBDataForLB(1, tmp_max_avg_ratio, tmp_comm_ratio);
879   tolerate_imb = tmp_max_avg_ratio;
880
881   // If RefineLB does a good job, then find the period considering RefineLB
882   if (tmp_max_avg_ratio <= 1.01) {
883     if (max/avg < tolerate_imb) {
884       CkPrintf("Resorting to imb = 1.0 coz max/avg (%lf) < imb(%lf)\n", max/avg, tolerate_imb);
885       tolerate_imb = 1.0;
886     }
887     CkPrintf("Will generate plan for refine %lf imb and %lf overhead\n", tolerate_imb, 0.2);
888     return getPeriodForStrategy(tolerate_imb, 0.2, period, ratio_at_t);
889   }
890
891   GetLBDataForLB(0, tmp_max_avg_ratio, tmp_comm_ratio);
892 #endif
893
894   GetPrevLBData(tmp_lb_type, tmp_max_avg_ratio, tmp_comm_ratio);
895   tolerate_imb = tmp_max_avg_ratio;
896   if (max/avg < tolerate_imb) {
897     CkPrintf("Resorting to imb = 1.0 coz max/avg (%lf) < imb(%lf)\n", max/avg, tolerate_imb);
898     tolerate_imb = 1.0;
899   }
900
901   if (getPeriodForStrategy(tolerate_imb, 1, period, ratio_at_t)) {
902     return true;
903   }
904
905   max = 0.0;
906   avg = 0.0;
907   for (int i = 0; i < adaptive_lbdb.history_data.size(); i++) {
908     data = adaptive_lbdb.history_data[i];
909     max += data.max_load;
910     avg += data.avg_load*tolerate_imb;
911     //DEBAD(("max (%d, %lf) avg (%d, %lf)\n", i, data.max_load, i, data.avg_load));
912     //CkPrintf("max (%d, %lf) avg (%d, %lf)\n", i, data.max_load, i, data.avg_load);
913   }
914   max /= adaptive_lbdb.history_data.size();
915   avg /= adaptive_lbdb.history_data.size();
916   double cost = adaptive_struct.lb_strategy_cost + adaptive_struct.lb_migration_cost;
917   period = cost/(max - avg); 
918   ratio_at_t = max / avg;
919   return true;
920 }
921
922 bool LBDatabase::getPeriodForStrategy(double new_load_percent,
923     double overhead_percent, int& period, double& ratio_at_t) {
924   double mslope, aslope, mc, ac;
925   getLineEq(new_load_percent, aslope, ac, mslope, mc);
926   CkPrintf("new load percent %lf\n", new_load_percent);
927   CkPrintf("\n max: %fx + %f; avg: %fx + %f\n", mslope, mc, aslope, ac);
928   double a = (mslope - aslope)/2;
929   double b = (mc - ac);
930   double c = -(adaptive_struct.lb_strategy_cost +
931       adaptive_struct.lb_migration_cost) * overhead_percent;
932   bool got_period = getPeriodForLinear(a, b, c, period);
933   if (!got_period) {
934     return false;
935   }
936
937   if (mslope < 0) {
938     if (period > (-mc/mslope)) {
939       CkPrintf("Max < 0 Period set when max load is -ve\n");
940       return false;
941     }
942   }
943
944   if (aslope < 0) {
945     if (period > (-ac/aslope)) {
946       CkPrintf("Avg < 0 Period set when avg load is -ve\n");
947       return false;
948     }
949   }
950
951   int intersection_t = (mc-ac) / (aslope - mslope);
952   if (intersection_t > 0 && period > intersection_t) {
953     CkPrintf("Avg | Max Period set when curves intersect\n");
954     return false;
955   }
956   ratio_at_t = ((mslope*period + mc)/(aslope*period + ac));
957   CkPrintf("Ratio at t (%lf*%d + %lf) / (%lf*%d+%lf) = %lf\n", mslope, period, mc, aslope, period, ac, ratio_at_t);
958   return true;
959 }
960
961 bool LBDatabase::getPeriodForLinear(double a, double b, double c, int& period) {
962   CkPrintf("Quadratic Equation %lf X^2 + %lf X + %lf\n", a, b, c);
963   if (a == 0.0) {
964     period = (-c / b);
965     if (period < 0) {
966       CkPrintf("-ve period for -c/b (%d)\n", period);
967       return false;
968     }
969     CkPrintf("Ideal period for linear load %d\n", period);
970     return true;
971   }
972   int x;
973   double t = (b * b) - (4*a*c);
974   if (t < 0) {
975     CkPrintf("(b * b) - (4*a*c) is -ve sqrt : %lf\n", sqrt(t));
976     return false;
977   }
978   t = (-b + sqrt(t)) / (2*a);
979   x = t;
980   if (x < 0) {
981     CkPrintf("boo!!! x (%d) < 0\n", x);
982     x = 0;
983     return false;
984   }
985   period = x;
986   CkPrintf("Ideal period for linear load %d\n", period);
987   return true;
988 }
989
990 bool LBDatabase::getLineEq(double new_load_percent, double& aslope, double& ac, double& mslope, double& mc) {
991   int total = adaptive_lbdb.history_data.size();
992   int iterations = 1 + adaptive_lbdb.history_data[total - 1].iteration -
993       adaptive_lbdb.history_data[0].iteration;
994   double a1 = 0;
995   double m1 = 0;
996   double a2 = 0;
997   double m2 = 0;
998   AdaptiveData data;
999   int i = 0;
1000   for (i = 0; i < total/2; i++) {
1001     data = adaptive_lbdb.history_data[i];
1002     m1 += data.max_load;
1003     a1 += data.avg_load;
1004     CkPrintf("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);
1005   }
1006   m1 /= i;
1007   a1 = (a1 * new_load_percent) / i;
1008
1009   for (i = total/2; i < total; i++) {
1010     data = adaptive_lbdb.history_data[i];
1011     m2 += data.max_load;
1012     a2 += data.avg_load;
1013     CkPrintf("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);
1014   }
1015   m2 /= (i - total/2);
1016   a2 = (a2 * new_load_percent) / (i - total/2);
1017
1018   aslope = 2 * (a2 - a1) / iterations;
1019   mslope = 2 * (m2 - m1) / iterations;
1020   ac = adaptive_lbdb.history_data[0].avg_load * new_load_percent;
1021   mc = adaptive_lbdb.history_data[0].max_load;
1022
1023   ac = a1 - ((aslope * total)/4);
1024   mc = m1 - ((mslope * total)/4);
1025
1026   //ac = (adaptive_lbdb.history_data[1].avg_load * new_load_percent - aslope);
1027   //mc = (adaptive_lbdb.history_data[1].max_load - mslope);
1028
1029   return true;
1030 }
1031
1032 void LBDatabase::LoadBalanceDecision(int req_no, int period) {
1033   if (req_no < adaptive_struct.lb_msg_recv_no) {
1034     CkPrintf("Error!!! Received a request which was already sent or old\n");
1035     return;
1036   }
1037   //CkPrintf("[%d] Load balance decision made cur iteration: %d period:%d state: %d\n",CkMyPe(), adaptive_struct.lb_iteration_no, period, local_state);
1038   adaptive_struct.tentative_period = period;
1039   adaptive_struct.lb_msg_recv_no = req_no;
1040   thisProxy[0].ReceiveIterationNo(req_no, adaptive_struct.lb_iteration_no);
1041 }
1042
1043 void LBDatabase::LoadBalanceDecisionFinal(int req_no, int period) {
1044   if (req_no < adaptive_struct.lb_msg_recv_no) {
1045     return;
1046   }
1047   DEBAD(("[%d] Final Load balance decision made cur iteration: %d period:%d \n",CkMyPe(), adaptive_struct.lb_iteration_no, period));
1048   adaptive_struct.tentative_period = period;
1049   adaptive_struct.final_lb_period = period;
1050   LDOMAdaptResumeSync(myLDHandle, period);
1051 }
1052
1053
1054 void LBDatabase::ReceiveIterationNo(int req_no, int local_iter_no) {
1055   CmiAssert(CkMyPe() == 0);
1056
1057   adaptive_struct.global_recv_iter_counter++;
1058   if (local_iter_no > adaptive_struct.global_max_iter_no) {
1059     adaptive_struct.global_max_iter_no = local_iter_no;
1060   }
1061
1062   int period;
1063   if (CkNumPes() == adaptive_struct.global_recv_iter_counter) {
1064
1065     if (adaptive_struct.global_max_iter_no > adaptive_struct.tentative_max_iter_no) {
1066       adaptive_struct.tentative_max_iter_no = adaptive_struct.global_max_iter_no;
1067     }
1068     period = (adaptive_struct.tentative_period > adaptive_struct.global_max_iter_no) ? adaptive_struct.tentative_period : adaptive_struct.global_max_iter_no + 1;
1069     // If no one has gone into load balancing stage, then we can safely change
1070     // the period otherwise keep the old period.
1071     if (adaptive_struct.global_max_iter_no < adaptive_struct.final_lb_period) {
1072       adaptive_struct.tentative_period = period;
1073       CkPrintf("Final lb_period CHANGED!%d\n", adaptive_struct.tentative_period);
1074     } else {
1075       adaptive_struct.tentative_period = adaptive_struct.final_lb_period;
1076       CkPrintf("Final lb_period NOT CHANGED!%d\n", adaptive_struct.tentative_period);
1077     }
1078     thisProxy.LoadBalanceDecisionFinal(req_no, adaptive_struct.tentative_period);
1079     adaptive_struct.in_progress = false;
1080     adaptive_struct.global_recv_iter_counter = 0;
1081   }
1082 }
1083
1084 int LBDatabase::getPredictedLBPeriod(bool& is_tentative) {
1085   // If tentative and final_lb_period are the same, then the decision has been
1086   // made but if not, they are in the middle of consensus, hence return the
1087   // lease of the two
1088   if (adaptive_struct.tentative_period != adaptive_struct.final_lb_period) {
1089     is_tentative = true;
1090   } else {
1091     is_tentative = false;
1092   }
1093   if (adaptive_struct.tentative_period < adaptive_struct.final_lb_period) {
1094     return adaptive_struct.tentative_period;
1095    } else {
1096      return adaptive_struct.final_lb_period;
1097    }
1098 }
1099
1100 // Called by CentralLB to indicate that the LB strategy and migration is in
1101 // progress.
1102 void LBDatabase::ResetAdaptive() {
1103   adaptive_struct.lb_iteration_no = -1;
1104   lb_in_progress = true;
1105 }
1106
1107 void LBDatabase::HandleAdaptiveNoObj() {
1108 #if EXTRA_FEATURE
1109   adaptive_struct.lb_iteration_no++;
1110   //CkPrintf("HandleAdaptiveNoObj %d\n", adaptive_struct.lb_iteration_no);
1111   thisProxy[0].RegisterNoObjCallback(CkMyPe());
1112   TriggerAdaptiveReduction();
1113 #endif
1114 }
1115
1116 void LBDatabase::RegisterNoObjCallback(int index) {
1117 #if EXTRA_FEATURE
1118   if (lb_in_progress) {
1119     lbdb_no_obj_callback.clear();
1120     //CkPrintf("Clearing and registering\n");
1121     lb_in_progress = false;
1122   }
1123   lbdb_no_obj_callback.push_back(index);
1124   CkPrintf("Registered %d to have no objs.\n", index);
1125
1126   // If collection has already happened and this is second iteration, then
1127   // trigger reduction.
1128   if (adaptive_struct.lb_iteration_no != -1) {
1129     //CkPrintf("Collection already started now %d so kick in\n", adaptive_struct.lb_iteration_no);
1130     thisProxy[index].TriggerAdaptiveReduction();
1131   }
1132 #endif
1133 }
1134
1135 void LBDatabase::TriggerAdaptiveReduction() {
1136 #if EXTRA_FEATURE
1137   adaptive_struct.lb_iteration_no++;
1138   //CkPrintf("Trigger adaptive for %d\n", adaptive_struct.lb_iteration_no);
1139   double lb_data[6];
1140   lb_data[0] = adaptive_struct.lb_iteration_no;
1141   lb_data[1] = 1;
1142   lb_data[2] = 0.0;
1143   lb_data[3] = 0.0;
1144   lb_data[4] = 0.0;
1145   lb_data[5] = 0.0;
1146
1147   // CkPrintf("   [%d] sends total load %lf idle time %lf ratio of idle/load %lf at iter %d\n", CkMyPe(),
1148   //     total_load_vec[iteration], idle_time,
1149   //     idle_time/total_load_vec[iteration], adaptive_struct.lb_iteration_no);
1150
1151   CkCallback cb(CkIndex_LBDatabase::ReceiveMinStats((CkReductionMsg*)NULL), thisProxy[0]);
1152   contribute(6*sizeof(double), lb_data, lbDataCollectionType, cb);
1153 #endif
1154 }
1155
1156
1157 bool LBDatabase::isStrategyComm() {
1158   return adaptive_struct.doCommStrategy;
1159 }
1160
1161 void LBDatabase::SetMigrationCost(double lb_migration_cost) {
1162   adaptive_struct.lb_migration_cost = lb_migration_cost;
1163 }
1164
1165 void LBDatabase::SetStrategyCost(double lb_strategy_cost) {
1166   adaptive_struct.lb_strategy_cost = lb_strategy_cost;
1167 }
1168
1169 void LBDatabase::UpdateAfterLBData(int lb, double lb_max, double lb_avg, double
1170     local_comm, double remote_comm) {
1171   adaptive_struct.last_lb_type = lb;
1172   if (lb == 0) {
1173     adaptive_struct.greedy_info.max_avg_ratio = lb_max/lb_avg;
1174   } else if (lb == 1) {
1175     adaptive_struct.refine_info.max_avg_ratio = lb_max/lb_avg;
1176   } else if (lb == 2) {
1177     adaptive_struct.comm_info.remote_local_ratio = remote_comm/local_comm;
1178   } else if (lb == 3) {
1179     adaptive_struct.comm_refine_info.remote_local_ratio =
1180     remote_comm/local_comm;
1181   }
1182 }
1183
1184 void LBDatabase::UpdateAfterLBData(double max_load, double max_cpu, double
1185 avg_load) {
1186   if (adaptive_struct.last_lb_type == -1) {
1187     adaptive_struct.last_lb_type = 0;
1188   }
1189   int lb = adaptive_struct.last_lb_type;
1190   //CkPrintf("Storing data after lb ratio %lf for lb %d\n", max_load/avg_load, lb);
1191   if (lb == 0) {
1192     adaptive_struct.greedy_info.max_avg_ratio = max_load/avg_load;
1193   } else if (lb == 1) {
1194     adaptive_struct.refine_info.max_avg_ratio = max_load/avg_load;
1195   } else if (lb == 2) {
1196     adaptive_struct.comm_info.max_avg_ratio = max_load/avg_load;
1197   } else if (lb == 3) {
1198     adaptive_struct.comm_refine_info.max_avg_ratio = max_load/avg_load;
1199   }
1200 }
1201
1202 void LBDatabase::UpdateAfterLBComm(double alpha_beta_to_load) {
1203   CkPrintf("Setting alpha beta %lf\n", alpha_beta_to_load);
1204   alpha_beta_cost_to_load = alpha_beta_to_load;
1205 }
1206
1207
1208 void LBDatabase::GetPrevLBData(int& lb_type, double& lb_max_avg_ratio, double&
1209     remote_local_comm_ratio) {
1210   lb_type = adaptive_struct.last_lb_type;
1211   lb_max_avg_ratio = 1;
1212   remote_local_comm_ratio = 1;
1213   GetLBDataForLB(lb_type, lb_max_avg_ratio, remote_local_comm_ratio);
1214 }
1215
1216 void LBDatabase::GetLBDataForLB(int lb_type, double& lb_max_avg_ratio, double&
1217     remote_local_comm_ratio) {
1218   if (lb_type == 0) {
1219     lb_max_avg_ratio = adaptive_struct.greedy_info.max_avg_ratio;
1220   } else if (lb_type == 1) {
1221     lb_max_avg_ratio = adaptive_struct.refine_info.max_avg_ratio;
1222   } else if (lb_type == 2) {
1223     remote_local_comm_ratio = adaptive_struct.comm_info.remote_local_ratio;
1224   } else if (lb_type == 3) {
1225     remote_local_comm_ratio =
1226        adaptive_struct.comm_refine_info.remote_local_ratio;
1227   }
1228 }
1229
1230 /*
1231   callable from user's code
1232 */
1233 void TurnManualLBOn()
1234 {
1235 #if CMK_LBDB_ON
1236    LBDatabase * myLbdb = LBDatabase::Object();
1237    if (myLbdb) {
1238      myLbdb->TurnManualLBOn();
1239    }
1240    else {
1241      LBDatabase::manualOn = 1;
1242    }
1243 #endif
1244 }
1245
1246 void TurnManualLBOff()
1247 {
1248 #if CMK_LBDB_ON
1249    LBDatabase * myLbdb = LBDatabase::Object();
1250    if (myLbdb) {
1251      myLbdb->TurnManualLBOff();
1252    }
1253    else {
1254      LBDatabase::manualOn = 0;
1255    }
1256 #endif
1257 }
1258
1259 extern "C" void LBTurnInstrumentOn() {
1260 #if CMK_LBDB_ON
1261   if (CkpvAccess(lbdatabaseInited))
1262     LBDatabase::Object()->CollectStatsOn();
1263   else
1264     _lb_args.statsOn() = 1;
1265 #endif
1266 }
1267
1268 extern "C" void LBTurnInstrumentOff() {
1269 #if CMK_LBDB_ON
1270   if (CkpvAccess(lbdatabaseInited))
1271     LBDatabase::Object()->CollectStatsOff();
1272   else
1273     _lb_args.statsOn() = 0;
1274 #endif
1275 }
1276 void LBClearLoads() {
1277 #if CMK_LBDB_ON
1278   LBDatabase::Object()->ClearLoads();
1279 #endif
1280 }
1281
1282 void LBTurnPredictorOn(LBPredictorFunction *model) {
1283 #if CMK_LBDB_ON
1284   LBDatabase::Object()->PredictorOn(model);
1285 #endif
1286 }
1287
1288 void LBTurnPredictorOn(LBPredictorFunction *model, int wind) {
1289 #if CMK_LBDB_ON
1290   LBDatabase::Object()->PredictorOn(model, wind);
1291 #endif
1292 }
1293
1294 void LBTurnPredictorOff() {
1295 #if CMK_LBDB_ON
1296   LBDatabase::Object()->PredictorOff();
1297 #endif
1298 }
1299
1300 void LBChangePredictor(LBPredictorFunction *model) {
1301 #if CMK_LBDB_ON
1302   LBDatabase::Object()->ChangePredictor(model);
1303 #endif
1304 }
1305
1306 void LBSetPeriod(double second) {
1307 #if CMK_LBDB_ON
1308   if (CkpvAccess(lbdatabaseInited))
1309     LBDatabase::Object()->SetLBPeriod(second);
1310   else
1311     _lb_args.lbperiod() = second;
1312 #endif
1313 }
1314
1315 #include "LBDatabase.def.h"
1316
1317 /*@}*/