21 #ifndef GRPPI_NATIVE_DIVIDECONQUER_H 22 #define GRPPI_NATIVE_DIVIDECONQUER_H 31 template <
typename Input,
typename Div
ider,
typename Solver,
typename Combiner>
32 typename std::result_of<Solver(Input)>::type
35 Divider && divide_op, Solver && solve_op,
36 Combiner && combine_op,
37 std::atomic<int> & num_threads)
40 using Output =
typename std::result_of<Solver(Input)>::type;
43 if(num_threads.load()>0){
44 auto subproblems = divide_op(input);
46 if(subproblems.size()>1){
47 std::vector<Output> partials(subproblems.size()-1);
50 std::vector<std::thread> tasks;
51 auto i = subproblems.begin();
52 for(i = subproblems.begin()+1; i != subproblems.end() && num_threads.load()>0 ; i++, division++){
54 tasks.emplace_back([&](
auto i,
int division) {
58 std::forward<Divider>(divide_op),
59 std::forward<Solver>(solve_op),
60 std::forward<Combiner>(combine_op),
69 for(i; i != subproblems.end(); i++){
71 std::forward<Divider>(divide_op),
72 std::forward<Solver>(solve_op),
73 std::forward<Combiner>(combine_op));
78 std::forward<Divider>(divide_op),
79 std::forward<Solver>(solve_op),
80 std::forward<Combiner>(combine_op), num_threads);
82 for(
int i=0; i< tasks.size(); i++){
86 for(
int i = 0; i<partials.size();i++){
87 out =combine_op(out,partials[i]);
90 out = solve_op(input);
94 std::forward<Divider>(divide_op),
95 std::forward<Solver>(solve_op),
96 std::forward<Combiner>(combine_op));
122 template <
typename Input,
typename Div
ider,
typename Solver,
typename Combiner>
123 typename std::result_of<Solver(Input)>::type
126 Divider && divide_op, Solver && solve_op,
127 Combiner && combine_op)
134 if (num_threads.load()>0) {
136 std::forward<Divider>(divide_op),
137 std::forward<Solver>(solve_op),
138 std::forward<Combiner>(combine_op));
141 auto subproblems = divide_op(problem);
143 if(subproblems.size()>1) {
144 using Output =
typename std::result_of<Solver(Input)>::type;
145 std::vector<Output> partials(subproblems.size()-1);
147 std::vector<std::thread> tasks;
148 auto i = subproblems.begin();
149 for(i = subproblems.begin()+1; i != subproblems.end() && num_threads.load()>0; i++, division++) {
151 tasks.emplace_back([&](
auto i,
int division) {
154 std::forward<Divider>(divide_op),
155 std::forward<Solver>(solve_op),
156 std::forward<Combiner>(combine_op),
164 for(i; i != subproblems.end(); i++) {
166 std::forward<Divider>(divide_op),
167 std::forward<Solver>(solve_op),
168 std::forward<Combiner>(combine_op));
173 std::forward<Divider>(divide_op),
174 std::forward<Solver>(solve_op),
175 std::forward<Combiner>(combine_op),
180 for (
auto && t : tasks) { t.join(); }
182 for (
auto && p : partials) { out = combine_op(out,p); }
187 return solve_op(problem);
Definition: callable_traits.h:24
int concurrency_degree() const noexcept
Get number of grppi trheads.
Definition: parallel_execution_native.h:178
Native parallel execution policy. This policy uses ISO C++ threads as implementation building block a...
Definition: parallel_execution_native.h:136
std::result_of< Solver(Input)>::type divide_conquer(parallel_execution_native &ex, Input &problem, Divider &÷_op, Solver &&solve_op, Combiner &&combine_op)
Invoke Divide/conquer pattern with native parallel execution.
Definition: native/divideconquer.h:124
native_thread_manager thread_manager()
Get a manager object for registration/deregistration in the thread index table for current thread...
Definition: parallel_execution_native.h:199
Sequential execution policy.
Definition: sequential_execution.h:31
std::result_of< Solver(Input)>::type internal_divide_conquer(parallel_execution_native &p, Input &input, Divider &÷_op, Solver &&solve_op, Combiner &&combine_op, std::atomic< int > &num_threads)
Definition: native/divideconquer.h:33