MADNESS 0.10.1
macrotaskpartitioner.h
Go to the documentation of this file.
1//
2// Created by Florian Bischoff on 12/10/20.
3//
4
5#ifndef MADNESS_MACROTASKPARTITIONER_H
6#define MADNESS_MACROTASKPARTITIONER_H
7
8#include<vector>
9#include<list>
10#include<string>
11#include<iomanip>
12#include<sstream>
14
15
16namespace madness {
17template<typename ... Ts>
18constexpr auto decay_types(std::tuple<Ts...> const &)
19-> std::tuple<std::remove_cv_t<std::remove_reference_t<Ts>>...>;
20
21template<typename T>
22using decay_tuple = decltype(decay_types(std::declval<T>()));
23
24template<typename>
25struct is_madness_function_vector : std::false_type {
26};
27
28template<typename T, std::size_t NDIM>
29struct is_madness_function_vector<std::vector<typename madness::Function<T, NDIM>>> : std::true_type {
30};
31
32template<typename Q> struct is_vector : std::false_type { };
33template<typename Q> struct is_vector<std::vector<Q>> : std::true_type { };
34
35/// given a tuple return the index of the first argument that is a vector of Function<T,NDIM>
36template<typename tupleT, std::size_t I>
37constexpr std::size_t get_index_of_first_vector_argument() {
38
39 typedef decay_tuple <tupleT> argtupleT; // removes const, &, etc
40
41 if constexpr(I >= std::tuple_size_v<tupleT>) {
42 // Last case, if nothing is left to iterate, then exit the function
43// MADNESS_EXCEPTION("there is no madness function vector argument in the list, cannot partition the tasks", 1);
44 return I;
45 } else {
46 using typeT = typename std::tuple_element<I, argtupleT>::type;// use decay types for determining a vector
47 if constexpr (is_vector<typeT>::value) {
48 return I;
49 } else {
50 // Going for next element.
51 return get_index_of_first_vector_argument<tupleT,I+1>();
52 }
53 }
54}
55
56/// given a tuple return the index of the second argument that is a vector of Function<T,NDIM>
57template<typename tupleT, std::size_t I>
58constexpr std::size_t get_index_of_second_vector_argument() {
59 constexpr std::size_t index0=get_index_of_first_vector_argument<tupleT,0>();
60 return get_index_of_first_vector_argument<tupleT,index0+1>();
61}
62
63class Batch_1D {
65
66public:
67 long begin=0, end=-1; ///< first and first past last index [begin,end)
68
70 Batch_1D(const Slice& s) : begin(s.start), end(s.end) {
71 MADNESS_CHECK(s.step==1);
72 }
73 Batch_1D(const long& begin, const long& end) : begin(begin), end(end) {}
74
75 bool operator==(const Batch_1D& other) const {
76 return (end==other.end && begin==other.begin);
77 }
78
79 long size() const {
80 return end - begin;
81 }
82
83 bool is_full_size() const {
84 return (begin==0 and end==-1);
85 }
86
87 /// select the relevant vector elements from the argument tuple
88 template<typename tupleT, std::size_t appearance>
89 tupleT copy_batch(const tupleT& arg) const {
90
91 constexpr std::size_t index = (appearance==0) ? get_index_of_first_vector_argument<tupleT,0>() :
92 get_index_of_second_vector_argument<tupleT,0>();
93 if constexpr (index>=std::tuple_size<tupleT>::value) {
94 MADNESS_CHECK(is_full_size()); // better: not set by user..
95 return arg;
96 } else {
97 auto v = std::get<index>(arg);
98 auto v_batch=copy_batch(v);
99 tupleT batched_arg = arg;
100 std::get<index>(batched_arg) = v_batch;
101 return batched_arg;
102 }
103 }
104
105 /// given vector v, copy vector elements of v_batch into vector
106 template<typename vecT>
107 vecT insert_batch(vecT v, const vecT& v_batch) const {
108 if (not (v_batch.size()==size_t(this->size()) or this->is_full_size())) {
109 print("error in insert_batch");
110 print("begin, end",begin, end);
111 print(*this);
112 print("v.size()",v.size());
113 print("v_batch.size()",v_batch.size());
114 MADNESS_CHECK_THROW(0, "error in insert_batch");
115 }
116 std::copy(v_batch.begin(), v_batch.end(), v.begin()+begin);
117 return v;
118 }
119
120 /// given vector v, return those vector elements inside this batch
121 template<typename vecT>
122 vecT copy_batch(const vecT v) const {
123 vecT result_batch;
124 long end1 = (end > 0) ? end : v.end() - v.begin();
125 std::copy(v.begin() + begin, v.begin() + end1, std::back_inserter(result_batch));
126 return result_batch;
127 }
128
129 friend std::ostream& operator<<(std::ostream& os, const Batch_1D& batch) {
130 std::stringstream ss;
131 if (batch.is_full_size()) ss << "[ ---- )";
132 else ss << "[" << std::setw(3) << batch.begin << ", " << std::setw(3) << batch.end << ")";
133 os << ss.str();
134 return os;
135 }
136};
137
138/// a batch consists of a 2D-input batch and a 1D-output batch: K-batch <- (I-batch, J-batch)
139class Batch {
140public:
142 std::vector<Batch_1D> input;
144
145 Batch() {}
146 Batch(const Batch& other) {
147 *this=other;
148 }
149 Batch& operator=(const Batch& other) {
150 if (this==&other) return *this;
151 result=other.result;
152 input=other.input;
153 return *this;
154 }
155
158 : input{input1,input2}, result(result) {}
159
160 std::size_t size_of_input() const {
161 std::size_t result=1;
162 for (auto i: input) result*=i.size();
163 return result;
164 }
165
166 /// select the relevant vector elements from the argument tuple
167 template<typename tupleT>
168 tupleT copy_input_batch(const tupleT& arg) const {
169 if (input.size()==0) return arg;
170 tupleT arg1=input[0].template copy_batch<tupleT,0>(arg);
171 if (input.size()>1) arg1=input[1].template copy_batch<tupleT,1>(arg1);
172 MADNESS_CHECK(input.size()<=2);
173 return arg1;
174 }
175
176 /// copy v_batch into the result vector
177 template<typename vecT>
178 vecT insert_result_batch(vecT v, const vecT& v_batch) const {
179 return result.template insert_batch(v,v_batch);
180 }
181
182 /// pretty print this batch
183 friend std::ostream& operator<<(std::ostream& os, const Batch& batch) {
184 std::stringstream ss;
185 ss << batch.result<< " <-- ";
186 if (batch.input.size()>0) ss << batch.input[0];
187 if (batch.input.size()>1) ss << ", " << batch.input[1];
188 os << ss.str();
189 return os;
190 }
191};
192
193/// partition one (two) vectors into 1D (2D) batches.
194
195/// derive from this class and override the \it{do_partitioning} method if you want to implement
196/// your custom partitioner
198 friend class Batch;
199
200public:
201 typedef std::list<std::pair<Batch,double>> partitionT;
202 std::size_t min_batch_size=5; ///< minimum batch size
203 std::size_t max_batch_size = 10; ///< maximum batch size (for memory management)
204 std::size_t nsubworld=1; ///< number of worlds (try to have enough batches for all worlds)
205 std::string policy = "guided"; ///< how to partition the batches
206 std::size_t dimension = 1; ///< partition one or two vectors
207
209
211
213 nsubworld=n;
214 return *this;
215 }
216 MacroTaskPartitioner& set_policy(const std::string& n) {
217 policy=n;
218 return *this;
219 }
220 MacroTaskPartitioner& set_dimension(const std::size_t& n) {
221 dimension=n;
222 return *this;
223 }
226 return *this;
227 }
230 return *this;
231 }
232
233 /// this will be called by MacroTask, it will *always* partition first (and possibly second) vector of arguments
234 template<typename tupleT>
235 partitionT partition_tasks(const tupleT& argtuple) const {
236
237 constexpr std::size_t I1 = get_index_of_first_vector_argument<tupleT, 0>();
238 constexpr std::size_t I2 = get_index_of_second_vector_argument<tupleT, 1>();
239 std::size_t vsize1=1,vsize2=1;
240 if constexpr (I2 < std::tuple_size_v<tupleT>) { // found at least 2 vectors of madness functions
241 constexpr std::size_t I2 = get_index_of_second_vector_argument<tupleT, 0>();
242 vsize2 = std::get<I2>(argtuple).size();
243 }
244 if constexpr (I1 < std::tuple_size_v<tupleT>) { // found at least 1 vector
245 constexpr std::size_t I1 = get_index_of_first_vector_argument<tupleT, 0>();
246 vsize1 = std::get<I1>(argtuple).size();
247 } else {
248 std::string msg="confused partitioning dimension: "+std::to_string(dimension) +" typeid " + typeid(tupleT).name();
249 MADNESS_EXCEPTION(msg.c_str(),1);
250 }
251
252 return do_partitioning(vsize1,vsize2,policy);
253 }
254
255 /// override this if you want your own partitioning
256 virtual partitionT do_partitioning(const std::size_t& vsize1, const std::size_t& vsize2,
257 const std::string policy) const {
258 if (dimension == 1) {
259 return do_1d_partition(vsize1, policy);
260 } else if (dimension == 2) {
261 return do_2d_partition(vsize1, vsize2, policy);
262 }
263 return partitionT();
264 }
265
266 partitionT do_1d_partition(const std::size_t vsize, const std::string policy) const {
267 partitionT result;
268 if (policy == "guided") {
269 long begin = 0;
270 long end = 0;
271 while (end < long(vsize)) {
272 end += std::min(max_batch_size, std::max(min_batch_size, ((vsize - end) / nsubworld)));
273 end = std::min(end, long(vsize));
274 Batch batch(Batch_1D(begin, end),Batch_1D(begin,end));
275 double priority=MacroTaskPartitioner::compute_priority(batch);
276 result.push_back(std::make_pair(batch,priority));
277 begin = end;
278 }
279 } else {
280 std::string msg = "unknown partitioning policy: " + policy;
281 MADNESS_EXCEPTION(msg.c_str(), 1);
282 }
283 return result;
284 }
285
286 /// outer product of 2 1d-partitionings -- result batches correspond to first input batches
287
288 /// [begin1,end1) <-- [begin1,end1) [begin2,end2)
289 partitionT do_2d_partition(const std::size_t vsize, const std::size_t v2size, const std::string policy) const {
290 partitionT partition1=do_1d_partition(vsize,policy);
291 partitionT partition2=do_1d_partition(v2size,policy);
292 partitionT result;
293 for (auto p1 : partition1) {
294 for (auto p2 : partition2) {
295 Batch batch(p1.first.input[0],p2.first.input[0],p1.first.result);
296 double priority=compute_priority(batch);
297 result.push_back(std::make_pair(batch,priority));
298 }
299 }
300 return result;
301 }
302
303 virtual double compute_priority(const Batch& batch) const {
304 return batch.size_of_input();
305 }
306
307};
308
309}
310
311#endif //MADNESS_MACROTASKPARTITIONER_H
Definition macrotaskpartitioner.h:63
friend std::ostream & operator<<(std::ostream &os, const Batch_1D &batch)
Definition macrotaskpartitioner.h:129
Batch_1D(const long &begin, const long &end)
Definition macrotaskpartitioner.h:73
bool is_full_size() const
Definition macrotaskpartitioner.h:83
tupleT copy_batch(const tupleT &arg) const
select the relevant vector elements from the argument tuple
Definition macrotaskpartitioner.h:89
long size() const
Definition macrotaskpartitioner.h:79
vecT copy_batch(const vecT v) const
given vector v, return those vector elements inside this batch
Definition macrotaskpartitioner.h:122
long end
first and first past last index [begin,end)
Definition macrotaskpartitioner.h:67
Batch_1D(const Slice &s)
Definition macrotaskpartitioner.h:70
vecT insert_batch(vecT v, const vecT &v_batch) const
given vector v, copy vector elements of v_batch into vector
Definition macrotaskpartitioner.h:107
Batch_1D()
Definition macrotaskpartitioner.h:69
long begin
Definition macrotaskpartitioner.h:67
bool operator==(const Batch_1D &other) const
Definition macrotaskpartitioner.h:75
a batch consists of a 2D-input batch and a 1D-output batch: K-batch <- (I-batch, J-batch)
Definition macrotaskpartitioner.h:139
friend std::ostream & operator<<(std::ostream &os, const Batch &batch)
pretty print this batch
Definition macrotaskpartitioner.h:183
Batch(Batch_1D input1, Batch_1D input2, Batch_1D result)
Definition macrotaskpartitioner.h:157
Batch_1D result
Definition macrotaskpartitioner.h:143
vecT insert_result_batch(vecT v, const vecT &v_batch) const
copy v_batch into the result vector
Definition macrotaskpartitioner.h:178
Batch()
Definition macrotaskpartitioner.h:145
Batch(Batch_1D input1, Batch_1D result)
Definition macrotaskpartitioner.h:156
tupleT copy_input_batch(const tupleT &arg) const
select the relevant vector elements from the argument tuple
Definition macrotaskpartitioner.h:168
Batch(const Batch &other)
Definition macrotaskpartitioner.h:146
Batch & operator=(const Batch &other)
Definition macrotaskpartitioner.h:149
std::size_t size_of_input() const
Definition macrotaskpartitioner.h:160
std::vector< Batch_1D > input
Definition macrotaskpartitioner.h:142
partition one (two) vectors into 1D (2D) batches.
Definition macrotaskpartitioner.h:197
std::string policy
how to partition the batches
Definition macrotaskpartitioner.h:205
MacroTaskPartitioner & set_min_batch_size(const long &n)
Definition macrotaskpartitioner.h:224
virtual partitionT do_partitioning(const std::size_t &vsize1, const std::size_t &vsize2, const std::string policy) const
override this if you want your own partitioning
Definition macrotaskpartitioner.h:256
std::size_t nsubworld
number of worlds (try to have enough batches for all worlds)
Definition macrotaskpartitioner.h:204
std::list< std::pair< Batch, double > > partitionT
Definition macrotaskpartitioner.h:201
MacroTaskPartitioner & set_policy(const std::string &n)
Definition macrotaskpartitioner.h:216
partitionT partition_tasks(const tupleT &argtuple) const
this will be called by MacroTask, it will always partition first (and possibly second) vector of argu...
Definition macrotaskpartitioner.h:235
MacroTaskPartitioner & set_dimension(const std::size_t &n)
Definition macrotaskpartitioner.h:220
virtual ~MacroTaskPartitioner()
Definition macrotaskpartitioner.h:210
MacroTaskPartitioner & set_max_batch_size(const long &n)
Definition macrotaskpartitioner.h:228
std::size_t dimension
partition one or two vectors
Definition macrotaskpartitioner.h:206
MacroTaskPartitioner & set_nsubworld(const long &n)
Definition macrotaskpartitioner.h:212
MacroTaskPartitioner()
Definition macrotaskpartitioner.h:208
partitionT do_2d_partition(const std::size_t vsize, const std::size_t v2size, const std::string policy) const
outer product of 2 1d-partitionings – result batches correspond to first input batches
Definition macrotaskpartitioner.h:289
partitionT do_1d_partition(const std::size_t vsize, const std::string policy) const
Definition macrotaskpartitioner.h:266
virtual double compute_priority(const Batch &batch) const
Definition macrotaskpartitioner.h:303
std::size_t min_batch_size
minimum batch size
Definition macrotaskpartitioner.h:202
std::size_t max_batch_size
maximum batch size (for memory management)
Definition macrotaskpartitioner.h:203
A slice defines a sub-range or patch of a dimension.
Definition slice.h:103
Tensor< typename Tensor< T >::scalar_type > arg(const Tensor< T > &t)
Return a new tensor holding the argument of each element of t (complex types only)
Definition tensor.h:2502
static const double v
Definition hatom_sf_dirac.cc:20
Defines madness::MadnessException for exception handling.
#define MADNESS_CHECK(condition)
Check a condition — even in a release build the condition is always evaluated so it can have side eff...
Definition madness_exception.h:182
#define MADNESS_EXCEPTION(msg, value)
Macro for throwing a MADNESS exception.
Definition madness_exception.h:119
#define MADNESS_CHECK_THROW(condition, msg)
Check a condition — even in a release build the condition is always evaluated so it can have side eff...
Definition madness_exception.h:207
Namespace for all elements and tools of MADNESS.
Definition DFParameters.h:10
constexpr auto decay_types(std::tuple< Ts... > const &) -> std::tuple< std::remove_cv_t< std::remove_reference_t< Ts > >... >
constexpr std::size_t get_index_of_first_vector_argument()
given a tuple return the index of the first argument that is a vector of Function<T,...
Definition macrotaskpartitioner.h:37
void print(const T &t, const Ts &... ts)
Print items to std::cout (items separated by spaces) and terminate with a new line.
Definition print.h:225
decltype(decay_types(std::declval< T >())) decay_tuple
Definition macrotaskpartitioner.h:22
std::string name(const FuncType &type, const int ex=-1)
Definition ccpairfunction.h:28
constexpr std::size_t get_index_of_second_vector_argument()
given a tuple return the index of the second argument that is a vector of Function<T,...
Definition macrotaskpartitioner.h:58
Definition mraimpl.h:50
Definition macrotaskpartitioner.h:25
Definition macrotaskpartitioner.h:32
static const double_complex I
Definition tdse1d.cc:164