ea18817016e89267370831067603d179da7096c9
[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
131 /// migration decision for an obj.
132 struct MigrateInfo {  
133     int index;   // object index in objData array
134     LDObjHandle obj;
135     int from_pe;
136     int to_pe;
137     int async_arrival;      // if an object is available for immediate migrate
138     MigrateInfo():  async_arrival(0) {}
139     void pup(PUP::er &p) {
140       p | index;
141       p | obj;
142       p | from_pe;
143       p | to_pe;
144       p | async_arrival;
145     }
146 };
147
148 /**
149   message contains the migration decision from LB strategies.
150 */
151 class LBMigrateMsg : public CMessage_LBMigrateMsg {
152 public:
153   int level;                    // which level in hierarchy, used in hybridLB
154
155   int n_moves;                  // number of moves
156   MigrateInfo* moves;
157
158   char * avail_vector;          // processor bit vector
159   int next_lb;                  // next load balancer
160
161   double * expectedLoad;        // expected load for future
162
163 public:
164 #if (defined(_FAULT_MLOG_) || defined(_FAULT_CAUSAL_))
165         int step;
166         int lbDecisionCount;
167 #endif
168   LBMigrateMsg(): level(0), n_moves(0), next_lb(0) {}
169   void pup(PUP::er &p) {
170     int i;
171     p | level;
172     p | n_moves;
173     // Warning: it relies on the fact that the message has been allocated already
174     // with the correct number of moves!
175     p | next_lb;
176     int numPes = CkNumPes();
177     p | numPes;
178     CkAssert(numPes == CkNumPes());
179     for (i=0; i<n_moves; ++i) p | moves[i];
180     p(avail_vector, numPes);
181     for (i=0; i<numPes; ++i) p | expectedLoad[i];
182   }
183 };
184
185 struct VectorMigrateInfo {  
186     int from_pe;
187     int to_pe;
188     double load;
189     int async_arrival;      // if an object is available for immediate migrate
190     VectorMigrateInfo():  async_arrival(0) {}
191 };
192
193 class LBVectorMigrateMsg : public CMessage_LBVectorMigrateMsg {
194 public:
195   int level;                    // which level in hierarchy, used in hybridLB
196
197   int n_moves;                  // number of moves
198   VectorMigrateInfo* moves;
199
200 public:
201   LBVectorMigrateMsg(): level(0), n_moves(0) {}
202 };
203
204 // for a FooLB, the following macro defines these functions for each LB:
205 // CreateFooLB():        create BOC and register with LBDatabase with a 
206 //                       sequence ticket,
207 // AllocateFooLB():      allocate the class instead of a BOC
208 // static void lbinit(): an init call for charm module registration
209 #if CMK_LBDB_ON
210
211 #define CreateLBFunc_Def(x, str)                \
212 void Create##x(void) {  \
213   int seqno = LBDatabaseObj()->getLoadbalancerTicket(); \
214   CProxy_##x::ckNew(CkLBOptions(seqno));        \
215 }       \
216 \
217 BaseLB *Allocate##x(void) { \
218   return new x((CkMigrateMessage*)NULL);        \
219 }       \
220 \
221 static void lbinit(void) {      \
222   LBRegisterBalancer(#x,        \
223                      Create##x, \
224                      Allocate##x,       \
225                      str);      \
226 }
227
228 #else           /* CMK_LBDB_ON */
229
230 #define CreateLBFunc_Def(x, str)        \
231 void Create##x(void) {}         \
232 BaseLB *Allocate##x(void) { return NULL; }      \
233 static void lbinit(void) {}
234
235 #endif          /* CMK_LBDB_ON */
236
237 #endif
238
239 /*@}*/