/home/runner/work/charm/charm/src/ck-ldb/BaseLB.C
Line | Count | Source (jump to first uncovered line) |
1 | | /** |
2 | | * \addtogroup CkLdb |
3 | | */ |
4 | | /*@{*/ |
5 | | |
6 | | #include "charm++.h" |
7 | | #include "BaseLB.h" |
8 | | #include "LBSimulation.h" |
9 | | |
10 | | #if CMK_LBDB_ON |
11 | | |
12 | 392 | void BaseLB::initLB(const CkLBOptions &opt) { |
13 | 392 | seqno = opt.getSeqNo(); |
14 | 392 | lbmgr = CProxy_LBManager(_lbmgr).ckLocalBranch(); |
15 | 392 | lbname = "Unknown"; |
16 | | // register this load balancer to LBManager at the sequence number |
17 | 392 | lbmgr->addLoadbalancer(this, seqno); |
18 | 392 | } |
19 | | |
20 | 19 | void BaseLB::pup(PUP::er &p) { |
21 | 19 | p|seqno; |
22 | 19 | if (p.isUnpacking()) |
23 | 12 | { |
24 | 12 | if (CkMyPe()==0) { |
25 | 4 | if (seqno!=-1) { |
26 | 4 | int newseq = LBManagerObj()->getLoadbalancerTicket(); |
27 | 4 | CmiAssert(newseq == seqno); |
28 | 4 | } |
29 | 4 | } |
30 | 12 | initLB(seqno); |
31 | 12 | } |
32 | 19 | } |
33 | | |
34 | 0 | void BaseLB::flushStates() { |
35 | 0 | Group::flushStates(); |
36 | 0 | lbmgr->ClearLoads(); |
37 | 0 | } |
38 | | |
39 | | #else |
40 | | void BaseLB::initLB(const CkLBOptions &) {} |
41 | | void BaseLB::pup(PUP::er &p) {} |
42 | | void BaseLB::flushStates() {} |
43 | | #endif |
44 | | |
45 | | void BaseLB::turnOn() |
46 | 0 | { |
47 | 0 | #if CMK_LBDB_ON |
48 | 0 | lbmgr->TurnOnStartLBFn(startLbFnHdl); |
49 | 0 | #endif |
50 | 0 | } |
51 | | |
52 | | void BaseLB::turnOff() |
53 | 0 | { |
54 | 0 | #if CMK_LBDB_ON |
55 | 0 | lbmgr->TurnOffStartLBFn(startLbFnHdl); |
56 | 0 | #endif |
57 | 0 | } |
58 | | |
59 | 0 | static inline int i_abs(int c) { return c>0?c:-c; } |
60 | | |
61 | | // assume integer is 32 bits |
62 | 4.24k | inline static int ObjKey(const CmiUInt8 &oid, const int hashSize) { |
63 | | // make sure all positive |
64 | 4.24k | return oid % hashSize; |
65 | 4.24k | } |
66 | | |
67 | | BaseLB::LDStats::LDStats(int npes, int complete) |
68 | 4 | : n_migrateobjs(0), |
69 | 4 | complete_flag(complete) |
70 | 4 | { |
71 | 4 | procs.resize(npes); |
72 | 4 | } |
73 | | |
74 | | const static unsigned int doublingPrimes[] = { |
75 | | 3, |
76 | | 7, |
77 | | 17, |
78 | | 37, |
79 | | 73, |
80 | | 157, |
81 | | 307, |
82 | | 617, |
83 | | 1217, |
84 | | 2417, |
85 | | 4817, |
86 | | 9677, |
87 | | 20117, |
88 | | 40177, |
89 | | 80177, |
90 | | 160117, |
91 | | 320107, |
92 | | 640007, |
93 | | 1280107, |
94 | | 2560171, |
95 | | 5120117, |
96 | | 10000079, |
97 | | 20000077, |
98 | | 40000217, |
99 | | 80000111, |
100 | | 160000177, |
101 | | 320000171, |
102 | | 640000171, |
103 | | 1280000017, |
104 | | 2560000217u, |
105 | | 4200000071u |
106 | | /* extra primes larger than an unsigned 32-bit integer: |
107 | | 51200000077, |
108 | | 100000000171, |
109 | | 200000000171, |
110 | | 400000000171, |
111 | | 800000000117, |
112 | | 1600000000021, |
113 | | 3200000000051, |
114 | | 6400000000081, |
115 | | 12800000000003, |
116 | | 25600000000021, |
117 | | 51200000000077, |
118 | | 100000000000067, |
119 | | 200000000000027, |
120 | | 400000000000063, |
121 | | 800000000000017, |
122 | | 1600000000000007, |
123 | | 3200000000000059, |
124 | | 6400000000000007, |
125 | | 12800000000000009, |
126 | | 25600000000000003, |
127 | | 51200000000000023, |
128 | | 100000000000000003, |
129 | | 200000000000000003, |
130 | | 400000000000000013, |
131 | | 800000000000000119, |
132 | | 1600000000000000031, |
133 | | 3200000000000000059 //This is a 62-bit number |
134 | | */ |
135 | | }; |
136 | | |
137 | | //This routine returns an arbitrary prime larger than x |
138 | | static unsigned int primeLargerThan(unsigned int x) |
139 | 46 | { |
140 | 46 | int i=0; |
141 | 138 | while (doublingPrimes[i]<=x) i++; |
142 | 46 | return doublingPrimes[i]; |
143 | 46 | } |
144 | | |
145 | 92 | void BaseLB::LDStats::makeCommHash() { |
146 | | // hash table is already build |
147 | 92 | if (!objHash.empty()) return; |
148 | | |
149 | 46 | hashSize = primeLargerThan(objData.size() * 2); |
150 | 46 | objHash.assign(hashSize, -1); |
151 | 46 | int i = 0; |
152 | 336 | for(const auto& obj : objData) { |
153 | 336 | const CmiUInt8 &oid = obj.objID(); |
154 | 336 | int hash = ObjKey(oid, hashSize); |
155 | 336 | CmiAssert(hash != -1); |
156 | 336 | while(objHash[hash] != -1) |
157 | 0 | hash = (hash+1)%hashSize; |
158 | 336 | objHash[hash] = i++; |
159 | 336 | } |
160 | 46 | } |
161 | | |
162 | 46 | void BaseLB::LDStats::deleteCommHash() { |
163 | 46 | objHash.clear(); |
164 | 46 | for(auto& comm : commData) { |
165 | 0 | comm.clearHash(); |
166 | 0 | } |
167 | 46 | } |
168 | | |
169 | | int BaseLB::LDStats::getHash(const CmiUInt8 &oid, const LDOMid &mid) |
170 | 3.90k | { |
171 | 3.90k | #if CMK_LBDB_ON |
172 | 3.90k | CmiAssert(hashSize > 0); |
173 | 3.90k | int hash = ObjKey(oid, hashSize); |
174 | | |
175 | 3.90k | for(int id=0;id<hashSize;id++){ |
176 | 3.90k | int index = (id+hash)%hashSize; |
177 | 3.90k | if (index == -1 || objHash[index] == -1) return -1; |
178 | 3.90k | if (objData[objHash[index]].objID() == oid && |
179 | 3.90k | objData[objHash[index]].omID() == mid) |
180 | 3.90k | return objHash[index]; |
181 | 3.90k | } |
182 | | // CkPrintf("not found \n"); |
183 | 0 | #endif |
184 | 0 | return -1; |
185 | 3.90k | } |
186 | | |
187 | | int BaseLB::LDStats::getHash(const LDObjKey &objKey) |
188 | 3.90k | { |
189 | 3.90k | const CmiUInt8 &oid = objKey.objID(); |
190 | 3.90k | const LDOMid &mid = objKey.omID(); |
191 | 3.90k | return getHash(oid, mid); |
192 | 3.90k | } |
193 | | |
194 | | int BaseLB::LDStats::getSendHash(LDCommData &cData) |
195 | 976 | { |
196 | 976 | if (cData.sendHash == -1) { |
197 | 976 | cData.sendHash = getHash(cData.sender); |
198 | 976 | } |
199 | 976 | return cData.sendHash; |
200 | 976 | } |
201 | | |
202 | | int BaseLB::LDStats::getRecvHash(LDCommData &cData) |
203 | 976 | { |
204 | 976 | if (cData.recvHash == -1) { |
205 | 976 | cData.recvHash = getHash(cData.receiver.get_destObj()); |
206 | 976 | } |
207 | 976 | return cData.recvHash; |
208 | 976 | } |
209 | | |
210 | 0 | void BaseLB::LDStats::clearCommHash() { |
211 | 0 | for(auto& comm : commData) { |
212 | 0 | comm.clearHash(); |
213 | 0 | } |
214 | 0 | } |
215 | | |
216 | | void BaseLB::LDStats::computeNonlocalComm(int &nmsgs, int &nbytes) |
217 | 0 | { |
218 | 0 | #if CMK_LBDB_ON |
219 | 0 | nmsgs = 0; |
220 | 0 | nbytes = 0; |
221 | |
|
222 | 0 | makeCommHash(); |
223 | |
|
224 | 0 | int mcast_count = 0; |
225 | 0 | for (auto& cdata : commData) { |
226 | 0 | int senderPE, receiverPE; |
227 | 0 | if (cdata.from_proc()) |
228 | 0 | senderPE = cdata.src_proc; |
229 | 0 | else { |
230 | 0 | int idx = getHash(cdata.sender); |
231 | 0 | if (idx == -1) continue; // sender has just migrated? |
232 | 0 | senderPE = to_proc[idx]; |
233 | 0 | CmiAssert(senderPE != -1); |
234 | 0 | } |
235 | 0 | CmiAssert(senderPE < procs.size() && senderPE >= 0); |
236 | | |
237 | | // find receiver: point-to-point and multicast two cases |
238 | 0 | int receiver_type = cdata.receiver.get_type(); |
239 | 0 | if (receiver_type == LD_PROC_MSG || receiver_type == LD_OBJ_MSG) { |
240 | 0 | if (receiver_type == LD_PROC_MSG) |
241 | 0 | receiverPE = cdata.receiver.proc(); |
242 | 0 | else { // LD_OBJ_MSG |
243 | 0 | int idx = getHash(cdata.receiver.get_destObj()); |
244 | 0 | if (idx == -1) { // receiver outside this domain |
245 | 0 | if (complete_flag) continue; |
246 | 0 | else receiverPE = -1; |
247 | 0 | } |
248 | 0 | else { |
249 | 0 | receiverPE = to_proc[idx]; |
250 | 0 | CmiAssert(receiverPE < procs.size() && receiverPE >= 0); |
251 | 0 | } |
252 | 0 | } |
253 | 0 | if(senderPE != receiverPE) |
254 | 0 | { |
255 | 0 | nmsgs += cdata.messages; |
256 | 0 | nbytes += cdata.bytes; |
257 | 0 | } |
258 | 0 | } |
259 | 0 | else if (receiver_type == LD_OBJLIST_MSG) { |
260 | 0 | int nobjs; |
261 | 0 | const LDObjKey *objs = cdata.receiver.get_destObjs(nobjs); |
262 | 0 | mcast_count ++; |
263 | 0 | std::vector<int> pes; |
264 | 0 | for (int i=0; i<nobjs; i++) { |
265 | 0 | int idx = getHash(objs[i]); |
266 | 0 | CmiAssert(idx != -1); |
267 | 0 | if (idx == -1) continue; // receiver has just been removed? |
268 | 0 | receiverPE = to_proc[idx]; |
269 | 0 | CmiAssert(receiverPE < procs.size() && receiverPE >= 0); |
270 | 0 | int exist = 0; |
271 | 0 | for (auto pe : pes) |
272 | 0 | if (receiverPE == pe) { exist=1; break; } |
273 | 0 | if (exist) continue; |
274 | 0 | pes.push_back(receiverPE); |
275 | 0 | if(senderPE != receiverPE) |
276 | 0 | { |
277 | 0 | nmsgs += cdata.messages; |
278 | 0 | nbytes += cdata.bytes; |
279 | 0 | } |
280 | 0 | } |
281 | 0 | } |
282 | 0 | } // end of for |
283 | 0 | #endif |
284 | 0 | } |
285 | | |
286 | 0 | void BaseLB::LDStats::normalize_speed() { |
287 | 0 | double maxspeed = 0.0; |
288 | |
|
289 | 0 | for (const auto& proc : procs) |
290 | 0 | { |
291 | 0 | if (proc.pe_speed > maxspeed) maxspeed = proc.pe_speed; |
292 | 0 | } |
293 | 0 | for (auto& proc : procs) proc.pe_speed /= maxspeed; |
294 | 0 | } |
295 | | |
296 | | void BaseLB::LDStats::print() |
297 | 0 | { |
298 | 0 | #if CMK_LBDB_ON |
299 | 0 | int i = 0; |
300 | 0 | CkPrintf("------------- Processor Data: %zu -------------\n", procs.size()); |
301 | 0 | for (const auto& proc : procs) |
302 | 0 | { |
303 | 0 | CkPrintf("Proc %d (%d) Speed %f Total = %f Idle = %f Bg = %f nObjs = %d", |
304 | 0 | i++, proc.pe, proc.pe_speed, proc.total_walltime, proc.idletime, |
305 | 0 | proc.bg_walltime, proc.n_objs); |
306 | | #if CMK_LB_CPUTIMER |
307 | | CkPrintf(" CPU Total %f Bg %f", proc.total_cputime, proc.bg_cputime); |
308 | | #endif |
309 | 0 | CkPrintf("\n"); |
310 | 0 | } |
311 | |
|
312 | 0 | i = 0; |
313 | 0 | CkPrintf("------------- Object Data: %zu objects -------------\n", objData.size()); |
314 | 0 | for(auto &odata : objData) { |
315 | 0 | CkPrintf("Object %d\n",i++); |
316 | 0 | CkPrintf(" id = %" PRIu64 "\n",odata.objID()); |
317 | 0 | CkPrintf(" OM id = %d\t",odata.omID().id.idx); |
318 | 0 | CkPrintf(" Mig. = %d\n",odata.migratable); |
319 | | #if CMK_LB_CPUTIMER |
320 | | CkPrintf(" CPU = %f\t",odata.cpuTime); |
321 | | #endif |
322 | 0 | CkPrintf(" Wall = %f\n",odata.wallTime); |
323 | 0 | } |
324 | |
|
325 | 0 | i = 0; |
326 | 0 | CkPrintf("------------- Comm Data: %zu records -------------\n", commData.size()); |
327 | 0 | for(const auto& comm : commData) { |
328 | 0 | CkPrintf("Link %d\n",i++); |
329 | |
|
330 | 0 | if (comm.from_proc()) |
331 | 0 | CkPrintf(" sender PE = %d\t",comm.src_proc); |
332 | 0 | else |
333 | 0 | CkPrintf(" sender id = %d:[%" PRIu64 "]\t", |
334 | 0 | comm.sender.omID().id.idx,comm.sender.objID()); |
335 | |
|
336 | 0 | if (comm.recv_type() == LD_PROC_MSG) |
337 | 0 | CkPrintf(" receiver PE = %d\n",comm.receiver.proc()); |
338 | 0 | else |
339 | 0 | CkPrintf(" receiver id = %d:[%" PRIu64 "]\n", |
340 | 0 | comm.receiver.get_destObj().omID().id.idx,comm.receiver.get_destObj().objID()); |
341 | | |
342 | 0 | CkPrintf(" messages = %d\t",comm.messages); |
343 | 0 | CkPrintf(" bytes = %d\n",comm.bytes); |
344 | 0 | } |
345 | 0 | CkPrintf("------------- Object to PE mapping -------------\n"); |
346 | 0 | for (const auto& val : from_proc) CkPrintf(" %d", val); |
347 | 0 | CkPrintf("\n"); |
348 | 0 | #endif |
349 | 0 | } |
350 | | |
351 | | double BaseLB::LDStats::computeAverageLoad() |
352 | 0 | { |
353 | 0 | int numAvail = 0; |
354 | 0 | double total = 0; |
355 | 0 | for (const auto& obj : objData) total += obj.wallTime; |
356 | |
|
357 | 0 | for (const auto& proc : procs) |
358 | 0 | { |
359 | 0 | if (proc.available) |
360 | 0 | { |
361 | 0 | total += proc.bg_walltime; |
362 | 0 | numAvail++; |
363 | 0 | } |
364 | 0 | } |
365 | |
|
366 | 0 | double averageLoad = total/numAvail; |
367 | 0 | return averageLoad; |
368 | 0 | } |
369 | | |
370 | | // remove the obj-th object from database |
371 | | void BaseLB::LDStats::removeObject(int obj) |
372 | 0 | { |
373 | 0 | CmiAssert(obj < objData.size()); |
374 | 0 | LDObjData odata = objData[obj]; |
375 | |
|
376 | 0 | LDObjKey okey; // build a key |
377 | 0 | okey.omID() = odata.omID(); |
378 | 0 | okey.objID() = odata.objID(); |
379 | |
|
380 | 0 | objData.erase(objData.begin() + obj); |
381 | 0 | from_proc.erase(from_proc.begin() + obj); |
382 | 0 | to_proc.erase(to_proc.begin() + obj); |
383 | 0 | if (odata.migratable) n_migrateobjs --; |
384 | | |
385 | | // search for sender, can be multiple sender |
386 | 0 | commData.erase(remove_if(commData.begin(), |
387 | 0 | commData.end(), |
388 | 0 | [&](LDCommData& cdata) { |
389 | 0 | return !cdata.from_proc() && cdata.sender == okey; |
390 | 0 | }), |
391 | 0 | commData.end()); |
392 | 0 | } |
393 | | |
394 | | void BaseLB::LDStats::pup(PUP::er &p) |
395 | 0 | { |
396 | 0 | p(n_migrateobjs); |
397 | 0 | p|procs; |
398 | 0 | if (p.isUnpacking()) |
399 | 0 | { |
400 | | // user can specify simulated processors other than the real # of procs |
401 | 0 | if (LBSimulation::simProcs > procs.size()) |
402 | 0 | { |
403 | 0 | procs.resize(LBSimulation::simProcs); |
404 | 0 | } |
405 | | // ignore the background load when unpacking if the user changed the # of procs |
406 | 0 | if (LBSimulation::procsChanged) |
407 | 0 | { |
408 | 0 | const auto size = procs.size(); |
409 | 0 | procs.clear(); |
410 | 0 | procs.resize(size); |
411 | 0 | } |
412 | 0 | } |
413 | 0 | p|objData; |
414 | 0 | p|from_proc; |
415 | | // reset to_proc when unpacking |
416 | 0 | if (p.isUnpacking()) |
417 | 0 | to_proc = from_proc; |
418 | 0 | p|commData; |
419 | 0 | if (p.isUnpacking()) { |
420 | 0 | if (_lb_args.lbversion() <= 1) |
421 | 0 | for (int i = 0; i < procs.size(); i++) procs[i].pe = i; |
422 | 0 | } |
423 | 0 | } |
424 | | |
425 | 46 | int BaseLB::LDStats::useMem() { |
426 | | // calculate the memory usage of this LB (superclass). |
427 | 46 | return sizeof(LDStats) + sizeof(ProcStats) * procs.size() + |
428 | 46 | (sizeof(LDObjData) + 2 * sizeof(int)) * objData.size() + |
429 | 46 | sizeof(LDCommData) * commData.size(); |
430 | 46 | } |
431 | | |
432 | | #include "BaseLB.def.h" |
433 | | |
434 | | /*@}*/ |