GrPPI  1.0
Generic and Reusable Parallel Pattern Interface
dynamic_execution.h
Go to the documentation of this file.
1 /*
2  * Copyright 2018 Universidad Carlos III de Madrid
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 #ifndef GRPPI_DYN_DYNAMIC_EXECUTION_H
17 #define GRPPI_DYN_DYNAMIC_EXECUTION_H
18 
19 #include "../seq/sequential_execution.h"
20 #include "../native/parallel_execution_native.h"
21 #include "../tbb/parallel_execution_tbb.h"
22 #include "../omp/parallel_execution_omp.h"
23 #include "../ff/parallel_execution_ff.h"
24 
25 #include <memory>
26 
27 namespace grppi{
28 
30 public:
31 
32  dynamic_execution() noexcept :
33  execution_{}
34  {}
35 
36  template <typename E>
37  dynamic_execution(const E & e) : execution_{std::make_unique<execution<E>>(e)} {}
38 
39  bool has_execution() const { return execution_.get() != nullptr; }
40 
55  template <typename ... InputIterators, typename OutputIterator,
56  typename Transformer>
57  void map(std::tuple<InputIterators...> firsts,
58  OutputIterator first_out, std::size_t sequence_size,
59  Transformer && transform_op) const;
60 
74  template <typename InputIterator, typename Identity, typename Combiner>
75  auto reduce(InputIterator first, std::size_t sequence_size,
76  Identity && identity,
77  Combiner && combine_op) const;
78 
93  template <typename ... InputIterators, typename Identity,
94  typename Transformer, typename Combiner>
95  auto map_reduce(std::tuple<InputIterators...> firsts,
96  std::size_t sequence_size,
97  Identity && identity,
98  Transformer && transform_op, Combiner && combine_op) const;
99 
116  template <typename ... InputIterators, typename OutputIterator,
117  typename StencilTransformer, typename Neighbourhood>
118  void stencil(std::tuple<InputIterators...> firsts, OutputIterator first_out,
119  std::size_t sequence_size,
120  StencilTransformer && transform_op,
121  Neighbourhood && neighbour_op) const;
122 
135  template <typename Input, typename Divider, typename Solver, typename Combiner>
136  [[deprecated("Use new interface with predicate argument")]]
137  auto divide_conquer(Input && input,
138  Divider && divide_op,
139  Solver && solve_op,
140  Combiner && combine_op) const;
141 
142 
157  template <typename Input, typename Divider, typename Predicate, typename Solver, typename Combiner>
158  auto divide_conquer(Input && input,
159  Divider && divide_op,
160  Predicate && predicate_op,
161  Solver && solve_op,
162  Combiner && combine_op) const;
163 
164 
172  template <typename Generator, typename ... Transformers>
173  void pipeline(Generator && generate_op,
174  Transformers && ... transform_ops) const;
175 
176 private:
177 
178  class execution_base {
179  public:
180  virtual ~execution_base() {};
181  };
182 
183  template <typename E>
184  class execution : public execution_base {
185  public:
186  execution(const E & e) : ex_{e} {}
187  virtual ~execution() = default;
188  E ex_;
189  };
190 
191 private:
193  std::unique_ptr<execution_base> execution_;
194 
195 };
196 
201 template <>
202 constexpr bool is_supported<dynamic_execution>() { return true; }
203 
208 template <>
209 constexpr bool supports_map<dynamic_execution>() { return true; }
210 
215 template <>
216 constexpr bool supports_reduce<dynamic_execution>() { return true; }
217 
222 template <>
223 constexpr bool supports_map_reduce<dynamic_execution>() { return true; }
224 
229 template <>
230 constexpr bool supports_stencil<dynamic_execution>() { return true; }
231 
236 template <>
237 constexpr bool supports_divide_conquer<dynamic_execution>() { return true; }
238 
243 template <>
244 constexpr bool supports_pipeline<dynamic_execution>() { return true; }
245 
246 
247 
248 #define GRPPI_TRY_PATTERN(E,PATTERN,...)\
249 {\
250  if (supports_##PATTERN<E>()) {\
251  auto * ex = dynamic_cast<execution<E>*>(execution_.get());\
252  if (ex) {\
253  return ex->ex_.PATTERN(__VA_ARGS__);\
254  }\
255  }\
256 }
257 
258 #define GRPPI_PATTERN_NOT_IMPLEMENTED(PATTERN,...)\
259 throw std::runtime_error{"Pattern " #PATTERN " not implemented"};
260 
261 #ifdef GRPPI_OMP
262 #define GRPPI_TRY_PATTERN_OMP(PATTERN,...) \
263 GRPPI_TRY_PATTERN(parallel_execution_omp,PATTERN,__VA_ARGS__)
264 #else
265 #define GRPPI_TRY_PATTERN_OMP(PATTERN,...)
266 #endif
267 
268 #ifdef GRPPI_TBB
269 #define GRPPI_TRY_PATTERN_TBB(PATTERN,...) \
270 GRPPI_TRY_PATTERN(parallel_execution_tbb,PATTERN,__VA_ARGS__)
271 #else
272 #define GRPPI_TRY_PATTERN_TBB(PATTERN,...)
273 #endif
274 
275 #ifdef GRPPI_FF
276 #define GRPPI_TRY_PATTERN_FF(PATTERN,...) \
277 GRPPI_TRY_PATTERN(parallel_execution_ff,PATTERN,__VA_ARGS__)
278 #else
279 #define GRPPI_TRY_PATTERN_FF(PATTERN,...)
280 #endif
281 
282 #define GRPPI_TRY_PATTERN_ALL(...) \
283 GRPPI_TRY_PATTERN(sequential_execution, __VA_ARGS__) \
284 GRPPI_TRY_PATTERN(parallel_execution_native, __VA_ARGS__) \
285 GRPPI_TRY_PATTERN_OMP(__VA_ARGS__) \
286 GRPPI_TRY_PATTERN_TBB(__VA_ARGS__) \
287 GRPPI_TRY_PATTERN_FF(__VA_ARGS__) \
288 GRPPI_PATTERN_NOT_IMPLEMENTED(__VA_ARGS__)\
289 
290 #define GRPPI_TRY_PATTERN_ALL_NOFF(...) \
291 GRPPI_TRY_PATTERN(sequential_execution, __VA_ARGS__) \
292 GRPPI_TRY_PATTERN(parallel_execution_native, __VA_ARGS__) \
293 GRPPI_TRY_PATTERN_OMP(__VA_ARGS__) \
294 GRPPI_TRY_PATTERN_TBB(__VA_ARGS__) \
295 GRPPI_PATTERN_NOT_IMPLEMENTED(__VA_ARGS__)\
296 
297 template <typename ... InputIterators, typename OutputIterator,
298  typename Transformer>
300  std::tuple<InputIterators...> firsts,
301  OutputIterator first_out,
302  std::size_t sequence_size,
303  Transformer && transform_op) const
304 {
305  GRPPI_TRY_PATTERN_ALL(map, firsts, first_out, sequence_size,
306  std::forward<Transformer>(transform_op));
307 }
308 
309 template <typename InputIterator, typename Identity, typename Combiner>
310 auto dynamic_execution::reduce(InputIterator first, std::size_t sequence_size,
311  Identity && identity,
312  Combiner && combine_op) const
313 {
314  GRPPI_TRY_PATTERN_ALL(reduce, first, sequence_size,
315  std::forward<Identity>(identity), std::forward<Combiner>(combine_op));
316 }
317 
318 template <typename ... InputIterators, typename Identity,
319  typename Transformer, typename Combiner>
321  std::tuple<InputIterators...> firsts,
322  std::size_t sequence_size,
323  Identity && identity,
324  Transformer && transform_op,
325  Combiner && combine_op) const
326 {
327  GRPPI_TRY_PATTERN_ALL(map_reduce, firsts, sequence_size,
328  std::forward<Identity>(identity),
329  std::forward<Transformer>(transform_op),
330  std::forward<Combiner>(combine_op));
331 }
332 
333 template <typename ... InputIterators, typename OutputIterator,
334  typename StencilTransformer, typename Neighbourhood>
336  std::tuple<InputIterators...> firsts,
337  OutputIterator first_out,
338  std::size_t sequence_size,
339  StencilTransformer && transform_op,
340  Neighbourhood && neighbour_op) const
341 {
342  GRPPI_TRY_PATTERN_ALL(stencil, firsts, first_out, sequence_size,
343  std::forward<StencilTransformer>(transform_op),
344  std::forward<Neighbourhood>(neighbour_op));
345 }
346 
347 template <typename Input, typename Divider, typename Solver, typename Combiner>
349  Input && input,
350  Divider && divide_op,
351  Solver && solve_op,
352  Combiner && combine_op) const
353 {
354  GRPPI_TRY_PATTERN_ALL_NOFF(divide_conquer, std::forward<Input>(input),
355  std::forward<Divider>(divide_op),
356  std::forward<Solver>(solve_op),
357  std::forward<Combiner>(combine_op));
358 }
359 
360 
361 template <typename Input, typename Divider,typename Predicate, typename Solver, typename Combiner>
363  Input && input,
364  Divider && divide_op,
365  Predicate && predicate_op,
366  Solver && solve_op,
367  Combiner && combine_op) const
368 {
369  GRPPI_TRY_PATTERN_ALL(divide_conquer, std::forward<Input>(input),
370  std::forward<Divider>(divide_op),
371  std::forward<Predicate>(predicate_op),
372  std::forward<Solver>(solve_op),
373  std::forward<Combiner>(combine_op));
374 }
375 
376 template <typename Generator, typename ... Transformers>
378  Generator && generate_op,
379  Transformers && ... transform_ops) const
380 {
381  GRPPI_TRY_PATTERN_ALL(pipeline, std::forward<Generator>(generate_op),
382  std::forward<Transformers>(transform_ops)...);
383 }
384 
385 #undef GRPPI_TRY_PATTERN
386 #undef GRPPI_TRY_PATTERN_OMP
387 #undef GRPPI_TRY_PATTERN_TBB
388 #undef GRPPI_TRY_PATTERN_ALL
389 #undef GRPPI_TRY_PATTERN_ALL_NOFF
390 
391 } // end namespace grppi
392 
393 #endif
Definition: dynamic_execution.h:29
auto map_reduce(std::tuple< InputIterators... > firsts, std::size_t sequence_size, Identity &&identity, Transformer &&transform_op, Combiner &&combine_op) const
Applies a map/reduce operation to a sequence of data items.
Definition: dynamic_execution.h:320
auto divide_conquer(Input &&input, Divider &&divide_op, Solver &&solve_op, Combiner &&combine_op) const
Invoke md_divide-conquer.
Definition: dynamic_execution.h:348
void stencil(std::tuple< InputIterators... > firsts, OutputIterator first_out, std::size_t sequence_size, StencilTransformer &&transform_op, Neighbourhood &&neighbour_op) const
Applies a stencil to multiple sequences leaving the result in another sequence.
Definition: dynamic_execution.h:335
void pipeline(Generator &&generate_op, Transformers &&... transform_ops) const
Invoke Pipeline pattern.
Definition: dynamic_execution.h:377
dynamic_execution() noexcept
Definition: dynamic_execution.h:32
auto reduce(InputIterator first, std::size_t sequence_size, Identity &&identity, Combiner &&combine_op) const
Applies a reduction to a sequence of data items.
Definition: dynamic_execution.h:310
void map(std::tuple< InputIterators... > firsts, OutputIterator first_out, std::size_t sequence_size, Transformer &&transform_op) const
Applies a transformation to multiple sequences leaving the result in another sequence.
Definition: dynamic_execution.h:299
dynamic_execution(const E &e)
Definition: dynamic_execution.h:37
bool has_execution() const
Definition: dynamic_execution.h:39
#define GRPPI_TRY_PATTERN_ALL(...)
Definition: dynamic_execution.h:282
#define GRPPI_TRY_PATTERN_ALL_NOFF(...)
Definition: dynamic_execution.h:290
Definition: callable_traits.h:21
constexpr bool supports_stencil< dynamic_execution >()
Determines if an execution policy supports the stencil pattern.
Definition: dynamic_execution.h:230
constexpr bool supports_map_reduce< dynamic_execution >()
Determines if an execution policy supports the map-reduce pattern.
Definition: dynamic_execution.h:223
constexpr bool supports_pipeline< dynamic_execution >()
Determines if an execution policy supports the pipeline pattern.
Definition: dynamic_execution.h:244
constexpr bool supports_reduce< dynamic_execution >()
Determines if an execution policy supports the reduce pattern.
Definition: dynamic_execution.h:216
constexpr bool supports_divide_conquer< dynamic_execution >()
Determines if an execution policy supports the divide/conquer pattern.
Definition: dynamic_execution.h:237
constexpr bool is_supported< dynamic_execution >()
Determines if an execution policy is supported in the current compilation.
Definition: dynamic_execution.h:202
constexpr bool supports_map< dynamic_execution >()
Determines if an execution policy supports the map pattern.
Definition: dynamic_execution.h:209