16 #ifndef GRPPI_TBB_PARALLEL_EXECUTION_TBB_H
17 #define GRPPI_TBB_PARALLEL_EXECUTION_TBB_H
21 #include "../common/mpmc_queue.h"
22 #include "../common/iterator.h"
23 #include "../common/patterns.h"
24 #include "../common/farm_pattern.h"
25 #include "../common/execution_traits.h"
27 #include <type_traits>
106 template <
typename T>
108 return {queue_size_, queue_mode_};
114 int tokens() const noexcept {
return num_tokens_; }
130 template <
typename ... InputIterators,
typename OutputIterator,
131 typename Transformer>
132 void map(std::tuple<InputIterators...> firsts,
133 OutputIterator first_out,
134 std::size_t sequence_size, Transformer transform_op)
const;
149 template <
typename InputIterator,
typename Identity,
typename Combiner>
150 auto reduce(InputIterator first, std::size_t sequence_size,
151 Identity && identity, Combiner && combine_op)
const;
167 template <
typename ... InputIterators,
typename Identity,
168 typename Transformer,
typename Combiner>
169 auto map_reduce(std::tuple<InputIterators...> firsts,
170 std::size_t sequence_size,
171 Identity && identity,
172 Transformer && transform_op, Combiner && combine_op)
const;
188 template <
typename ... InputIterators,
typename OutputIterator,
189 typename StencilTransformer,
typename Neighbourhood>
190 void stencil(std::tuple<InputIterators...> firsts, OutputIterator first_out,
191 std::size_t sequence_size,
192 StencilTransformer && transform_op,
193 Neighbourhood && neighbour_op)
const;
207 template <
typename Input,
typename Div
ider,
typename Solver,
typename Combiner>
208 [[deprecated(
"Use new interface with predicate argument")]]
210 Divider && divide_op,
212 Combiner && combine_op)
const;
229 template <
typename Input,
typename Div
ider,
typename Predicate,
typename Solver,
typename Combiner>
231 Divider && divide_op,
232 Predicate && predicate_op,
234 Combiner && combine_op)
const;
243 template <
typename Generator,
typename ... Transformers>
244 void pipeline(Generator && generate_op,
245 Transformers && ... transform_op)
const;
257 template <
typename InputType,
typename Transformer,
typename OutputType>
261 ::std::atomic<long> order {0};
264 auto item = input_queue.
pop();
265 if(!item.first) input_queue.
push(item);
268 std::forward<Transformer>(transform_op),
270 output_queue.
push(make_pair(
typename OutputType::first_type{item}, order.load()));
274 output_queue.
push(make_pair(
typename OutputType::first_type{}, order.load()));
282 template <
typename Input,
typename Div
ider,
typename Solver,
typename Combiner>
284 Divider && divide_op,
286 Combiner && combine_op,
287 std::atomic<int> & num_threads)
const;
289 template <
typename Input,
typename Div
ider,
typename Predicate,
typename Solver,
typename Combiner>
291 Divider && divide_op,
292 Predicate && predicate_op,
294 Combiner && combine_op,
295 std::atomic<int> & num_threads)
const;
297 template <
typename Input,
typename Transformer,
299 auto make_filter(Transformer && transform_op)
const;
301 template <
typename Input,
typename Transformer,
typename ... OtherTransformers,
303 auto make_filter(Transformer && transform_op,
304 OtherTransformers && ... other_transform_ops)
const;
306 template <
typename Input,
typename FarmTransformer,
307 template <
typename>
class Farm,
309 auto make_filter(Farm<FarmTransformer> & farm_obj)
const
311 return this->
template make_filter<Input>(std::move(farm_obj));
314 template <
typename Input,
typename FarmTransformer,
315 template <
typename>
class Farm,
316 requires_farm<Farm<FarmTransformer>> = 0>
317 auto make_filter(Farm<FarmTransformer> && farm_obj)
const;
319 template <
typename Input,
typename Execution,
typename Transformer,
320 template <
typename,
typename>
class Context,
321 typename ... OtherTransformers,
322 requires_context<Context<Execution,Transformer>> = 0>
323 auto make_filter(Context<Execution,Transformer> && context_op,
324 OtherTransformers &&... other_ops)
const
326 return this->
template make_filter<Input>(std::forward<Transformer>(context_op.transformer()),
327 std::forward<OtherTransformers>(other_ops)...);
330 template <
typename Input,
typename Execution,
typename Transformer,
331 template <
typename,
typename>
class Context,
332 typename ... OtherTransformers,
333 requires_context<Context<Execution,Transformer>> = 0>
334 auto make_filter(Context<Execution,Transformer> & context_op,
335 OtherTransformers &&... other_ops)
const
337 return this->
template make_filter<Input>(std::move(context_op),
338 std::forward<OtherTransformers>(other_ops)...);
342 template <
typename Input,
typename FarmTransformer,
343 template <
typename>
class Farm,
344 typename ... OtherTransformers,
345 requires_farm<Farm<FarmTransformer>> = 0>
346 auto make_filter(Farm<FarmTransformer> & filter_obj,
347 OtherTransformers && ... other_transform_ops)
const
349 return this->
template make_filter<Input>(std::move(filter_obj),
350 std::forward<OtherTransformers>(other_transform_ops)...);
353 template <
typename Input,
typename FarmTransformer,
354 template <
typename>
class Farm,
355 typename ... OtherTransformers,
356 requires_farm<Farm<FarmTransformer>> = 0>
357 auto make_filter(Farm<FarmTransformer> && filter_obj,
358 OtherTransformers && ... other_transform_ops)
const;
360 template <
typename Input,
typename Predicate,
361 template <
typename>
class Filter,
362 requires_filter<Filter<Predicate>> = 0>
363 auto make_filter(Filter<Predicate> & filter_obj)
const
365 return this->
template make_filter<Input>(std::move(filter_obj));
368 template <
typename Input,
typename Predicate,
369 template <
typename>
class Filter,
370 requires_filter<Filter<Predicate>> = 0>
371 auto make_filter(Filter<Predicate> && filter_obj)
const;
373 template <
typename Input,
typename Predicate,
374 template <
typename>
class Filter,
375 typename ... OtherTransformers,
376 requires_filter<Filter<Predicate>> = 0>
377 auto make_filter(Filter<Predicate> & filter_obj,
378 OtherTransformers && ... other_transform_ops)
const
380 return this->
template make_filter<Input>(std::move(filter_obj),
381 std::forward<OtherTransformers>(other_transform_ops)...);
384 template <
typename Input,
typename Predicate,
385 template <
typename>
class Filter,
386 typename ... OtherTransformers,
387 requires_filter<Filter<Predicate>> = 0>
388 auto make_filter(Filter<Predicate> && filter_obj,
389 OtherTransformers && ... other_transform_ops)
const;
391 template <
typename Input,
typename Combiner,
typename Identity,
392 template <
typename C,
typename I>
class Reduce,
393 typename ... OtherTransformers,
394 requires_reduce<Reduce<Combiner,Identity>> = 0>
395 auto make_filter(Reduce<Combiner,Identity> & reduce_obj,
396 OtherTransformers && ... other_transform_ops)
const
398 return this->
template make_filter<Input>(std::move(reduce_obj),
399 std::forward<OtherTransformers>(other_transform_ops)...);
402 template <
typename Input,
typename Combiner,
typename Identity,
403 template <
typename C,
typename I>
class Reduce,
404 typename ... OtherTransformers,
405 requires_reduce<Reduce<Combiner,Identity>> = 0>
406 auto make_filter(Reduce<Combiner,Identity> && reduce_obj,
407 OtherTransformers && ... other_transform_ops)
const;
409 template <
typename Input,
typename Transformer,
typename Predicate,
410 template <
typename T,
typename P>
class Iteration,
411 typename ... OtherTransformers,
412 requires_iteration<Iteration<Transformer,Predicate>> =0,
413 requires_no_pattern<Transformer> =0>
414 auto make_filter(Iteration<Transformer,Predicate> & iteration_obj,
415 OtherTransformers && ... other_transform_ops)
const
417 return this->
template make_filter<Input>(std::move(iteration_obj),
418 std::forward<OtherTransformers>(other_transform_ops)...);
421 template <
typename Input,
typename Transformer,
typename Predicate,
422 template <
typename T,
typename P>
class Iteration,
423 typename ... OtherTransformers,
424 requires_iteration<Iteration<Transformer,Predicate>> =0,
425 requires_no_pattern<Transformer> =0>
426 auto make_filter(Iteration<Transformer,Predicate> && iteration_obj,
427 OtherTransformers && ... other_transform_ops)
const;
429 template <
typename Input,
typename Transformer,
typename Predicate,
430 template <
typename T,
typename P>
class Iteration,
431 typename ... OtherTransformers,
432 requires_iteration<Iteration<Transformer,Predicate>> =0,
433 requires_pipeline<Transformer> =0>
434 auto make_filter(Iteration<Transformer,Predicate> && iteration_obj,
435 OtherTransformers && ... other_transform_ops)
const;
437 template <
typename Input,
typename ... Transformers,
438 template <
typename...>
class Pipeline,
439 typename ... OtherTransformers,
441 auto make_filter(Pipeline<Transformers...> & pipeline_obj,
442 OtherTransformers && ... other_transform_ops)
const
444 return this->
template make_filter<Input>(std::move(pipeline_obj),
445 std::forward<OtherTransformers>(other_transform_ops)...);
448 template <
typename Input,
typename ... Transformers,
449 template <
typename...>
class Pipeline,
450 typename ... OtherTransformers,
452 auto make_filter(Pipeline<Transformers...> && pipeline_obj,
453 OtherTransformers && ... other_transform_ops)
const;
455 template <
typename Input,
typename ... Transformers,
457 auto make_filter_nested(std::tuple<Transformers...> && transform_ops,
458 std::index_sequence<I...>)
const;
462 constexpr
static int default_concurrency_degree = 4;
463 int concurrency_degree_ = default_concurrency_degree;
465 bool ordering_ =
true;
467 constexpr
static int default_queue_size = 100;
468 int queue_size_ = default_queue_size;
470 constexpr
static int default_num_tokens_ = 100;
471 int num_tokens_ = default_num_tokens_;
480 template <
typename E>
482 return std::is_same<E, parallel_execution_tbb>::value;
534 template <
typename ... InputIterators,
typename OutputIterator,
535 typename Transformer>
537 std::tuple<InputIterators...> firsts,
538 OutputIterator first_out,
539 std::size_t sequence_size, Transformer transform_op)
const
542 std::size_t{0}, sequence_size,
543 [&] (std::size_t index){
550 template <
typename InputIterator,
typename Identity,
typename Combiner>
553 std::size_t sequence_size,
554 Identity && identity,
555 Combiner && combine_op)
const
558 return tbb::parallel_reduce(
559 tbb::blocked_range<InputIterator>(first, std::next(first,sequence_size)),
561 [combine_op,seq](
const auto & range,
auto value) {
562 return seq.reduce(range.begin(), range.size(), value, combine_op);
567 template <
typename ... InputIterators,
typename Identity,
568 typename Transformer,
typename Combiner>
570 std::tuple<InputIterators...> firsts,
571 std::size_t sequence_size,
573 Transformer && transform_op, Combiner && combine_op)
const
579 std::vector<result_type> partial_results(concurrency_degree_);
581 auto process_chunk = [&](
auto fins, std::size_t sz, std::size_t i) {
582 partial_results[i] = seq.map_reduce(fins, sz,
583 std::forward<result_type>(partial_results[i]),
584 std::forward<Transformer>(transform_op),
585 std::forward<Combiner>(combine_op));
588 const auto chunk_size = sequence_size/concurrency_degree_;
590 for(
int i=0; i<concurrency_degree_-1;++i) {
591 const auto delta = chunk_size * i;
594 g.run([&, chunk_firsts, i]() {
595 process_chunk(chunk_firsts, chunk_size, i);
599 const auto delta = chunk_size * (concurrency_degree_ - 1);
601 process_chunk(chunk_firsts, sequence_size - delta, concurrency_degree_-1);
605 return seq.reduce(std::next(partial_results.begin()),
606 partial_results.size()-1, std::forward<result_type>(partial_results[0]),
607 std::forward<Combiner>(combine_op));
610 template <
typename ... InputIterators,
typename OutputIterator,
611 typename StencilTransformer,
typename Neighbourhood>
613 std::tuple<InputIterators...> firsts, OutputIterator first_out,
614 std::size_t sequence_size,
615 StencilTransformer && transform_op,
616 Neighbourhood && neighbour_op)
const
618 const auto chunk_size = sequence_size / concurrency_degree_;
619 auto process_chunk = [&](
auto f, std::size_t sz, std::size_t delta) {
621 seq.
stencil(f, std::next(first_out,delta), sz,
622 std::forward<StencilTransformer>(transform_op),
623 std::forward<Neighbourhood>(neighbour_op));
627 for (
int i=0; i<concurrency_degree_-1; ++i) {
629 const auto delta = chunk_size * i;
631 process_chunk(chunk_firsts, chunk_size, delta);
635 const auto delta = chunk_size * (concurrency_degree_ - 1);
637 const auto chunk_last = std::next(std::get<0>(firsts), sequence_size);
638 process_chunk(chunk_firsts,
639 std::distance(std::get<0>(chunk_firsts), chunk_last), delta);
644 template <
typename Input,
typename Div
ider,
typename Solver,
typename Combiner>
647 Divider && divide_op,
649 Combiner && combine_op)
const
651 std::atomic<int> num_threads{concurrency_degree_-1};
653 std::forward<Divider>(divide_op), std::forward<Solver>(solve_op),
654 std::forward<Combiner>(combine_op), num_threads);
657 template <
typename Input,
typename Div
ider,
typename Predicate,
typename Solver,
typename Combiner>
660 Divider && divide_op,
661 Predicate && predicate_op,
663 Combiner && combine_op)
const
665 std::atomic<int> num_threads{concurrency_degree_-1};
667 std::forward<Divider>(divide_op), std::forward<Predicate>(predicate_op),
668 std::forward<Solver>(solve_op),
669 std::forward<Combiner>(combine_op), num_threads);
673 template <
typename Generator,
typename ... Transformers>
675 Generator && generate_op,
676 Transformers && ... transform_ops)
const
679 using namespace experimental;
681 using result_type = decay_t<
typename result_of<Generator()>::type>;
683 using output_type = optional<output_value_type>;
685 auto generator = tbb::make_filter<void, output_type>(
686 tbb::filter::serial_in_order,
687 [&](tbb::flow_control & fc) -> output_type {
688 auto item = generate_op();
700 this->
template make_filter<output_value_type>(forward<Transformers>(transform_ops)...);
703 tbb::task_group_context context;
704 tbb::parallel_pipeline(
tokens(),
712 template <
typename Input,
typename Div
ider,
typename Solver,
typename Combiner>
715 Divider && divide_op,
717 Combiner && combine_op,
718 std::atomic<int> & num_threads)
const
722 if (num_threads.load()<=0) {
724 std::forward<Divider>(divide_op), std::forward<Solver>(solve_op),
725 std::forward<Combiner>(combine_op));
728 auto subproblems = divide_op(std::forward<Input>(input));
730 if (subproblems.size()<=1) {
return solve_op(std::forward<Input>(input)); }
732 using subresult_type = std::decay_t<
typename std::result_of<Solver(Input)>::type>;
733 std::vector<subresult_type> partials(subproblems.size()-1);
737 auto i = subproblems.begin()+1;
738 while (i!=subproblems.end() && num_threads.load()>0) {
739 g.run([&,
this,it=i++,div=division++]() {
741 std::forward<Divider>(divide_op), std::forward<Solver>(solve_op),
742 std::forward<Combiner>(combine_op), num_threads);
748 while (i != subproblems.end()){
749 partials[division] = seq.divide_conquer(std::forward<Input>(*i++),
750 std::forward<Divider>(divide_op), std::forward<Solver>(solve_op),
751 std::forward<Combiner>(combine_op));
754 auto out =
divide_conquer(std::forward<Input>(*subproblems.begin()),
755 std::forward<Divider>(divide_op), std::forward<Solver>(solve_op),
756 std::forward<Combiner>(combine_op), num_threads);
760 return seq.reduce(partials.begin(), partials.size(),
761 std::forward<subresult_type>(out), std::forward<Combiner>(combine_op));
764 template <
typename Input,
typename Div
ider,
typename Predicate,
typename Solver,
typename Combiner>
767 Divider && divide_op,
768 Predicate && predicate_op,
770 Combiner && combine_op,
771 std::atomic<int> & num_threads)
const
773 constexpr sequential_execution seq;
775 if (num_threads.load()<=0) {
776 return seq.divide_conquer(std::forward<Input>(input),
777 std::forward<Divider>(divide_op),std::forward<Predicate>(predicate_op),
778 std::forward<Solver>(solve_op),
779 std::forward<Combiner>(combine_op));
783 if (predicate_op(input)) {
return solve_op(std::forward<Input>(input)); }
784 auto subproblems = divide_op(std::forward<Input>(input));
786 using subresult_type = std::decay_t<
typename std::result_of<Solver(Input)>::type>;
787 std::vector<subresult_type> partials(subproblems.size()-1);
791 auto i = subproblems.begin()+1;
792 while (i!=subproblems.end() && num_threads.load()>0) {
793 g.run([&,
this,it=i++,div=division++]() {
795 std::forward<Divider>(divide_op), std::forward<Predicate>(predicate_op),
796 std::forward<Solver>(solve_op),
797 std::forward<Combiner>(combine_op), num_threads);
803 while (i != subproblems.end()){
804 partials[division] = seq.divide_conquer(std::forward<Input>(*i++),
805 std::forward<Divider>(divide_op), std::forward<Predicate>(predicate_op),
806 std::forward<Solver>(solve_op),
807 std::forward<Combiner>(combine_op));
810 auto out =
divide_conquer(std::forward<Input>(*subproblems.begin()),
811 std::forward<Divider>(divide_op), std::forward<Predicate>(predicate_op), std::forward<Solver>(solve_op),
812 std::forward<Combiner>(combine_op), num_threads);
816 return seq.reduce(partials.begin(), partials.size(),
817 std::forward<subresult_type>(out), std::forward<Combiner>(combine_op));
820 template <
typename Input,
typename Transformer,
821 requires_no_pattern<Transformer>>
822 auto parallel_execution_tbb::make_filter(
823 Transformer && transform_op)
const
826 using namespace experimental;
828 using input_value_type = Input;
829 using gen_value_type = optional<input_value_type>;
831 return tbb::make_filter<gen_value_type, void>(
832 tbb::filter::serial_in_order,
833 [=](gen_value_type item) {
834 if (item) transform_op(*item);
838 template <
typename Input,
typename Transformer,
typename ... OtherTransformers,
839 requires_no_pattern<Transformer>>
840 auto parallel_execution_tbb::make_filter(
841 Transformer && transform_op,
842 OtherTransformers && ... other_transform_ops)
const
845 using namespace experimental;
847 using input_value_type = Input;
848 static_assert(!is_void<input_value_type>::value,
849 "Transformer must take non-void argument");
850 using gen_value_type = optional<input_value_type>;
852 decay_t<
typename result_of<Transformer(input_value_type)>::type>;
853 static_assert(!is_void<output_value_type>::value,
854 "Transformer must return a non-void result");
855 using output_type = optional<output_value_type>;
859 tbb::make_filter<gen_value_type, output_type>(
860 tbb::filter::serial_in_order,
861 [=](gen_value_type item) -> output_type {
862 if (item)
return transform_op(*item);
866 this->
template make_filter<output_value_type>(
867 std::forward<OtherTransformers>(other_transform_ops)...);
870 template <
typename Input,
typename FarmTransformer,
871 template <
typename>
class Farm,
872 requires_farm<Farm<FarmTransformer>>>
873 auto parallel_execution_tbb::make_filter(
874 Farm<FarmTransformer> && farm_obj)
const
877 using namespace experimental;
879 using input_value_type = Input;
880 using gen_value_type = optional<input_value_type>;
882 return tbb::make_filter<gen_value_type, void>(
883 tbb::filter::parallel,
884 [=](gen_value_type item) {
885 if (item) farm_obj(*item);
889 template <
typename Input,
typename FarmTransformer,
890 template <
typename>
class Farm,
891 typename ... OtherTransformers,
892 requires_farm<Farm<FarmTransformer>>>
893 auto parallel_execution_tbb::make_filter(
894 Farm<FarmTransformer> && farm_obj,
895 OtherTransformers && ... other_transform_ops)
const
898 using namespace experimental;
900 using input_value_type = Input;
901 static_assert(!is_void<input_value_type>::value,
902 "Farm must take non-void argument");
903 using gen_value_type = optional<input_value_type>;
904 using output_value_type = decay_t<
typename result_of<FarmTransformer(input_value_type)>::type>;
905 static_assert(!is_void<output_value_type>::value,
906 "Farm must return a non-void result");
907 using output_type = optional<output_value_type>;
909 return tbb::make_filter<gen_value_type, output_type>(
910 tbb::filter::parallel,
911 [&](gen_value_type item) -> output_type {
912 if (item)
return farm_obj(*item);
916 this->
template make_filter<output_value_type>(
917 std::forward<OtherTransformers>(other_transform_ops)...);
920 template <
typename Input,
typename Predicate,
921 template <
typename>
class Filter,
922 requires_filter<Filter<Predicate>>>
923 auto parallel_execution_tbb::make_filter(
924 Filter<Predicate> &&)
const
927 using namespace experimental;
929 using input_value_type = Input;
930 using gen_value_type = optional<input_value_type>;
932 return tbb::make_filter<gen_value_type, void>(
933 tbb::filter::parallel,
934 [=](gen_value_type item) {
935 if (item) filter_obj(*item);
939 template <
typename Input,
typename Predicate,
940 template <
typename>
class Filter,
941 typename ... OtherTransformers,
942 requires_filter<Filter<Predicate>>>
943 auto parallel_execution_tbb::make_filter(
944 Filter<Predicate> && filter_obj,
945 OtherTransformers && ... other_transform_ops)
const
948 using namespace experimental;
950 using input_value_type = Input;
951 static_assert(!is_void<input_value_type>::value,
952 "Filter must take non-void argument");
953 using gen_value_type = optional<input_value_type>;
955 return tbb::make_filter<gen_value_type, gen_value_type>(
956 tbb::filter::parallel,
957 [&](gen_value_type item) -> gen_value_type {
958 if (item && filter_obj(*item))
return item;
962 this->
template make_filter<input_value_type>(
963 std::forward<OtherTransformers>(other_transform_ops)...);
966 template <
typename Input,
typename Combiner,
typename Identity,
967 template <
typename C,
typename I>
class Reduce,
968 typename ... OtherTransformers,
969 requires_reduce<Reduce<Combiner,Identity>>>
970 auto parallel_execution_tbb::make_filter(
971 Reduce<Combiner,Identity> && reduce_obj,
972 OtherTransformers && ... other_transform_ops)
const
975 using namespace experimental;
977 using input_value_type = Input;
978 using gen_value_type = optional<input_value_type>;
980 return tbb::make_filter<gen_value_type, gen_value_type>(
982 [&, it=std::vector<input_value_type>()](gen_value_type item) -> gen_value_type {
983 if (!item)
return {};
984 reduce_obj.add_item(std::forward<Identity>(*item));
985 if (reduce_obj.reduction_needed()) {
986 constexpr sequential_execution seq;
987 return reduce_obj.reduce_window(seq);
992 this->
template make_filter<input_value_type>(
993 std::forward<OtherTransformers>(other_transform_ops)...);
996 template <
typename Input,
typename Transformer,
typename Predicate,
997 template <
typename T,
typename P>
class Iteration,
998 typename ... OtherTransformers,
999 requires_iteration<Iteration<Transformer,Predicate>>,
1000 requires_no_pattern<Transformer>>
1001 auto parallel_execution_tbb::make_filter(
1002 Iteration<Transformer,Predicate> && iteration_obj,
1003 OtherTransformers && ... other_transform_ops)
const
1005 using namespace std;
1006 using namespace experimental;
1008 using input_value_type = Input;
1009 using gen_value_type = optional<input_value_type>;
1011 return tbb::make_filter<gen_value_type, gen_value_type>(
1012 tbb::filter::serial,
1013 [&](gen_value_type item) -> gen_value_type {
1014 if (!item)
return {};
1016 item = iteration_obj.transform(*item);
1017 }
while (!iteration_obj.predicate(*item));
1021 this->
template make_filter<input_value_type>(
1022 std::forward<OtherTransformers>(other_transform_ops)...);
1025 template <
typename Input,
typename Transformer,
typename Predicate,
1026 template <
typename T,
typename P>
class Iteration,
1027 typename ... OtherTransformers,
1028 requires_iteration<Iteration<Transformer,Predicate>>,
1029 requires_pipeline<Transformer>>
1030 auto parallel_execution_tbb::make_filter(
1031 Iteration<Transformer,Predicate> &&,
1032 OtherTransformers && ...)
const
1034 static_assert(!is_pipeline<Transformer>,
"Not implemented");
1039 template <
typename Input,
typename ... Transformers,
1040 template <
typename...>
class Pipeline,
1041 typename ... OtherTransformers,
1043 auto parallel_execution_tbb::make_filter(
1044 Pipeline<Transformers...> && pipeline_obj,
1045 OtherTransformers && ... other_transform_ops)
const
1047 return this->
template make_filter_nested<Input>(
1048 std::tuple_cat(pipeline_obj.transformers(),
1049 std::forward_as_tuple(other_transform_ops...)),
1050 std::make_index_sequence<
sizeof...(Transformers)+
sizeof...(OtherTransformers)>());
1053 template <
typename Input,
typename ... Transformers,
1055 auto parallel_execution_tbb::make_filter_nested(
1056 std::tuple<Transformers...> && transform_ops,
1057 std::index_sequence<I...>)
const
1059 return this->
template make_filter<Input>(
1060 std::forward<Transformers>(std::get<I>(transform_ops))...);
1072 struct parallel_execution_tbb {};
1079 template <
typename E>
Definition: mpmc_queue.h:33
bool push(T item)
Definition: mpmc_queue.h:130
T pop()
Definition: mpmc_queue.h:95
TBB parallel execution policy.
Definition: parallel_execution_tbb.h:39
parallel_execution_tbb() noexcept
Default construct a TBB parallel execution policy.
Definition: parallel_execution_tbb.h:50
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 using available...
Definition: parallel_execution_tbb.h:536
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: parallel_execution_tbb.h:569
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: parallel_execution_tbb.h:551
void disable_ordering() noexcept
Disable ordering.
Definition: parallel_execution_tbb.h:85
parallel_execution_tbb(int concurrency_degree, bool order=true) noexcept
Constructs a TBB parallel execution policy.
Definition: parallel_execution_tbb.h:62
int concurrency_degree() const noexcept
Get number of grppi threads.
Definition: parallel_execution_tbb.h:75
void enable_ordering() noexcept
Enable ordering.
Definition: parallel_execution_tbb.h:80
auto divide_conquer(Input &&input, Divider &÷_op, Solver &&solve_op, Combiner &&combine_op) const
Invoke md_divide-conquer.
Definition: parallel_execution_tbb.h:645
mpmc_queue< T > make_queue() const
Makes a communication queue for elements of type T. Constructs a queue using the attributes that can ...
Definition: parallel_execution_tbb.h:107
void pipeline(mpmc_queue< InputType > &input_queue, Transformer &&transform_op, mpmc_queue< OutputType > &output_queue) const
Invoke Pipeline pattern coming from another context that uses mpmc_queues as communication channels.
Definition: parallel_execution_tbb.h:258
void set_concurrency_degree(int degree) noexcept
Set number of grppi threads.
Definition: parallel_execution_tbb.h:70
int tokens() const noexcept
Definition: parallel_execution_tbb.h:114
void stencil(std::tuple< InputIterators... > firsts, OutputIterator first_out, std::size_t sequence_size, StencilTransformer &&transform_op, Neighbourhood &&neighbour_op) const
Applies a transformation to multiple sequences leaving the result in another sequence.
Definition: parallel_execution_tbb.h:612
bool is_ordered() const noexcept
Is execution ordered.
Definition: parallel_execution_tbb.h:90
void pipeline(Generator &&generate_op, Transformers &&... transform_op) const
Invoke Pipeline pattern.
Definition: parallel_execution_tbb.h:674
void set_queue_attributes(int size, queue_mode mode, int tokens) noexcept
Sets the attributes for the queues built through make_queue<T>()
Definition: parallel_execution_tbb.h:95
Sequential execution policy.
Definition: sequential_execution.h:36
constexpr 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: sequential_execution.h:497
auto divide_conquer(Input &&input, Divider &÷_op, Solver &&solve_op, Combiner &&combine_op) const
Invoke md_divide-conquer.
Definition: sequential_execution.h:538
Definition: callable_traits.h:21
typename std::enable_if_t< is_pipeline< T >, int > requires_pipeline
Definition: pipeline_pattern.h:107
typename internal::output_value_type< I, T >::type output_value_type
Definition: pipeline_pattern.h:128
typename std::enable_if_t< is_farm< T >, int > requires_farm
Definition: farm_pattern.h:85
constexpr bool supports_pipeline< parallel_execution_tbb >()
Determines if an execution policy supports the pipeline pattern.
Definition: parallel_execution_tbb.h:532
constexpr bool supports_map_reduce< parallel_execution_tbb >()
Determines if an execution policy supports the map-reduce pattern.
Definition: parallel_execution_tbb.h:511
typename std::result_of< Transformer(Input)>::type result_type
Determines the return type of applying a function on a input type.
Definition: patterns.h:105
constexpr bool is_supported< parallel_execution_tbb >()
Determines if an execution policy is supported in the current compilation.
Definition: parallel_execution_tbb.h:490
queue_mode
Definition: mpmc_queue.h:30
auto iterators_next(T &&t, int n)
Computes next n steps from a tuple of iterators.
Definition: iterator.h:170
constexpr bool supports_divide_conquer< parallel_execution_tbb >()
Determines if an execution policy supports the divide/conquer pattern.
Definition: parallel_execution_tbb.h:525
constexpr bool supports_reduce< parallel_execution_tbb >()
Determines if an execution policy supports the reduce pattern.
Definition: parallel_execution_tbb.h:504
decltype(auto) apply_iterators_indexed(F &&f, T &&t, std::size_t i)
Applies a callable object to the values obtained from the iterators in a tuple by indexing....
Definition: iterator.h:142
constexpr bool supports_map< parallel_execution_tbb >()
Determines if an execution policy supports the map pattern.
Definition: parallel_execution_tbb.h:497
std::enable_if_t< is_no_pattern< T >, int > requires_no_pattern
Definition: patterns.h:87
constexpr bool supports_stencil< parallel_execution_tbb >()
Determines if an execution policy supports the stencil pattern.
Definition: parallel_execution_tbb.h:518
constexpr bool is_parallel_execution_tbb()
Metafunction that determines if type E is parallel_execution_tbb.
Definition: parallel_execution_tbb.h:481