more cleanup
[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 50
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 #define MIN_STATS 6
26
27 #   define DEBAD(x) /*CkPrintf x*/
28 #   define EXTRA_FEATURE 0
29
30 CkGroupID _lbdb;
31
32 CkpvDeclare(int, numLoadBalancers);  /**< num of lb created */
33 CkpvDeclare(int, hasNullLB);         /**< true if NullLB is created */
34 CkpvDeclare(int, lbdatabaseInited);  /**< true if lbdatabase is inited */
35
36 // command line options
37 CkLBArgs _lb_args;
38 int _lb_predict=0;
39 int _lb_predict_delay=10;
40 int _lb_predict_window=20;
41
42 // registry class stores all load balancers linked and created at runtime
43 class LBDBRegistry {
44 friend class LBDBInit;
45 friend class LBDatabase;
46 private:
47   // table for all available LBs linked in
48   struct LBDBEntry {
49     const char *name;
50     LBCreateFn  cfn;
51     LBAllocFn   afn;
52     const char *help;
53     int         shown;          // if 0, donot show in help page
54     LBDBEntry(): name(0), cfn(0), afn(0), help(0), shown(1) {}
55     LBDBEntry(int) {}
56     LBDBEntry(const char *n, LBCreateFn cf, LBAllocFn af,
57               const char *h, int show=1):
58       name(n), cfn(cf), afn(af), help(h), shown(show) {};
59   };
60   CkVec<LBDBEntry> lbtables;            // a list of available LBs linked
61   CkVec<const char *>   compile_lbs;    // load balancers at compile time
62   CkVec<const char *>   runtime_lbs;    // load balancers at run time
63 public:
64   LBDBRegistry() {}
65   void displayLBs()
66   {
67     CmiPrintf("\nAvailable load balancers:\n");
68     for (int i=0; i<lbtables.length(); i++) {
69       LBDBEntry &entry = lbtables[i];
70       if (entry.shown) CmiPrintf("* %s: %s\n", entry.name, entry.help);
71     }
72     CmiPrintf("\n");
73   }
74   void addEntry(const char *name, LBCreateFn fn, LBAllocFn afn, const char *help, int shown) {
75     lbtables.push_back(LBDBEntry(name, fn, afn, help, shown));
76   }
77   void addCompiletimeBalancer(const char *name) {
78     compile_lbs.push_back(name);
79   }
80   void addRuntimeBalancer(const char *name) {
81     runtime_lbs.push_back(name);
82   }
83   LBCreateFn search(const char *name) {
84     char *ptr = strpbrk((char *)name, ":,");
85     int slen = ptr!=NULL?ptr-name:strlen(name);
86     for (int i=0; i<lbtables.length(); i++)
87       if (0==strncmp(name, lbtables[i].name, slen)) return lbtables[i].cfn;
88     return NULL;
89   }
90   LBAllocFn getLBAllocFn(const char *name) {
91     char *ptr = strpbrk((char *)name, ":,");
92     int slen = ptr-name;
93     for (int i=0; i<lbtables.length(); i++)
94       if (0==strncmp(name, lbtables[i].name, slen)) return lbtables[i].afn;
95     return NULL;
96   }
97 };
98
99 static LBDBRegistry lbRegistry;
100
101 void LBDefaultCreate(const char *lbname)
102 {
103   lbRegistry.addCompiletimeBalancer(lbname);
104 }
105
106 // default is to show the helper
107 void LBRegisterBalancer(const char *name, LBCreateFn fn, LBAllocFn afn, const char *help, int shown)
108 {
109   lbRegistry.addEntry(name, fn, afn, help, shown);
110 }
111
112 LBAllocFn getLBAllocFn(char *lbname) {
113     return lbRegistry.getLBAllocFn(lbname);
114 }
115
116 LBCreateFn getLBCreateFn(const char *lbname) {
117     return lbRegistry.search(lbname);
118 }
119 // create a load balancer group using the strategy name
120 static void createLoadBalancer(const char *lbname)
121 {
122     LBCreateFn fn = lbRegistry.search(lbname);
123     if (!fn) {    // invalid lb name
124       CmiPrintf("Abort: Unknown load balancer: '%s'!\n", lbname);
125       lbRegistry.displayLBs();    // display help page
126       CkAbort("Abort");
127     }
128     // invoke function to create load balancer
129     fn();
130 }
131
132 // mainchare
133 LBDBInit::LBDBInit(CkArgMsg *m)
134 {
135 #if CMK_LBDB_ON
136   _lbdb = CProxy_LBDatabase::ckNew();
137
138   // runtime specified load balancer
139   if (lbRegistry.runtime_lbs.size() > 0) {
140     for (int i=0; i<lbRegistry.runtime_lbs.size(); i++) {
141       const char *balancer = lbRegistry.runtime_lbs[i];
142       createLoadBalancer(balancer);
143     }
144   }
145   else if (lbRegistry.compile_lbs.size() > 0) {
146     for (int i=0; i<lbRegistry.compile_lbs.size(); i++) {
147       const char* balancer = lbRegistry.compile_lbs[i];
148       createLoadBalancer(balancer);
149     }
150   }
151   else {
152     // NullLB is the default when none of above lb created
153     // note user may create his own load balancer in his code manually like
154     // in NAMD, but never mind NullLB can disable itself if there is
155     // a non NULL LB.
156     createLoadBalancer("NullLB");
157   }
158
159   // simulation mode
160   if (LBSimulation::doSimulation) {
161     CmiPrintf("Charm++> Entering Load Balancer Simulation Mode ... \n");
162     CProxy_LBDatabase(_lbdb).ckLocalBranch()->StartLB();
163   }
164 #endif
165   delete m;
166 }
167
168 // called from init.C
169 void _loadbalancerInit()
170 {
171   CkpvInitialize(int, lbdatabaseInited);
172   CkpvAccess(lbdatabaseInited) = 0;
173   CkpvInitialize(int, numLoadBalancers);
174   CkpvAccess(numLoadBalancers) = 0;
175   CkpvInitialize(int, hasNullLB);
176   CkpvAccess(hasNullLB) = 0;
177
178   char **argv = CkGetArgv();
179   char *balancer = NULL;
180   CmiArgGroup("Charm++","Load Balancer");
181   while (CmiGetArgStringDesc(argv, "+balancer", &balancer, "Use this load balancer")) {
182     if (CkMyRank() == 0)
183       lbRegistry.addRuntimeBalancer(balancer);   /* lbRegistry is a static */
184   }
185
186   // set up init value for LBPeriod time in seconds
187   // it can also be set by calling LDSetLBPeriod()
188   CmiGetArgDoubleDesc(argv,"+LBPeriod", &_lb_args.lbperiod(),"the minimum time period in seconds allowed for two consecutive automatic load balancing");
189   _lb_args.loop() = CmiGetArgFlagDesc(argv, "+LBLoop", "Use multiple load balancing strategies in loop");
190
191   // now called in cldb.c: CldModuleGeneralInit()
192   // registerLBTopos();
193   CmiGetArgStringDesc(argv, "+LBTopo", &_lbtopo, "define load balancing topology");
194   //Read the K parameter for RefineKLB
195   CmiGetArgIntDesc(argv, "+LBNumMoves", &_lb_args.percentMovesAllowed() , "Percentage of chares to be moved (used by RefineKLB) [0-100]");
196
197   /**************** FUTURE PREDICTOR ****************/
198   _lb_predict = CmiGetArgFlagDesc(argv, "+LBPredictor", "Turn on LB future predictor");
199   CmiGetArgIntDesc(argv, "+LBPredictorDelay", &_lb_predict_delay, "Number of balance steps before learning a model");
200   CmiGetArgIntDesc(argv, "+LBPredictorWindow", &_lb_predict_window, "Number of steps to use to learn a model");
201   if (_lb_predict_window < _lb_predict_delay) {
202     CmiPrintf("LB> [%d] Argument LBPredictorWindow (%d) less than LBPredictorDelay (%d) , fixing\n", CkMyPe(), _lb_predict_window, _lb_predict_delay);
203     _lb_predict_delay = _lb_predict_window;
204   }
205
206   /******************* SIMULATION *******************/
207   // get the step number at which to dump the LB database
208   CmiGetArgIntDesc(argv, "+LBVersion", &_lb_args.lbversion(), "LB database file version number");
209   CmiGetArgIntDesc(argv, "+LBCentPE", &_lb_args.central_pe(), "CentralLB processor");
210   int _lb_dump_activated = 0;
211   if (CmiGetArgIntDesc(argv, "+LBDump", &LBSimulation::dumpStep, "Dump the LB state from this step"))
212     _lb_dump_activated = 1;
213   if (_lb_dump_activated && LBSimulation::dumpStep < 0) {
214     CmiPrintf("LB> Argument LBDump (%d) negative, setting to 0\n",LBSimulation::dumpStep);
215     LBSimulation::dumpStep = 0;
216   }
217   CmiGetArgIntDesc(argv, "+LBDumpSteps", &LBSimulation::dumpStepSize, "Dump the LB state for this amount of steps");
218   if (LBSimulation::dumpStepSize <= 0) {
219     CmiPrintf("LB> Argument LBDumpSteps (%d) too small, setting to 1\n",LBSimulation::dumpStepSize);
220     LBSimulation::dumpStepSize = 1;
221   }
222   CmiGetArgStringDesc(argv, "+LBDumpFile", &LBSimulation::dumpFile, "Set the LB state file name");
223   // get the simulation flag and number. Now the flag can also be avoided by the presence of the number
224   LBSimulation::doSimulation = CmiGetArgIntDesc(argv, "+LBSim", &LBSimulation::simStep, "Read LB state from LBDumpFile since this step");
225   // check for stupid LBSim parameter
226   if (LBSimulation::doSimulation && LBSimulation::simStep < 0) {
227     CmiPrintf("LB> Argument LBSim (%d) invalid, should be >= 0\n");
228     CkExit();
229     return;
230   }
231   CmiGetArgIntDesc(argv, "+LBSimSteps", &LBSimulation::simStepSize, "Read LB state for this number of steps");
232   if (LBSimulation::simStepSize <= 0) {
233     CmiPrintf("LB> Argument LBSimSteps (%d) too small, setting to 1\n",LBSimulation::simStepSize);
234     LBSimulation::simStepSize = 1;
235   }
236
237
238   LBSimulation::simProcs = 0;
239   CmiGetArgIntDesc(argv, "+LBSimProcs", &LBSimulation::simProcs, "Number of target processors.");
240
241   LBSimulation::showDecisionsOnly =
242     CmiGetArgFlagDesc(argv, "+LBShowDecisions",
243                       "Write to File: Load Balancing Object to Processor Map decisions during LB Simulation");
244
245   // force a global barrier after migration done
246   _lb_args.syncResume() = CmiGetArgFlagDesc(argv, "+LBSyncResume",
247                   "LB performs a barrier after migration is finished");
248
249   // both +LBDebug and +LBDebug level should work
250   if (!CmiGetArgIntDesc(argv, "+LBDebug", &_lb_args.debug(),
251                                           "Turn on LB debugging printouts"))
252     _lb_args.debug() = CmiGetArgFlagDesc(argv, "+LBDebug",
253                                              "Turn on LB debugging printouts");
254
255   // getting the size of the team with +teamSize
256   if (!CmiGetArgIntDesc(argv, "+teamSize", &_lb_args.teamSize(),
257                                           "Team size"))
258     _lb_args.teamSize() = 1;
259
260   // ask to print summary/quality of load balancer
261   _lb_args.printSummary() = CmiGetArgFlagDesc(argv, "+LBPrintSummary",
262                 "Print load balancing result summary");
263
264   // to ignore baclground load
265   _lb_args.ignoreBgLoad() = CmiGetArgFlagDesc(argv, "+LBNoBackground",
266                       "Load balancer ignores the background load.");
267 #ifdef __BIGSIM__
268   _lb_args.ignoreBgLoad() = 1;
269 #endif
270   _lb_args.migObjOnly() = CmiGetArgFlagDesc(argv, "+LBObjOnly",
271                       "Only load balancing migratable objects, ignoring all others.");
272   if (_lb_args.migObjOnly()) _lb_args.ignoreBgLoad() = 1;
273
274   // assume all CPUs are identical
275   _lb_args.testPeSpeed() = CmiGetArgFlagDesc(argv, "+LBTestPESpeed",
276                       "Load balancer test all CPUs speed.");
277   _lb_args.samePeSpeed() = CmiGetArgFlagDesc(argv, "+LBSameCpus",
278                       "Load balancer assumes all CPUs are of same speed.");
279   if (!_lb_args.testPeSpeed()) _lb_args.samePeSpeed() = 1;
280
281   _lb_args.useCpuTime() = CmiGetArgFlagDesc(argv, "+LBUseCpuTime",
282                       "Load balancer uses CPU time instead of wallclock time.");
283
284   // turn instrumentation off at startup
285   _lb_args.statsOn() = !CmiGetArgFlagDesc(argv, "+LBOff",
286                         "Turn load balancer instrumentation off");
287
288   // turn instrumentation of communicatin off at startup
289   _lb_args.traceComm() = !CmiGetArgFlagDesc(argv, "+LBCommOff",
290                 "Turn load balancer instrumentation of communication off");
291
292   // set alpha and beeta
293   _lb_args.alpha() = PER_MESSAGE_SEND_OVERHEAD_DEFAULT;
294   _lb_args.beeta() = PER_BYTE_SEND_OVERHEAD_DEFAULT;
295   CmiGetArgDoubleDesc(argv,"+LBAlpha", &_lb_args.alpha(),
296                            "per message send overhead");
297   CmiGetArgDoubleDesc(argv,"+LBBeta", &_lb_args.beeta(),
298                            "per byte send overhead");
299
300   if (CkMyPe() == 0) {
301     if (_lb_args.debug()) {
302       CmiPrintf("CharmLB> Verbose level %d, load balancing period: %g seconds\n", _lb_args.debug(), _lb_args.lbperiod());
303     }
304     if (_lb_args.debug() > 1) {
305       CmiPrintf("CharmLB> Topology %s alpha: %es beta: %es.\n", _lbtopo, _lb_args.alpha(), _lb_args.beeta());
306     }
307     if (_lb_args.printSummary())
308       CmiPrintf("CharmLB> Load balancer print summary of load balancing result.\n");
309     if (_lb_args.ignoreBgLoad())
310       CmiPrintf("CharmLB> Load balancer ignores processor background load.\n");
311     if (_lb_args.samePeSpeed())
312       CmiPrintf("CharmLB> Load balancer assumes all CPUs are same.\n");
313     if (_lb_args.useCpuTime())
314       CmiPrintf("CharmLB> Load balancer uses CPU time instead of wallclock time.\n");
315     if (LBSimulation::doSimulation)
316       CmiPrintf("CharmLB> Load balancer running in simulation mode on file '%s' version %d.\n", LBSimulation::dumpFile, _lb_args.lbversion());
317     if (_lb_args.statsOn()==0)
318       CkPrintf("CharmLB> Load balancing instrumentation is off.\n");
319     if (_lb_args.traceComm()==0)
320       CkPrintf("CharmLB> Load balancing instrumentation for communication is off.\n");
321     if (_lb_args.migObjOnly())
322       CkPrintf("LB> Load balancing strategy ignores non-migratable objects.\n");
323   }
324 }
325
326 int LBDatabase::manualOn = 0;
327 char *LBDatabase::avail_vector = NULL;
328 CmiNodeLock avail_vector_lock;
329
330 static LBRealType * _expectedLoad = NULL;
331
332 void LBDatabase::initnodeFn()
333 {
334   int proc;
335   int num_proc = CkNumPes();
336   avail_vector= new char[num_proc];
337   for(proc = 0; proc < num_proc; proc++)
338       avail_vector[proc] = 1;
339   avail_vector_lock = CmiCreateLock();
340
341   _expectedLoad = new LBRealType[num_proc];
342   for (proc=0; proc<num_proc; proc++) _expectedLoad[proc]=0.0;
343
344   //CkPrintf("Total objs in %d is %d\n", CkMyPe(), getLBDB()->ObjDataCount());
345 }
346
347 // called my constructor
348 void LBDatabase::init(void)
349 {
350   //thisProxy = CProxy_LBDatabase(thisgroup);
351   myLDHandle = LDCreate();
352   mystep = 0;
353   nloadbalancers = 0;
354   new_ld_balancer = 0;
355   metabalancer = (MetaBalancer *)CkLocalBranch(_metalb);
356
357   CkpvAccess(lbdatabaseInited) = 1;
358 #if CMK_LBDB_ON
359   if (manualOn) TurnManualLBOn();
360 #endif
361
362 }
363
364 LBDatabase::LastLBInfo::LastLBInfo()
365 {
366   expectedLoad = _expectedLoad;
367 }
368
369 void LBDatabase::get_avail_vector(char * bitmap) {
370     CmiAssert(bitmap && avail_vector);
371     const int num_proc = CkNumPes();
372     for(int proc = 0; proc < num_proc; proc++){
373       bitmap[proc] = avail_vector[proc];
374     }
375 }
376
377 // new_ld == -1(default) : calcualte a new ld
378 //           -2 : ignore new ld
379 //           >=0: given a new ld
380 void LBDatabase::set_avail_vector(char * bitmap, int new_ld){
381     int assigned = 0;
382     const int num_proc = CkNumPes();
383     if (new_ld == -2) assigned = 1;
384     else if (new_ld >= 0) {
385       CmiAssert(new_ld < num_proc);
386       new_ld_balancer = new_ld;
387       assigned = 1;
388     }
389     CmiAssert(bitmap && avail_vector);
390     for(int count = 0; count < num_proc; count++){
391         avail_vector[count] = bitmap[count];
392         if((bitmap[count] == 1) && !assigned){
393             new_ld_balancer = count;
394             assigned = 1;
395         }
396     }
397 }
398
399 // called in CreateFooLB() when multiple load balancers are created
400 // on PE0, BaseLB of each load balancer applies a ticket number
401 // and broadcast the ticket number to all processors
402 int LBDatabase::getLoadbalancerTicket()  {
403   int seq = nloadbalancers;
404   nloadbalancers ++;
405   loadbalancers.resize(nloadbalancers);
406   loadbalancers[seq] = NULL;
407   return seq;
408 }
409
410 void LBDatabase::addLoadbalancer(BaseLB *lb, int seq) {
411 //  CmiPrintf("[%d] addLoadbalancer for seq %d\n", CkMyPe(), seq);
412   if (seq == -1) return;
413   if (CkMyPe() == 0) {
414     CmiAssert(seq < nloadbalancers);
415     if (loadbalancers[seq]) {
416       CmiPrintf("Duplicate load balancer created at %d\n", seq);
417       CmiAbort("LBDatabase");
418     }
419   }
420   else
421     nloadbalancers ++;
422   loadbalancers.resize(seq+1);
423   loadbalancers[seq] = lb;
424 }
425
426 // switch strategy in order
427 void LBDatabase::nextLoadbalancer(int seq) {
428   if (seq == -1) return;                // -1 means this is the only LB
429   int next = seq+1;
430   if (_lb_args.loop()) {
431     if (next == nloadbalancers) next = 0;
432   }
433   else {
434     if (next == nloadbalancers) next --;  // keep using the last one
435   }
436   if (seq != next) {
437     loadbalancers[seq]->turnOff();
438     CmiAssert(loadbalancers[next]);
439     loadbalancers[next]->turnOn();
440   }
441 }
442
443 // return the seq-th load balancer string name of
444 // it can be specified in either compile time or runtime
445 // runtime has higher priority
446 const char *LBDatabase::loadbalancer(int seq) {
447   if (lbRegistry.runtime_lbs.length()) {
448     CmiAssert(seq < lbRegistry.runtime_lbs.length());
449     return lbRegistry.runtime_lbs[seq];
450   }
451   else {
452     CmiAssert(seq < lbRegistry.compile_lbs.length());
453     return lbRegistry.compile_lbs[seq];
454   }
455 }
456
457 void LBDatabase::pup(PUP::er& p)
458 {
459   // NOTE if unpacking set metabalancer using the id
460         IrrGroup::pup(p);
461         // the memory should be already allocated
462         int np;
463         if (!p.isUnpacking()) np = CkNumPes();
464         p|np;
465         CmiAssert(avail_vector);
466         // in case number of processors changes
467         if (p.isUnpacking() && np > CkNumPes()) {
468                 CmiLock(avail_vector_lock);
469                 delete [] avail_vector;
470                 avail_vector = new char[np];
471                 for (int i=0; i<np; i++) avail_vector[i] = 1;
472                 CmiUnlock(avail_vector_lock);
473         }
474         p(avail_vector, np);
475         p|mystep;
476         if(p.isUnpacking()) {
477     nloadbalancers = 0;
478     metabalancer = (MetaBalancer*)CkLocalBranch(_metalb);
479   }
480 }
481
482
483 void LBDatabase::EstObjLoad(const LDObjHandle &_h, double cputime)
484 {
485 #if CMK_LBDB_ON
486   LBDB *const db = (LBDB*)(_h.omhandle.ldb.handle);
487   LBObj *const obj = db->LbObj(_h);
488
489   CmiAssert(obj != NULL);
490   obj->setTiming(cputime);
491 #endif
492 }
493
494 void LBDatabase::ResetAdaptive() {
495         if (metabalancer == NULL) {
496                 metabalancer = CProxy_MetaBalancer(_metalb).ckLocalBranch();
497         }
498         if (metabalancer != NULL) {
499                 metabalancer->ResetAdaptive();
500         }
501 }
502
503 void LBDatabase::DoneRegisteringObjects(LDOMHandle _om) {
504         LDDoneRegisteringObjects(_om);
505 #if CMK_LBDB_ON
506         if (metabalancer == NULL) {
507                 metabalancer = CProxy_MetaBalancer(_metalb).ckLocalBranch();
508         }
509         if (metabalancer != NULL && getLBDB()->ObjDataCount() == 0) {
510                 metabalancer->HandleAdaptiveNoObj();
511         }
512 #endif
513 }
514
515 void LBDatabase::ResumeClients() {
516 #if CMK_LBDB_ON
517   if (metabalancer == NULL) {
518     metabalancer = CProxy_MetaBalancer(_metalb).ckLocalBranch();
519   }
520   if (metabalancer != NULL) {
521     metabalancer->ResumeClients();
522   }
523 #endif
524   LDResumeClients(myLDHandle);
525 }
526
527 void LBDatabase::SetMigrationCost(double cost) {
528   if (metabalancer == NULL) {
529     metabalancer = (MetaBalancer *)CkLocalBranch(_metalb);
530   }
531   if (metabalancer != NULL)  {
532     metabalancer->SetMigrationCost(cost);
533   }
534 }
535
536 void LBDatabase::SetStrategyCost(double cost) {
537   if (metabalancer == NULL) {
538     metabalancer = (MetaBalancer *)CkLocalBranch(_metalb);
539   }
540   if (metabalancer != NULL)  {
541     metabalancer->SetStrategyCost(cost);
542   }
543 }
544
545 /*
546   callable from user's code
547 */
548 void TurnManualLBOn()
549 {
550 #if CMK_LBDB_ON
551    LBDatabase * myLbdb = LBDatabase::Object();
552    if (myLbdb) {
553      myLbdb->TurnManualLBOn();
554    }
555    else {
556      LBDatabase::manualOn = 1;
557    }
558 #endif
559 }
560
561 void TurnManualLBOff()
562 {
563 #if CMK_LBDB_ON
564    LBDatabase * myLbdb = LBDatabase::Object();
565    if (myLbdb) {
566      myLbdb->TurnManualLBOff();
567    }
568    else {
569      LBDatabase::manualOn = 0;
570    }
571 #endif
572 }
573
574 extern "C" void LBTurnInstrumentOn() {
575 #if CMK_LBDB_ON
576   if (CkpvAccess(lbdatabaseInited))
577     LBDatabase::Object()->CollectStatsOn();
578   else
579     _lb_args.statsOn() = 1;
580 #endif
581 }
582
583 extern "C" void LBTurnInstrumentOff() {
584 #if CMK_LBDB_ON
585   if (CkpvAccess(lbdatabaseInited))
586     LBDatabase::Object()->CollectStatsOff();
587   else
588     _lb_args.statsOn() = 0;
589 #endif
590 }
591 void LBClearLoads() {
592 #if CMK_LBDB_ON
593   LBDatabase::Object()->ClearLoads();
594 #endif
595 }
596
597 void LBTurnPredictorOn(LBPredictorFunction *model) {
598 #if CMK_LBDB_ON
599   LBDatabase::Object()->PredictorOn(model);
600 #endif
601 }
602
603 void LBTurnPredictorOn(LBPredictorFunction *model, int wind) {
604 #if CMK_LBDB_ON
605   LBDatabase::Object()->PredictorOn(model, wind);
606 #endif
607 }
608
609 void LBTurnPredictorOff() {
610 #if CMK_LBDB_ON
611   LBDatabase::Object()->PredictorOff();
612 #endif
613 }
614
615 void LBChangePredictor(LBPredictorFunction *model) {
616 #if CMK_LBDB_ON
617   LBDatabase::Object()->ChangePredictor(model);
618 #endif
619 }
620
621 void LBSetPeriod(double second) {
622 #if CMK_LBDB_ON
623   if (CkpvAccess(lbdatabaseInited))
624     LBDatabase::Object()->SetLBPeriod(second);
625   else
626     _lb_args.lbperiod() = second;
627 #endif
628 }
629
630 #include "LBDatabase.def.h"
631
632 /*@}*/