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