doc: Add serial to list of ci file reserved words
[charm.git] / src / ck-ldb / BaseLB.h
1 /**
2  \defgroup CkLdb  Charm++ Load Balancing Framework 
3 */
4 /*@{*/
5
6 #ifndef BASELB_H
7 #define BASELB_H
8
9 #include "LBDatabase.h"
10
11 #define PER_MESSAGE_SEND_OVERHEAD_DEFAULT   3.5e-5
12 #define PER_BYTE_SEND_OVERHEAD_DEFAULT      8.5e-9
13 #define PER_MESSAGE_RECV_OVERHEAD           0.0
14 #define PER_BYTE_RECV_OVERHEAD              0.0
15
16 /// Base class for all LB strategies.
17 /**
18   BaseLB is the base class for all LB strategy class.
19   it does some tracking about how many lb strategies are created.
20   it also defines some common functions.
21 */
22 class BaseLB: public CBase_BaseLB
23 {
24 protected:
25   int  seqno;
26   const char *lbname;
27   LBDatabase *theLbdb;
28   LDBarrierReceiver receiver;
29   int  notifier;
30   int  startLbFnHdl;
31 private:
32   void initLB(const CkLBOptions &);
33 public:
34   struct ProcStats {            // per processor data
35     int n_objs;                 // number of objects on the processor
36     double pe_speed;            // processor frequency
37     /// total time (total_walltime) = idletime + overhead (bg_walltime)
38     ///                             + object load (obj_walltime)
39     /// walltime and cputime may be different on shared compute nodes
40     /// it is advisable to use walltime in most cases
41     double total_walltime;
42     /// time for which the processor is sitting idle
43     double idletime;
44     /// bg_walltime called background load (overhead in ckgraph.h) is a
45     /// derived quantity: total_walltime - idletime - object load (obj_walltime)
46     double bg_walltime;
47 #if CMK_LB_CPUTIMER
48     double total_cputime;
49     double bg_cputime;
50 #endif
51     // double utilization;
52     int pe;                     // processor id
53     CmiBool available;
54     ProcStats(): n_objs(0), pe_speed(1), total_walltime(0.0), idletime(0.0),
55 #if CMK_LB_CPUTIMER
56                  total_cputime(0.0), bg_cputime(0.0),
57 #endif
58                  bg_walltime(0.0), pe(-1), available(CmiTrue) {}
59     inline void clearBgLoad() {
60       idletime = bg_walltime = 
61 #if CMK_LB_CPUTIMER
62       bg_cputime = 
63 #endif
64       0.0;
65     }
66     inline void pup(PUP::er &p) {
67       p|total_walltime;
68       p|idletime;
69       p|bg_walltime;
70 #if CMK_LB_CPUTIMER
71       p|total_cputime;
72       p|bg_cputime;
73 #endif
74       p|pe_speed;
75       if (_lb_args.lbversion() < 1 && p.isUnpacking()) {
76          double dummy;  p|dummy;    // for old format with utilization
77       }
78       p|available; p|n_objs;
79       if (_lb_args.lbversion()>=2) p|pe; 
80     }
81   };
82
83   /** Passed to the virtual functions Strategy(...) and work(...) */
84   struct LDStats {
85     int count;                  // number of processors in the array "procs"
86     ProcStats *procs;           // processor statistics
87
88     int n_objs;                 // total number of objects in the vector "objData"
89     int n_migrateobjs;          // total number of migratable objects
90     CkVec<LDObjData> objData;   // LDObjData and LDCommData defined in lbdb.h
91     CkVec<int> from_proc;       // current pe an object is on
92     CkVec<int> to_proc;         // new pe you want the object to be on
93
94     int n_comm;                 // number of edges in the vector "commData"
95     CkVec<LDCommData> commData; // communication data - edge list representation
96                                 // of the communication between objects
97
98     int *objHash;               // this a map from the hash for the 4 integer
99                                 // LDObjId to the index in the vector "objData"
100     int  hashSize;
101
102     int complete_flag;          // if this ocg is complete, eg in HybridLB,
103     // this LDStats may not be complete
104
105     int is_prev_lb_refine;
106     double after_lb_max;
107     double after_lb_avg;
108
109     LDStats(int c=0, int complete_flag=1);
110     /// the functions below should be used to obtain the number of processors
111     /// instead of accessing count directly
112     inline int nprocs() const { return count; }
113     inline int &nprocs() { return count; }
114
115     void assign(int oid, int pe) { CmiAssert(procs[pe].available); to_proc[oid] = pe; }
116     /// build hash table
117     void makeCommHash();
118     void deleteCommHash();
119     /// given an LDObjKey, returns the index in the objData vector
120     /// this index changes every time one does load balancing even within a run
121     int getHash(const LDObjKey &);
122     int getHash(const LDObjid &oid, const LDOMid &mid);
123     int getSendHash(LDCommData &cData);
124     int getRecvHash(LDCommData &cData);
125     void clearCommHash();
126     void clear() {
127       n_objs = n_migrateobjs = n_comm = 0;
128       objData.free();
129       commData.free();
130       from_proc.free();
131       to_proc.free();
132       deleteCommHash();
133     }
134     void clearBgLoad() {
135       for (int i=0; i<nprocs(); i++) procs[i].clearBgLoad();
136     }
137     void computeNonlocalComm(int &nmsgs, int &nbytes);
138     double computeAverageLoad();
139     void normalize_speed();
140     void print();
141     // edit functions
142     void removeObject(int obj);
143     void pup(PUP::er &p);
144     int useMem();
145   };
146
147   BaseLB(const CkLBOptions &opt)  { initLB(opt); }
148   BaseLB(CkMigrateMessage *m):CBase_BaseLB(m) {}
149   virtual ~BaseLB();
150
151   void unregister(); 
152   inline const char *lbName() { return lbname; }
153   inline int step() { return theLbdb->step(); }
154   virtual void turnOff() { CmiAbort("turnOff not implemented"); }
155   virtual void turnOn()  { CmiAbort("turnOn not implemented"); }
156   virtual int  useMem()  { return 0; }
157   virtual void pup(PUP::er &p);
158   virtual void flushStates();
159
160   CkGroupID getGroupID() {return thisgroup;}
161 };
162
163 /// migration decision for an obj.
164 struct MigrateInfo {  
165     int index;   // object index in objData array
166     LDObjHandle obj;
167     int from_pe;
168     int to_pe;
169     int async_arrival;      // if an object is available for immediate migrate
170     MigrateInfo():  async_arrival(0) {
171 #if CMK_GLOBAL_LOCATION_UPDATE
172       obj.id.isArrayElement = 0; 
173 #endif
174     }
175
176     void pup(PUP::er &p) {
177       p | index;
178       p | obj;
179       p | from_pe;
180       p | to_pe;
181       p | async_arrival;
182     }
183 };
184
185 /**
186   message contains the migration decision from LB strategies.
187 */
188 class LBMigrateMsg : public CMessage_LBMigrateMsg {
189 public:
190   int level;                    // which level in hierarchy, used in hybridLB
191
192   int n_moves;                  // number of moves
193   MigrateInfo* moves;
194
195   char * avail_vector;          // processor bit vector
196   int next_lb;                  // next load balancer
197
198   double * expectedLoad;        // expected load for future
199
200 public:
201 #if (defined(_FAULT_MLOG_) || defined(_FAULT_CAUSAL_))
202         int step;
203         int lbDecisionCount;
204 #endif
205   LBMigrateMsg(): level(0), n_moves(0), next_lb(0) {}
206   void pup(PUP::er &p) {
207     int i;
208     p | level;
209     p | n_moves;
210     // Warning: it relies on the fact that the message has been allocated already
211     // with the correct number of moves!
212     p | next_lb;
213     int numPes = CkNumPes();
214     p | numPes;
215     CkAssert(numPes == CkNumPes());
216     for (i=0; i<n_moves; ++i) p | moves[i];
217     p(avail_vector, numPes);
218     for (i=0; i<numPes; ++i) p | expectedLoad[i];
219   }
220 };
221
222 struct VectorMigrateInfo {  
223     int from_pe;
224     int to_pe;
225     double load;
226     int async_arrival;      // if an object is available for immediate migrate
227     VectorMigrateInfo():  async_arrival(0) {}
228 };
229
230 class LBVectorMigrateMsg : public CMessage_LBVectorMigrateMsg {
231 public:
232   int level;                    // which level in hierarchy, used in hybridLB
233
234   int n_moves;                  // number of moves
235   VectorMigrateInfo* moves;
236
237 public:
238   LBVectorMigrateMsg(): level(0), n_moves(0) {}
239 };
240
241 // for a FooLB, the following macro defines these functions for each LB:
242 // CreateFooLB():        create BOC and register with LBDatabase with a 
243 //                       sequence ticket,
244 // AllocateFooLB():      allocate the class instead of a BOC
245 // static void lbinit(): an init call for charm module registration
246 #if CMK_LBDB_ON
247
248 #define CreateLBFunc_Def(x, str)                \
249 void Create##x(void) {  \
250   int seqno = LBDatabaseObj()->getLoadbalancerTicket(); \
251   CProxy_##x::ckNew(CkLBOptions(seqno));        \
252 }       \
253 \
254 BaseLB *Allocate##x(void) { \
255   return new x((CkMigrateMessage*)NULL);        \
256 }       \
257 \
258 static void lbinit(void) {      \
259   LBRegisterBalancer(#x,        \
260                      Create##x, \
261                      Allocate##x,       \
262                      str);      \
263 }
264
265 #else           /* CMK_LBDB_ON */
266
267 #define CreateLBFunc_Def(x, str)        \
268 void Create##x(void) {}         \
269 BaseLB *Allocate##x(void) { return NULL; }      \
270 static void lbinit(void) {}
271
272 #endif          /* CMK_LBDB_ON */
273
274 #endif
275
276 /*@}*/