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