fixed getObjTime to actually get obj walltime.
[charm.git] / src / ck-ldb / lbdb.C
1 /*****************************************************************************
2  * $Source$
3  * $Author$
4  * $Date$
5  * $Revision$
6  *****************************************************************************/
7
8 /**
9  * \addtogroup CkLdb
10 */
11 /*@{*/
12
13 #include <converse.h>
14
15 #include <math.h>
16
17 #include "lbdb.h"
18 #include "LBObj.h"
19 #include "LBOM.h"
20 #include "LBDatabase.h"
21 #include "LBDBManager.h"
22   
23 #if CMK_LBDB_ON
24
25 extern "C" LDHandle LDCreate(void)
26 {
27   LDHandle h;
28   h.handle = (void*)(new LBDB);
29   return h;
30 }
31
32 extern "C" LDOMHandle LDRegisterOM(LDHandle _db, LDOMid _userID,
33                                    void *_userptr, LDCallbacks _callbacks)
34 {
35   LBDB *const db = (LBDB*)(_db.handle);
36   return db->AddOM(_userID, _userptr, _callbacks);
37 }
38
39 extern "C" void * LDOMUserData(LDOMHandle &_h)
40 {
41   LBDB *const db = (LBDB*)(_h.ldb.handle);
42   return db->LbOM(_h)->getUserData();
43 }
44
45 extern "C" void LDRegisteringObjects(LDOMHandle _h)
46 {
47   LBDB *const db = (LBDB*)(_h.ldb.handle);
48   db->RegisteringObjects(_h);
49 }
50
51 extern "C" void LDDoneRegisteringObjects(LDOMHandle _h)
52 {
53   LBDB *const db = (LBDB*)(_h.ldb.handle);
54   db->DoneRegisteringObjects(_h);
55 }
56
57 extern "C" LDObjHandle LDRegisterObj(LDOMHandle _h, LDObjid _id, 
58                                        void *_userData, int _migratable)
59 {
60   LBDB *const db = (LBDB*)(_h.ldb.handle);
61   return db->AddObj(_h, _id, _userData, (CmiBool)(_migratable));
62 }
63
64 extern "C" void LDUnregisterObj(LDObjHandle _h)
65 {
66   LBDB *const db = (LBDB*)(_h.omhandle.ldb.handle);
67   db->UnregisterObj(_h);
68   return;
69 }
70
71 extern "C" const LDObjHandle &LDGetObjHandle(LDHandle h, int oh)
72 {
73   LBDB *const db = (LBDB*)(h.handle);
74   LBObj *const obj = db->LbObjIdx(oh);
75   return obj->GetLDObjHandle();
76 }
77
78 extern "C" void LDObjTime(LDObjHandle &_h,
79                             double walltime, double cputime)
80 {
81   LBDB *const db = (LBDB*)(_h.omhandle.ldb.handle);
82   LBObj *const obj = db->LbObj(_h);
83   obj->IncrementTime(walltime,cputime);
84 }
85   
86 extern "C" void LDQueryKnownObjLoad(LDObjHandle &_h, double *wallT, double *cpuT)
87 {
88   LBDB *const db = (LBDB*)(_h.omhandle.ldb.handle);
89   LBObj *const obj = db->LbObj(_h);
90   obj->lastKnownLoad(wallT, cpuT);
91 }
92
93 extern "C" void * LDObjUserData(LDObjHandle &_h)
94 {
95   LBDB *const db = (LBDB*)(_h.omhandle.ldb.handle);
96   LBObj *const obj = db->LbObj(_h);
97   return obj->getUserData();
98 }
99
100 extern "C" void LDDumpDatabase(LDHandle _db)
101 {
102   LBDB *const db = (LBDB*)(_db.handle);
103   db->DumpDatabase();
104 }
105
106 extern "C" void LDNotifyMigrated(LDHandle _db, LDMigratedFn fn, void* data)
107 {
108   LBDB *const db = (LBDB*)(_db.handle);
109   db->NotifyMigrated(fn,data);
110 }
111
112 extern "C" void LDAddStartLBFn(LDHandle _db, LDStartLBFn fn, void* data)
113 {
114   LBDB *const db = (LBDB*)(_db.handle);
115   db->AddStartLBFn(fn,data);
116 }
117
118 extern "C" void LDRemoveStartLBFn(LDHandle _db, LDStartLBFn fn)
119 {
120   LBDB *const db = (LBDB*)(_db.handle);
121   db->RemoveStartLBFn(fn);
122 }
123
124 extern "C" void LDStartLB(LDHandle _db)
125 {
126   LBDB *const db = (LBDB*)(_db.handle);
127   db->StartLB();
128 }
129
130 extern "C" void LDTurnManualLBOn(LDHandle _db)
131 {
132   LBDB *const db = (LBDB*)(_db.handle);
133   db->TurnManualLBOn();
134 }
135
136 extern "C" void LDTurnManualLBOff(LDHandle _db)
137 {
138   LBDB *const db = (LBDB*)(_db.handle);
139   db->TurnManualLBOff();
140 }
141
142 extern "C" void LDTurnPredictorOn(LDHandle _db, void *model)
143 {
144   LBDB *const db = (LBDB*)(_db.handle);
145   db->TurnPredictorOn(model);
146 }
147
148 extern "C" void LDTurnPredictorOnWin(LDHandle _db, void *model, int wind)
149 {
150   LBDB *const db = (LBDB*)(_db.handle);
151   db->TurnPredictorOn(model, wind);
152 }
153
154 extern "C" void LDTurnPredictorOff(LDHandle _db)
155 {
156   LBDB *const db = (LBDB*)(_db.handle);
157   db->TurnPredictorOff();
158 }
159
160 /* the parameter model is really of class LBPredictorFunction in file LBDatabase.h */
161 extern "C" void LDChangePredictor(LDHandle _db, void *model)
162 {
163   LBDB *const db = (LBDB*)(_db.handle);
164   db->ChangePredictor(model);
165 }
166
167 extern "C" void LDCollectStatsOn(LDHandle _db)
168 {
169   LBDB *const db = (LBDB*)(_db.handle);
170
171   if (!db->StatsOn()) {
172     if (db->ObjIsRunning()) {
173        // stats on in the middle of an entry, start timer
174       const LDObjHandle &oh = db->RunningObj();
175       LBObj *obj = db->LbObj(oh);
176       obj->StartTimer();
177     }
178     db->TurnStatsOn();
179   }
180 }
181
182 extern "C" void LDCollectStatsOff(LDHandle _db)
183 {
184   LBDB *const db = (LBDB*)(_db.handle);
185   db->TurnStatsOff();
186 }
187
188 extern "C" int CLDCollectingStats(LDHandle _db)
189 {
190 //  LBDB *const db = (LBDB*)(_db.handle);
191 //
192 //  return db->StatsOn();
193   return LDCollectingStats(_db);
194 }
195
196 extern "C" int CLDRunningObject(LDHandle _h, LDObjHandle* _o)
197 {
198   return LDRunningObject(_h, _o);
199 }
200
201 extern "C" void LDObjectStart(const LDObjHandle &_h)
202 {
203   LBDB *const db = (LBDB*)(_h.omhandle.ldb.handle);
204
205   if (db->ObjIsRunning()) LDObjectStop(db->RunningObj());
206
207   db->SetRunningObj(_h);
208
209   if (db->StatsOn()) {
210     LBObj *const obj = db->LbObj(_h);
211     obj->StartTimer();
212   }
213 }
214
215 extern "C" void LDObjectStop(const LDObjHandle &_h)
216 {
217   LBDB *const db = (LBDB*)(_h.omhandle.ldb.handle);
218   LBObj *const obj = db->LbObj(_h);
219
220   if (db->StatsOn()) {
221     double walltime, cputime;
222     obj->StopTimer(&walltime,&cputime);
223     obj->IncrementTime(walltime,cputime);
224   }
225   db->NoRunningObj();
226 }
227
228 extern "C" void LDSend(const LDOMHandle &destOM, const LDObjid &destid, unsigned int bytes, int destObjProc, int force)
229 {
230   LBDB *const db = (LBDB*)(destOM.ldb.handle);
231   if (force || db->StatsOn() && _lb_args.traceComm())
232     db->Send(destOM,destid,bytes, destObjProc);
233 }
234
235 extern "C" void LDMulticastSend(const LDOMHandle &destOM, LDObjid *destids, int ndests, unsigned int bytes, int nMsgs)
236 {
237   LBDB *const db = (LBDB*)(destOM.ldb.handle);
238   if (db->StatsOn() && _lb_args.traceComm())
239     db->MulticastSend(destOM,destids,ndests,bytes,nMsgs);
240 }
241
242 extern "C" void LDBackgroundLoad(LDHandle _db,
243                                  double* walltime, double* cputime)
244 {
245   LBDB *const db = (LBDB*)(_db.handle);
246   db->BackgroundLoad(walltime,cputime);
247
248   return;
249 }
250
251 extern "C" void LDIdleTime(LDHandle _db,double* walltime)
252 {
253   LBDB *const db = (LBDB*)(_db.handle);
254   db->IdleTime(walltime);
255
256   return;
257 }
258
259 extern "C" void LDTotalTime(LDHandle _db,double* walltime, double* cputime)
260 {
261   LBDB *const db = (LBDB*)(_db.handle);
262   db->TotalTime(walltime,cputime);
263
264   return;
265 }
266
267 extern "C" void LDGetTime(LDHandle _db, double *total_walltime,
268                    double *total_cputime,
269                    double *idletime, double *bg_walltime, double *bg_cputime)
270 {
271   LBDB *const db = (LBDB*)(_db.handle);
272   db->GetTime(total_walltime, total_cputime, idletime, bg_walltime, bg_cputime);
273 }
274
275 extern "C" void LDNonMigratable(const LDObjHandle &h)
276 {
277   LBDB *const db = (LBDB*)(h.omhandle.ldb.handle);
278   LBObj *const obj = db->LbObj(h);
279
280   obj->SetMigratable(CmiFalse);
281 }
282
283 extern "C" void LDMigratable(const LDObjHandle &h)
284 {
285   LBDB *const db = (LBDB*)(h.omhandle.ldb.handle);
286   LBObj *const obj = db->LbObj(h);
287
288   obj->SetMigratable(CmiTrue);
289 }
290
291 extern "C" void LDAsyncMigrate(const LDObjHandle &h, CmiBool async)
292 {
293   LBDB *const db = (LBDB*)(h.omhandle.ldb.handle);
294   LBObj *const obj = db->LbObj(h);
295
296   obj->UseAsyncMigrate(async);
297 }
298
299 extern "C" void LDClearLoads(LDHandle _db)
300 {
301   LBDB *const db = (LBDB*)(_db.handle);
302
303   db->ClearLoads();
304 }
305
306 extern "C" int LDGetObjDataSz(LDHandle _db)
307 {
308   LBDB *const db = (LBDB*)(_db.handle);
309
310   return db->ObjDataCount();
311 }
312
313 extern "C" void LDGetObjData(LDHandle _db, LDObjData *data)
314 {
315   LBDB *const db = (LBDB*)(_db.handle);
316
317   db->GetObjData(data);
318 }
319
320 extern "C" int LDGetCommDataSz(LDHandle _db)
321 {
322   LBDB *const db = (LBDB*)(_db.handle);
323
324   return db->CommDataCount();
325 }
326
327 extern "C" void LDGetCommData(LDHandle _db, LDCommData *data)
328 {
329   LBDB *const db = (LBDB*)(_db.handle);
330
331   db->GetCommData(data);
332   return;
333 }
334
335 extern "C" int LDMigrate(LDObjHandle _h, int dest)
336 {
337   LBDB *const db = (LBDB*)(_h.omhandle.ldb.handle);
338
339   return db->Migrate(_h,dest);
340 }
341
342 extern "C" void LDMigrated(LDObjHandle _h, int waitBarrier)
343 {
344   LBDB *const db = (LBDB*)(_h.omhandle.ldb.handle);
345
346   db->Migrated(_h, waitBarrier);
347 }
348
349 extern "C" LDBarrierClient 
350 LDAddLocalBarrierClient(LDHandle _db, LDResumeFn fn, void* data)
351 {
352   LBDB *const db = (LBDB*)(_db.handle);
353
354   return db->AddLocalBarrierClient(fn,data);
355 }
356
357 extern "C" void LDRemoveLocalBarrierClient(LDHandle _db, LDBarrierClient h)
358 {
359   LBDB *const db = (LBDB*)(_db.handle);
360
361   db->RemoveLocalBarrierClient(h);
362 }
363
364 extern "C" LDBarrierReceiver 
365 LDAddLocalBarrierReceiver(LDHandle _db,LDBarrierFn fn, void* data)
366 {
367   LBDB *const db = (LBDB*)(_db.handle);
368
369   return db->AddLocalBarrierReceiver(fn,data);
370 }
371
372 extern "C" void 
373 LDRemoveLocalBarrierReceiver(LDHandle _db,LDBarrierReceiver h)
374 {
375   LBDB *const db = (LBDB*)(_db.handle);
376
377   db->RemoveLocalBarrierReceiver(h);
378 }
379
380 extern "C" void LDAtLocalBarrier(LDHandle _db, LDBarrierClient h)
381 {
382   LBDB *const db = (LBDB*)(_db.handle);
383         
384   db->AtLocalBarrier(h);
385 }
386
387 extern "C" void LDLocalBarrierOn(LDHandle _db)
388 {
389   LBDB *const db = (LBDB*)(_db.handle);
390
391   db->LocalBarrierOn();
392 }
393
394 extern "C" void LDLocalBarrierOff(LDHandle _db)
395 {
396   LBDB *const db = (LBDB*)(_db.handle);
397
398   db->LocalBarrierOff();
399 }
400
401
402 extern "C" void LDResumeClients(LDHandle _db)
403 {
404   LBDB *const db = (LBDB*)(_db.handle);
405
406   db->ResumeClients();
407 }
408
409 static void work(int iter_block, int* result) {
410   int i;
411   *result = 1;
412   for(i=0; i < iter_block; i++) {
413     double b=0.1 + 0.1 * *result;
414     *result=(int)(sqrt(1+cos(b * 1.57)));
415   }
416 }
417
418 extern "C" int LDProcessorSpeed()
419 {
420   // for SMP version, if one processor have done this testing,
421   // we can skip the other processors by remember the number here
422   static int thisProcessorSpeed = -1;
423
424   if (_lb_args.samePeSpeed() || CkNumPes() == 1)  // I think it is safe to assume that we can
425     return 1;            // skip this if we are only using 1 PE
426   
427   if (thisProcessorSpeed != -1) return thisProcessorSpeed;
428
429   //if (CkMyPe()==0) CkPrintf("Measuring processor speeds...");
430
431   static int result=0;  // I don't care what this is, its just for
432                         // timing, so this is thread safe.
433   int wps = 0;
434   const double elapse = 0.4;
435   // First, count how many iterations for .2 second.
436   // Since we are doing lots of function calls, this will be rough
437   const double end_time = CmiCpuTimer()+elapse;
438   wps = 0;
439   while(CmiCpuTimer() < end_time) {
440     work(1000,&result);
441     wps+=1000;
442   }
443
444   // Now we have a rough idea of how many iterations there are per
445   // second, so just perform a few cycles of correction by
446   // running for what we think is 1 second.  Then correct
447   // the number of iterations per second to make it closer
448   // to the correct value
449   
450   for(int i=0; i < 2; i++) {
451     const double start_time = CmiCpuTimer();
452     work(wps,&result);
453     const double end_time = CmiCpuTimer();
454     const double correction = elapse / (end_time-start_time);
455     wps = (int)((double)wps * correction + 0.5);
456   }
457   
458   // If necessary, do a check now
459   //    const double start_time3 = CmiWallTimer();
460   //    work(msec * 1e-3 * wps);
461   //    const double end_time3 = CmiWallTimer();
462   //    CkPrintf("[%d] Work block size is %d %d %f\n",
463   //         thisIndex,wps,msec,1.e3*(end_time3-start_time3));
464   thisProcessorSpeed = wps;
465
466   //if (CkMyPe()==0) CkPrintf(" Done.\n");
467
468   return wps;
469 }
470
471 extern "C" void LDSetLBPeriod(LDHandle _db, double s)   // s is in seconds
472 {
473   LBDB *const db = (LBDB*)(_db.handle);
474   db->SetPeriod(s);
475 }
476
477 extern "C" double LDGetLBPeriod(LDHandle _db)   // s is in seconds
478 {
479   LBDB *const db = (LBDB*)(_db.handle);
480   return db->GetPeriod();
481 }
482
483 /*
484 // to be implemented
485 extern "C" void LDEstObjLoad(LDObjHandle h, double load)
486 {
487 }
488 */
489
490 // to be implemented
491 extern "C" void LDQueryEstLoad(LDHandle bdb)
492 {
493 }
494
495 extern "C" int LDMemusage(LDHandle _db) 
496 {
497   LBDB *const db = (LBDB*)(_db.handle);
498   return db->useMem();
499 }
500
501 #else
502 extern "C" int LDProcessorSpeed() { return 1; }
503 #endif // CMK_LBDB_ON
504
505 CmiBool LDOMidEqual(const LDOMid &i1, const LDOMid &i2)
506 {
507  return i1.id == i2.id?CmiTrue:CmiFalse;
508 }
509
510 CmiBool LDObjIDEqual(const LDObjid &i1, const LDObjid &i2)
511 {
512   return (CmiBool)(i1.id[0] == i2.id[0] 
513          && i1.id[1] == i2.id[1] && i1.id[2] == i2.id[2] 
514          && i1.id[3] == i2.id[3]);
515 }
516
517 /*@}*/