Coverage Report

Created: 2026-10-28 17:42

/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
/*@}*/