2 \defgroup CkLdb Charm++ Load Balancing Framework
9 #include "LBDatabase.h"
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
16 /// Base class for all LB strategies.
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.
22 class BaseLB
: public CBase_BaseLB
28 LDBarrierReceiver receiver
;
32 void initLB(const CkLBOptions
&);
34 struct ProcStats
{ // per processor data
35 int n_objs
; // number of objects on the processor
36 double pe_speed
; // processor frequency
41 /// total time (total_walltime) = idletime + overhead (bg_walltime)
42 /// + object load (obj_walltime)
43 /// walltime and cputime may be different on shared compute nodes
44 /// it is advisable to use walltime in most cases
45 double total_walltime
;
46 /// time for which the processor is sitting idle
48 /// bg_walltime called background load (overhead in ckgraph.h) is a
49 /// derived quantity: total_walltime - idletime - object load (obj_walltime)
55 // double utilization;
56 int pe
; // processor id
58 ProcStats(): n_objs(0), pe_speed(1), total_walltime(0.0), idletime(0.0),
60 total_cputime(0.0), bg_cputime(0.0),
62 bg_walltime(0.0), pe(-1), available(true) {}
63 inline void clearBgLoad() {
64 idletime
= bg_walltime
=
70 inline void pup(PUP::er
&p
) {
79 if (_lb_args
.lbversion() < 1 && p
.isUnpacking()) {
80 double dummy
; p
|dummy
; // for old format with utilization
82 p
|available
; p
|n_objs
;
83 if (_lb_args
.lbversion()>=2) p
|pe
;
87 /** Passed to the virtual functions Strategy(...) and work(...) */
89 int count
; // number of processors in the array "procs"
90 ProcStats
*procs
; // processor statistics
92 int n_objs
; // total number of objects in the vector "objData"
93 int n_migrateobjs
; // total number of migratable objects
94 CkVec
<LDObjData
> objData
; // LDObjData and LDCommData defined in lbdb.h
95 CkVec
<int> from_proc
; // current pe an object is on
96 CkVec
<int> to_proc
; // new pe you want the object to be on
98 int n_comm
; // number of edges in the vector "commData"
99 CkVec
<LDCommData
> commData
; // communication data - edge list representation
100 // of the communication between objects
102 int *objHash
; // this a map from the hash for the 4 integer
103 // LDObjId to the index in the vector "objData"
106 int complete_flag
; // if this ocg is complete, eg in HybridLB,
107 // this LDStats may not be complete
109 int is_prev_lb_refine
;
113 LDStats(int c
=0, int complete_flag
=1);
114 /// the functions below should be used to obtain the number of processors
115 /// instead of accessing count directly
116 inline int nprocs() const { return count
; }
117 inline int &nprocs() { return count
; }
119 void assign(int oid
, int pe
) { CmiAssert(procs
[pe
].available
); to_proc
[oid
] = pe
; }
122 void deleteCommHash();
123 /// given an LDObjKey, returns the index in the objData vector
124 /// this index changes every time one does load balancing even within a run
125 int getHash(const LDObjKey
&);
126 int getHash(const LDObjid
&oid
, const LDOMid
&mid
);
127 int getSendHash(LDCommData
&cData
);
128 int getRecvHash(LDCommData
&cData
);
129 void clearCommHash();
131 n_objs
= n_migrateobjs
= n_comm
= 0;
139 for (int i
=0; i
<nprocs(); i
++) procs
[i
].clearBgLoad();
141 void computeNonlocalComm(int &nmsgs
, int &nbytes
);
142 double computeAverageLoad();
143 void normalize_speed();
146 void removeObject(int obj
);
147 void pup(PUP::er
&p
);
151 BaseLB(const CkLBOptions
&opt
) { initLB(opt
); }
152 BaseLB(CkMigrateMessage
*m
):CBase_BaseLB(m
) {
153 theLbdb
= CProxy_LBDatabase(_lbdb
).ckLocalBranch();
158 inline const char *lbName() { return lbname
; }
159 inline int step() { return theLbdb
->step(); }
160 virtual void turnOff() { CmiAbort("turnOff not implemented"); }
161 virtual void turnOn() { CmiAbort("turnOn not implemented"); }
162 virtual int useMem() { return 0; }
163 virtual void pup(PUP::er
&p
);
164 virtual void flushStates();
166 CkGroupID
getGroupID() {return thisgroup
;}
169 /// migration decision for an obj.
171 int index
; // object index in objData array
175 int async_arrival
; // if an object is available for immediate migrate
176 MigrateInfo(): async_arrival(0) {
177 #if CMK_GLOBAL_LOCATION_UPDATE
178 obj
.id
.isArrayElement
= 0;
182 void pup(PUP::er
&p
) {
191 struct MigrateDecision
{
196 MigrateDecision
&operator=(const MigrateInfo
&mInfo
) {
197 dbIndex
= mInfo
.obj
.handle
;
198 fromPe
= mInfo
.from_pe
;
206 class LBScatterMsg
: public CMessage_LBScatterMsg
{
211 int *numMigratesPerPe
;
212 MigrateDecision
*moves
;
214 LBScatterMsg(int firstPe
, int lastPe
) {
216 firstPeInSpan
= firstPe
;
217 lastPeInSpan
= lastPe
;
224 message contains the migration decision from LB strategies.
226 class LBMigrateMsg
: public CMessage_LBMigrateMsg
{
228 int level
; // which level in hierarchy, used in hybridLB
230 int n_moves
; // number of moves
233 char * avail_vector
; // processor bit vector
234 int next_lb
; // next load balancer
236 double * expectedLoad
; // expected load for future
239 #if (defined(_FAULT_MLOG_) || defined(_FAULT_CAUSAL_))
243 LBMigrateMsg(): level(0), n_moves(0), next_lb(0) {}
244 void pup(PUP::er
&p
) {
248 // Warning: it relies on the fact that the message has been allocated already
249 // with the correct number of moves!
251 int numPes
= CkNumPes();
253 CkAssert(numPes
== CkNumPes());
254 for (i
=0; i
<n_moves
; ++i
) p
| moves
[i
];
255 p(avail_vector
, numPes
);
256 for (i
=0; i
<numPes
; ++i
) p
| expectedLoad
[i
];
260 struct VectorMigrateInfo
{
264 int async_arrival
; // if an object is available for immediate migrate
265 VectorMigrateInfo(): async_arrival(0) {}
268 class LBVectorMigrateMsg
: public CMessage_LBVectorMigrateMsg
{
270 int level
; // which level in hierarchy, used in hybridLB
272 int n_moves
; // number of moves
273 VectorMigrateInfo
* moves
;
276 LBVectorMigrateMsg(): level(0), n_moves(0) {}
279 // for a FooLB, the following macro defines these functions for each LB:
280 // CreateFooLB(): create BOC and register with LBDatabase with a
282 // AllocateFooLB(): allocate the class instead of a BOC
283 // static void lbinit(): an init call for charm module registration
286 #define CreateLBFunc_Def(x, str) \
287 void Create##x(void) { \
288 int seqno = LBDatabaseObj()->getLoadbalancerTicket(); \
289 CProxy_##x::ckNew(CkLBOptions(seqno)); \
292 BaseLB *Allocate##x(void) { \
293 return new x((CkMigrateMessage*)NULL); \
296 static void lbinit(void) { \
297 LBRegisterBalancer(#x, \
303 #else /* CMK_LBDB_ON */
305 #define CreateLBFunc_Def(x, str) \
306 void Create##x(void) {} \
307 BaseLB *Allocate##x(void) { return NULL; } \
308 static void lbinit(void) {}
310 #endif /* CMK_LBDB_ON */