NEURON
lpt.cpp
Go to the documentation of this file.
1 /*
2 # =============================================================================
3 # Copyright (c) 2016 - 2021 Blue Brain Project/EPFL
4 #
5 # See top-level LICENSE file for details.
6 # =============================================================================
7 */
8 
9 #include <algorithm>
10 #include <functional>
11 #include <numeric>
12 #include <queue>
13 
14 #if CORENRN_BUILD
15 #include "coreneuron/nrnconf.h" // for size_t
17 #else
18 #include "oc/nrnassrt.h"
19 #endif
20 
21 #include "coreneuron/utils/lpt.hpp"
22 
23 using P = std::pair<size_t, size_t>;
24 
25 // lpt Least Processing Time algorithm.
26 // Largest piece goes into least size bag.
27 // in: number of bags, vector of sizes
28 // return: a new vector of bag indices parallel to the vector of sizes.
29 
30 std::vector<std::size_t> lpt(std::size_t nbag, std::vector<std::size_t>& pieces, double* bal) {
31  nrn_assert(nbag > 0);
32  nrn_assert(!pieces.empty());
33 
34  std::vector<P> pvec;
35  for (size_t i = 0; i < pieces.size(); ++i) {
36  pvec.push_back(P(i, pieces[i]));
37  }
38 
39  auto P_comp = [](const P& a, const P& b) { return a.second > b.second; };
40 
41  std::sort(pvec.begin(), pvec.end(), P_comp);
42 
43  std::vector<std::size_t> bagindices(pieces.size());
44 
45  std::priority_queue<P, std::vector<P>, decltype(P_comp)> bagq(P_comp);
46  for (size_t i = 0; i < nbag; ++i) {
47  bagq.push(P(i, 0));
48  }
49 
50  for (const auto& p: pvec) {
51  P bagqitem = bagq.top();
52  bagq.pop();
53  bagindices[p.first] = bagqitem.first;
54  bagqitem.second += p.second;
55  bagq.push(bagqitem);
56  }
57 
58  // load balance average/max (1.0 is perfect)
59  std::vector<size_t> v(bagq.size());
60  for (size_t i = 1; i < nbag; ++i) {
61  v[i] = bagq.top().second;
62  bagq.pop();
63  }
64  double b = load_balance(v);
65  if (bal) {
66  *bal = b;
67  } else {
68  printf("load balance = %g for %ld pieces in %ld bags\n", b, pieces.size(), nbag);
69  }
70 
71  return bagindices;
72 }
73 
74 double load_balance(std::vector<size_t>& v) {
75  nrn_assert(!v.empty());
76  std::size_t sum = std::accumulate(v.begin(), v.end(), 0);
77  std::size_t max = *std::max_element(v.begin(), v.end());
78  return (double(sum) / v.size()) / max;
79 }
#define v
Definition: md1redef.h:11
#define i
Definition: md1redef.h:19
double load_balance(std::vector< size_t > &v)
Definition: lpt.cpp:74
std::pair< size_t, size_t > P
Definition: lpt.cpp:23
std::vector< std::size_t > lpt(std::size_t nbag, std::vector< std::size_t > &pieces, double *bal)
Definition: lpt.cpp:30
printf
Definition: extdef.h:5
#define nrn_assert(x)
assert()-like macro, independent of NDEBUG status
Definition: nrn_assert.h:33
size_t p