Line | % of fetches | Source |
---|---|---|
1 | // Copyright (c) 2007-2016 Hartmut Kaiser | |
2 | // | |
3 | // Distributed under the Boost Software License, Version 1.0. (See accompanying | |
4 | // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) | |
5 | ||
6 | #if !defined(HPX_PARALLEL_UTIL_PARTITIONER_MAY_27_2014_1040PM) | |
7 | #define HPX_PARALLEL_UTIL_PARTITIONER_MAY_27_2014_1040PM | |
8 | ||
9 | #include <hpx/config.hpp> | |
10 | #include <hpx/dataflow.hpp> | |
11 | #include <hpx/exception_list.hpp> | |
12 | #include <hpx/lcos/wait_all.hpp> | |
13 | #include <hpx/util/decay.hpp> | |
14 | #include <hpx/util/deferred_call.hpp> | |
15 | #include <hpx/util/tuple.hpp> | |
16 | ||
17 | #include <hpx/parallel/execution_policy.hpp> | |
18 | #include <hpx/parallel/executors/executor_parameter_traits.hpp> | |
19 | #include <hpx/parallel/executors/executor_traits.hpp> | |
20 | #include <hpx/parallel/traits/extract_partitioner.hpp> | |
21 | #include <hpx/parallel/util/detail/chunk_size.hpp> | |
22 | #include <hpx/parallel/util/detail/handle_local_exceptions.hpp> | |
23 | #include <hpx/parallel/util/detail/partitioner_iteration.hpp> | |
24 | #include <hpx/parallel/util/detail/scoped_executor_parameters.hpp> | |
25 | ||
26 | #include <boost/exception_ptr.hpp> | |
27 | #include <boost/range/functions.hpp> | |
28 | ||
29 | #include <cstddef> | |
30 | #include <iterator> | |
31 | #include <list> | |
32 | #include <memory> | |
33 | #include <utility> | |
34 | #include <vector> | |
35 | ||
36 | /////////////////////////////////////////////////////////////////////////////// | |
37 | namespace hpx { namespace parallel { namespace util | |
38 | { | |
39 | /////////////////////////////////////////////////////////////////////////// | |
40 | namespace detail | |
41 | { | |
42 | /////////////////////////////////////////////////////////////////////// | |
43 | // The static partitioner simply spawns one chunk of iterations for | |
44 | // each available core. | |
45 | template <typename ExPolicy_, typename R, typename Result = void> | |
46 | struct static_partitioner | |
47 | { | |
48 | template <typename ExPolicy, typename FwdIter, typename F1, typename F2> | |
49 | static R call(ExPolicy && policy, FwdIter first, | |
50 | std::size_t count, F1 && f1, F2 && f2) | |
51 | { | |
52 | typedef typename hpx::util::decay<ExPolicy>::type::executor_type | |
53 | executor_type; | |
54 | typedef typename hpx::parallel::executor_traits<executor_type> | |
55 | executor_traits; | |
56 | ||
57 | typedef typename | |
58 | hpx::util::decay<ExPolicy>::type::executor_parameters_type | |
59 | parameters_type; | |
60 | typedef executor_parameter_traits<parameters_type> | |
61 | parameters_traits; | |
62 | ||
63 | // inform parameter traits | |
64 | scoped_executor_parameters<parameters_type> scoped_param( | |
65 | policy.parameters()); | |
66 | ||
67 | std::vector<hpx::future<Result> > inititems; | |
68 | std::list<boost::exception_ptr> errors; | |
69 | ||
70 | try { | |
71 | // estimate a chunk size based on number of cores used | |
72 | typedef typename parameters_traits::has_variable_chunk_size | |
73 | has_variable_chunk_size; | |
74 | ||
75 | auto shapes = | |
76 | get_bulk_iteration_shape(policy, inititems, f1, | |
77 | first, count, 1, has_variable_chunk_size()); | |
78 | ||
79 | std::vector<hpx::future<Result> > workitems = | |
80 | executor_traits::bulk_async_execute( | |
81 | policy.executor(), | |
82 | partitioner_iteration<Result, F1>{std::forward<F1>(f1)}, | |
83 | std::move(shapes)); | |
84 | ||
85 | // add the newly created workitems to the list | |
86 | inititems.reserve(inititems.size() + workitems.size()); | |
87 | std::move(workitems.begin(), workitems.end(), | |
88 | std::back_inserter(inititems)); | |
89 | } | |
90 | catch (...) { | |
91 | handle_local_exceptions<ExPolicy>::call( | |
92 | boost::current_exception(), errors); | |
93 | } | |
94 | ||
95 | // wait for all tasks to finish | |
96 | hpx::wait_all(inititems); | |
97 | ||
98 | // always rethrow if 'errors' is not empty or inititems has | |
99 | // exceptional future | |
100 | handle_local_exceptions<ExPolicy>::call(inititems, errors); | |
101 | ||
102 | try { | |
103 | return f2(std::move(inititems)); | |
104 | } | |
105 | catch (...) { | |
106 | // rethrow either bad_alloc or exception_list | |
107 | handle_local_exceptions<ExPolicy>::call( | |
108 | boost::current_exception()); | |
109 | } | |
110 | } | |
111 | ||
112 | template <typename ExPolicy, typename FwdIter, typename F1, | |
113 | typename F2, typename Data> | |
114 | // requires is_container<Data> | |
115 | static R call_with_data(ExPolicy && policy, | |
116 | FwdIter first, std::size_t count, F1 && f1, F2 && f2, | |
117 | std::vector<std::size_t> const& chunk_sizes, Data && data) | |
118 | { | |
119 | HPX_ASSERT(boost::size(data) >= boost::size(chunk_sizes)); | |
120 | ||
121 | typedef typename hpx::util::decay<ExPolicy>::type::executor_type | |
122 | executor_type; | |
123 | typedef typename hpx::parallel::executor_traits<executor_type> | |
124 | executor_traits; | |
125 | ||
126 | typedef typename | |
127 | hpx::util::decay<ExPolicy>::type::executor_parameters_type | |
128 | parameters_type; | |
129 | ||
130 | typedef typename hpx::util::decay<Data>::type data_type; | |
131 | ||
132 | // inform parameter traits | |
133 | scoped_executor_parameters<parameters_type> scoped_param( | |
134 | policy.parameters()); | |
135 | ||
136 | typename data_type::const_iterator data_it = boost::begin(data); | |
137 | typename std::vector<std::size_t>::const_iterator chunk_size_it = | |
138 | boost::begin(chunk_sizes); | |
139 | ||
140 | typedef typename hpx::util::tuple< | |
141 | typename data_type::value_type, FwdIter, std::size_t | |
142 | > tuple_type; | |
143 | ||
144 | std::vector<hpx::future<Result> > workitems; | |
145 | std::list<boost::exception_ptr> errors; | |
146 | ||
147 | try { | |
148 | // schedule every chunk on a separate thread | |
149 | std::vector<tuple_type> shape; | |
150 | shape.reserve(chunk_sizes.size()); | |
151 | ||
152 | while(count != 0) | |
153 | { | |
154 | std::size_t chunk = (std::min)(count, *chunk_size_it); | |
155 | HPX_ASSERT(chunk != 0); | |
156 | ||
157 | shape.push_back(hpx::util::make_tuple( | |
158 | *data_it, first, chunk)); | |
159 | ||
160 | count -= chunk; | |
161 | std::advance(first, chunk); | |
162 | ||
163 | ++data_it; | |
164 | ++chunk_size_it; | |
165 | } | |
166 | ||
167 | HPX_ASSERT(chunk_size_it == chunk_sizes.end()); | |
168 | ||
169 | workitems = executor_traits::bulk_async_execute( | |
170 | policy.executor(), | |
171 | partitioner_iteration<Result, F1>{std::forward<F1>(f1)}, | |
172 | std::move(shape)); | |
173 | } | |
174 | catch (...) { | |
175 | handle_local_exceptions<ExPolicy>::call( | |
176 | boost::current_exception(), errors); | |
177 | } | |
178 | ||
179 | // wait for all tasks to finish | |
180 | hpx::wait_all(workitems); | |
181 | ||
182 | // always rethrow if 'errors' is not empty or inititems has | |
183 | // exceptional future | |
184 | handle_local_exceptions<ExPolicy>::call(workitems, errors); | |
185 | ||
186 | try { | |
187 | return f2(std::move(workitems)); | |
188 | } | |
189 | catch (...) { | |
190 | // rethrow either bad_alloc or exception_list | |
191 | handle_local_exceptions<ExPolicy>::call( | |
192 | boost::current_exception()); | |
193 | } | |
194 | } | |
195 | ||
196 | template <typename ExPolicy, typename FwdIter, typename Stride, | |
197 | typename F1, typename F2> | |
198 | static R call_with_index(ExPolicy && policy, FwdIter first, | |
199 | std::size_t count, Stride stride, F1 && f1, F2 && f2) | |
200 | { | |
201 | typedef typename hpx::util::decay<ExPolicy>::type::executor_type | |
202 | executor_type; | |
203 | typedef typename hpx::parallel::executor_traits<executor_type> | |
204 | executor_traits; | |
205 | ||
206 | typedef typename | |
207 | hpx::util::decay<ExPolicy>::type::executor_parameters_type | |
208 | parameters_type; | |
209 | typedef executor_parameter_traits<parameters_type> | |
210 | parameters_traits; | |
211 | ||
212 | // inform parameter traits | |
213 | scoped_executor_parameters<parameters_type> scoped_param( | |
214 | policy.parameters()); | |
215 | ||
216 | std::vector<hpx::future<Result> > inititems; | |
217 | std::list<boost::exception_ptr> errors; | |
218 | ||
219 | try { | |
220 | // estimate a chunk size based on number of cores used | |
221 | typedef typename parameters_traits::has_variable_chunk_size | |
222 | has_variable_chunk_size; | |
223 | ||
224 | auto shapes = | |
225 | get_bulk_iteration_shape_idx(policy, inititems, f1, | |
226 | first, count, stride, has_variable_chunk_size()); | |
227 | ||
228 | std::vector<hpx::future<Result> > workitems = | |
229 | executor_traits::bulk_async_execute( | |
230 | policy.executor(), | |
231 | partitioner_iteration<Result, F1>{std::forward<F1>(f1)}, | |
232 | std::move(shapes)); | |
233 | ||
234 | inititems.reserve(inititems.size() + workitems.size()); | |
235 | std::move(workitems.begin(), workitems.end(), | |
236 | std::back_inserter(inititems)); | |
237 | } | |
238 | catch (...) { | |
239 | handle_local_exceptions<ExPolicy>::call( | |
240 | boost::current_exception(), errors); | |
241 | } | |
242 | ||
243 | // wait for all tasks to finish | |
244 | hpx::wait_all(inititems); | |
245 | ||
246 | // always rethrow if 'errors' is not empty or inititems has | |
247 | // exceptional future | |
248 | handle_local_exceptions<ExPolicy>::call(inititems, errors); | |
249 | ||
250 | try { | |
251 | return f2(std::move(inititems)); | |
252 | } | |
253 | catch (...) { | |
254 | // rethrow either bad_alloc or exception_list | |
255 | handle_local_exceptions<ExPolicy>::call( | |
256 | boost::current_exception()); | |
257 | } | |
258 | } | |
259 | }; | |
260 | ||
261 | template <typename R, typename Result> | |
262 | struct static_partitioner<parallel_task_execution_policy, R, Result> | |
263 | { | |
264 | template <typename ExPolicy, typename FwdIter, typename F1, typename F2> | |
265 | static hpx::future<R> call(ExPolicy && policy, | |
266 | FwdIter first, std::size_t count, F1 && f1, F2 && f2) | |
267 | { | |
268 | typedef typename hpx::util::decay<ExPolicy>::type::executor_type | |
269 | executor_type; | |
270 | typedef typename hpx::parallel::executor_traits<executor_type> | |
271 | executor_traits; | |
272 | ||
273 | typedef typename | |
274 | hpx::util::decay<ExPolicy>::type::executor_parameters_type | |
275 | parameters_type; | |
276 | typedef executor_parameter_traits<parameters_type> | |
277 | parameters_traits; | |
278 | ||
279 | typedef scoped_executor_parameters<parameters_type> | |
280 | scoped_executor_parameters; | |
281 | ||
282 | // inform parameter traits | |
283 | std::shared_ptr<scoped_executor_parameters> | |
284 | scoped_param(std::make_shared< | |
285 | scoped_executor_parameters | |
286 | >(policy.parameters())); | |
287 | ||
288 | std::vector<hpx::future<Result> > inititems; | |
289 | std::list<boost::exception_ptr> errors; | |
290 | ||
291 | try { | |
292 | // estimate a chunk size based on number of cores used | |
293 | typedef typename parameters_traits::has_variable_chunk_size | |
294 | has_variable_chunk_size; | |
295 | ||
296 | auto shapes = | |
297 | get_bulk_iteration_shape(policy, inititems, f1, | |
298 | first, count, 1, has_variable_chunk_size()); | |
299 | ||
300 | std::vector<hpx::future<Result> > workitems = | |
301 | executor_traits::bulk_async_execute( | |
302 | policy.executor(), | |
303 | partitioner_iteration<Result, F1>{std::forward<F1>(f1)}, | |
304 | std::move(shapes)); | |
305 | ||
306 | inititems.reserve(inititems.size() + workitems.size()); | |
307 | std::move(workitems.begin(), workitems.end(), | |
308 | std::back_inserter(inititems)); | |
309 | } | |
310 | catch (std::bad_alloc const&) { | |
311 | return hpx::make_exceptional_future<R>( | |
312 | boost::current_exception()); | |
313 | } | |
314 | catch (...) { | |
315 | errors.push_back(boost::current_exception()); | |
316 | } | |
317 | ||
318 | // wait for all tasks to finish | |
319 | return hpx::dataflow( | |
320 | [f2, errors, scoped_param]( | |
321 | std::vector<hpx::future<Result> > && r) mutable -> R | |
322 | { | |
323 | // inform parameter traits | |
324 | handle_local_exceptions<ExPolicy>::call(r, errors); | |
325 | return f2(std::move(r)); | |
326 | }, | |
327 | std::move(inititems)); | |
328 | } | |
329 | ||
330 | template <typename ExPolicy, typename FwdIter, typename F1, | |
331 | typename F2, typename Data> | |
332 | // requires is_container<Data> | |
333 | static hpx::future<R> call_with_data(ExPolicy && policy, | |
334 | FwdIter first, std::size_t count, F1 && f1, F2 && f2, | |
335 | std::vector<std::size_t> const& chunk_sizes, Data && data) | |
336 | { | |
337 | HPX_ASSERT(boost::size(data) >= boost::size(chunk_sizes)); | |
338 | ||
339 | typedef typename hpx::util::decay<ExPolicy>::type::executor_type | |
340 | executor_type; | |
341 | typedef typename hpx::parallel::executor_traits<executor_type> | |
342 | executor_traits; | |
343 | ||
344 | typedef typename | |
345 | hpx::util::decay<ExPolicy>::type::executor_parameters_type | |
346 | parameters_type; | |
347 | typedef scoped_executor_parameters<parameters_type> | |
348 | scoped_executor_parameters; | |
349 | ||
350 | typedef typename hpx::util::decay<Data>::type data_type; | |
351 | ||
352 | // inform parameter traits | |
353 | std::shared_ptr<scoped_executor_parameters> | |
354 | scoped_param(std::make_shared< | |
355 | scoped_executor_parameters | |
356 | >(policy.parameters())); | |
357 | ||
358 | typename data_type::const_iterator data_it = boost::begin(data); | |
359 | typename std::vector<std::size_t>::const_iterator chunk_size_it = | |
360 | boost::begin(chunk_sizes); | |
361 | ||
362 | typedef typename hpx::util::tuple< | |
363 | typename data_type::value_type, FwdIter, std::size_t | |
364 | > tuple_type; | |
365 | ||
366 | std::vector<hpx::future<Result> > workitems; | |
367 | std::list<boost::exception_ptr> errors; | |
368 | ||
369 | try { | |
370 | // schedule every chunk on a separate thread | |
371 | std::vector<tuple_type> shape; | |
372 | shape.reserve(chunk_sizes.size()); | |
373 | ||
374 | while(count != 0) | |
375 | { | |
376 | std::size_t chunk = (std::min)(count, *chunk_size_it); | |
377 | HPX_ASSERT(chunk != 0); | |
378 | ||
379 | shape.push_back(hpx::util::make_tuple( | |
380 | *data_it, first, chunk)); | |
381 | ||
382 | count -= chunk; | |
383 | std::advance(first, chunk); | |
384 | ||
385 | ++data_it; | |
386 | ++chunk_size_it; | |
387 | } | |
388 | HPX_ASSERT(chunk_size_it == chunk_sizes.end()); | |
389 | ||
390 | workitems = executor_traits::bulk_async_execute( | |
391 | policy.executor(), | |
392 | partitioner_iteration<Result, F1>{std::forward<F1>(f1)}, | |
393 | std::move(shape)); | |
394 | } | |
395 | catch (std::bad_alloc const&) { | |
396 | return hpx::make_exceptional_future<R>( | |
397 | boost::current_exception()); | |
398 | } | |
399 | catch (...) { | |
400 | errors.push_back(boost::current_exception()); | |
401 | } | |
402 | ||
403 | // wait for all tasks to finish | |
404 | return hpx::dataflow( | |
405 | [f2, errors, scoped_param]( | |
406 | std::vector<hpx::future<Result> > && r) mutable -> R | |
407 | { | |
408 | // inform parameter traits | |
409 | handle_local_exceptions<ExPolicy>::call(r, errors); | |
410 | return f2(std::move(r)); | |
411 | }, | |
412 | std::move(workitems)); | |
413 | } | |
414 | ||
415 | template <typename ExPolicy, typename FwdIter, typename Stride, | |
416 | typename F1, typename F2> | |
417 | static hpx::future<R> call_with_index(ExPolicy && policy, | |
418 | FwdIter first, std::size_t count, Stride stride, | |
419 | F1 && f1, F2 && f2) | |
420 | { | |
421 | typedef typename hpx::util::decay<ExPolicy>::type::executor_type | |
422 | executor_type; | |
423 | typedef typename hpx::parallel::executor_traits<executor_type> | |
424 | executor_traits; | |
425 | ||
426 | typedef typename | |
427 | hpx::util::decay<ExPolicy>::type::executor_parameters_type | |
428 | parameters_type; | |
429 | typedef executor_parameter_traits<parameters_type> | |
430 | parameters_traits; | |
431 | ||
432 | typedef scoped_executor_parameters<parameters_type> | |
433 | scoped_executor_parameters; | |
434 | ||
435 | // inform parameter traits | |
436 | std::shared_ptr<scoped_executor_parameters> | |
437 | scoped_param(std::make_shared< | |
438 | scoped_executor_parameters | |
439 | >(policy.parameters())); | |
440 | ||
441 | std::vector<hpx::future<Result> > inititems; | |
442 | std::list<boost::exception_ptr> errors; | |
443 | ||
444 | try { | |
445 | // estimate a chunk size based on number of cores used | |
446 | typedef typename parameters_traits::has_variable_chunk_size | |
447 | has_variable_chunk_size; | |
448 | ||
449 | auto shapes = | |
450 | get_bulk_iteration_shape_idx(policy, inititems, f1, | |
451 | first, count, stride, has_variable_chunk_size()); | |
452 | ||
453 | std::vector<hpx::future<Result> > workitems = | |
454 | executor_traits::bulk_async_execute( | |
455 | policy.executor(), | |
456 | partitioner_iteration<Result, F1>{std::forward<F1>(f1)}, | |
457 | std::move(shapes)); | |
458 | ||
459 | std::move(workitems.begin(), workitems.end(), | |
460 | std::back_inserter(inititems)); | |
461 | } | |
462 | catch (std::bad_alloc const&) { | |
463 | return hpx::make_exceptional_future<R>( | |
464 | boost::current_exception()); | |
465 | } | |
466 | catch (...) { | |
467 | errors.push_back(boost::current_exception()); | |
468 | } | |
469 | ||
470 | // wait for all tasks to finish | |
471 | return hpx::dataflow( | |
472 | [f2, errors, scoped_param]( | |
473 | std::vector<hpx::future<Result> > && r) mutable -> R | |
474 | { | |
475 | // inform parameter traits | |
476 | handle_local_exceptions<ExPolicy>::call(r, errors); | |
477 | return f2(std::move(r)); | |
478 | }, | |
479 | std::move(inititems)); | |
480 | } | |
481 | }; | |
482 | ||
483 | template <typename Executor, typename Parameters, typename R, | |
484 | typename Result> | |
485 | struct static_partitioner< | |
486 | parallel_task_execution_policy_shim<Executor, Parameters>, | |
487 | R, Result> | |
488 | : static_partitioner<parallel_task_execution_policy, R, Result> | |
489 | {}; | |
490 | ||
491 | /////////////////////////////////////////////////////////////////////// | |
492 | // ExPolicy: execution policy | |
493 | // R: overall result type | |
494 | // Result: intermediate result type of first step | |
495 | // PartTag: select appropriate partitioner | |
496 | template <typename ExPolicy, typename R, typename Result, typename Tag> | |
497 | struct partitioner; | |
498 | ||
499 | /////////////////////////////////////////////////////////////////////// | |
500 | template <typename ExPolicy_, typename R, typename Result> | |
501 | struct partitioner<ExPolicy_, R, Result, | |
502 | parallel::traits::static_partitioner_tag> | |
503 | { | |
504 | template <typename ExPolicy, typename FwdIter, typename F1, typename F2> | |
505 | static R call(ExPolicy && policy, FwdIter first, | |
506 | std::size_t count, F1 && f1, F2 && f2) | |
507 | { | |
508 | return static_partitioner< | |
509 | typename hpx::util::decay<ExPolicy>::type, R, Result | |
510 | >::call( | |
511 | std::forward<ExPolicy>(policy), first, count, | |
512 | std::forward<F1>(f1), std::forward<F2>(f2)); | |
513 | } | |
514 | ||
515 | template <typename ExPolicy, typename FwdIter, typename F1, | |
516 | typename F2, typename Data> | |
517 | static R call_with_data(ExPolicy && policy, FwdIter first, | |
518 | std::size_t count, F1 && f1, F2 && f2, | |
519 | std::vector<std::size_t> const& chunk_sizes, Data && data) | |
520 | { | |
521 | return static_partitioner< | |
522 | typename hpx::util::decay<ExPolicy>::type, R, Result | |
523 | >::call_with_data( | |
524 | std::forward<ExPolicy>(policy), first, count, | |
525 | std::forward<F1>(f1), std::forward<F2>(f2), chunk_sizes, | |
526 | std::forward<Data>(data)); | |
527 | } | |
528 | ||
529 | template <typename ExPolicy, typename FwdIter, typename Stride, typename F1, | |
530 | typename F2> | |
531 | static R call_with_index(ExPolicy && policy, FwdIter first, | |
532 | std::size_t count, Stride stride, F1 && f1, F2 && f2) | |
533 | { | |
534 | return static_partitioner< | |
535 | typename hpx::util::decay<ExPolicy>::type, R, Result | |
536 | >::call_with_index( | |
537 | std::forward<ExPolicy>(policy), first, count, stride, | |
538 | std::forward<F1>(f1), std::forward<F2>(f2)); | |
539 | } | |
540 | }; | |
541 | ||
542 | template <typename R, typename Result> | |
543 | struct partitioner<parallel_task_execution_policy, R, Result, | |
544 | parallel::traits::static_partitioner_tag> | |
545 | { | |
546 | template <typename ExPolicy, typename FwdIter, typename F1, | |
547 | typename F2> | |
548 | static hpx::future<R> call(ExPolicy && policy, | |
549 | FwdIter first, std::size_t count, F1 && f1, F2 && f2) | |
550 | { | |
551 | return static_partitioner< | |
552 | typename hpx::util::decay<ExPolicy>::type, R, Result | |
553 | >::call( | |
554 | std::forward<ExPolicy>(policy), first, count, | |
555 | std::forward<F1>(f1), std::forward<F2>(f2)); | |
556 | } | |
557 | ||
558 | template <typename ExPolicy, typename FwdIter, typename F1, | |
559 | typename F2, typename Data> | |
560 | static hpx::future<R> call_with_data(ExPolicy && policy, | |
561 | FwdIter first, std::size_t count, F1 && f1, F2 && f2, | |
562 | std::vector<std::size_t> const& chunk_sizes, Data && data) | |
563 | { | |
564 | return static_partitioner< | |
565 | typename hpx::util::decay<ExPolicy>::type, R, Result | |
566 | >::call_with_data( | |
567 | std::forward<ExPolicy>(policy), first, count, | |
568 | std::forward<F1>(f1), std::forward<F2>(f2), | |
569 | chunk_sizes, std::forward<Data>(data)); | |
570 | } | |
571 | ||
572 | template <typename ExPolicy, typename FwdIter, typename Stride, | |
573 | typename F1, typename F2> | |
574 | static hpx::future<R> call_with_index(ExPolicy && policy, | |
575 | FwdIter first, std::size_t count, Stride stride, | |
576 | F1 && f1, F2 && f2) | |
577 | { | |
578 | return static_partitioner< | |
579 | typename hpx::util::decay<ExPolicy>::type, R, Result | |
580 | >::call_with_index( | |
581 | std::forward<ExPolicy>(policy), first, count, stride, | |
582 | std::forward<F1>(f1), std::forward<F2>(f2)); | |
583 | } | |
584 | }; | |
585 | ||
586 | #if defined(HPX_HAVE_DATAPAR) | |
587 | template <typename R, typename Result> | |
588 | struct partitioner<datapar_task_execution_policy, R, Result, | |
589 | parallel::traits::static_partitioner_tag> | |
590 | { | |
591 | template <typename ExPolicy, typename FwdIter, typename F1, | |
592 | typename F2> | |
593 | static hpx::future<R> call(ExPolicy && policy, | |
594 | FwdIter first, std::size_t count, F1 && f1, F2 && f2) | |
595 | { | |
596 | return static_partitioner< | |
597 | parallel_task_execution_policy, R, Result | |
598 | >::call( | |
599 | std::forward<ExPolicy>(policy), first, count, | |
600 | std::forward<F1>(f1), std::forward<F2>(f2)); | |
601 | } | |
602 | ||
603 | template <typename ExPolicy, typename FwdIter, typename F1, | |
604 | typename F2, typename Data> | |
605 | static hpx::future<R> call_with_data(ExPolicy && policy, | |
606 | FwdIter first, std::size_t count, F1 && f1, F2 && f2, | |
607 | std::vector<std::size_t> const& chunk_sizes, Data && data) | |
608 | { | |
609 | return static_partitioner< | |
610 | parallel_task_execution_policy, R, Result | |
611 | >::call_with_data( | |
612 | std::forward<ExPolicy>(policy), first, count, | |
613 | std::forward<F1>(f1), std::forward<F2>(f2), | |
614 | chunk_sizes, std::forward<Data>(data)); | |
615 | } | |
616 | ||
617 | template <typename ExPolicy, typename FwdIter, typename Stride, | |
618 | typename F1, typename F2> | |
619 | static hpx::future<R> call_with_index(ExPolicy && policy, | |
620 | FwdIter first, std::size_t count, Stride stride, | |
621 | F1 && f1, F2 && f2) | |
622 | { | |
623 | return static_partitioner< | |
624 | parallel_task_execution_policy, R, Result | |
625 | >::call_with_index( | |
626 | std::forward<ExPolicy>(policy), first, count, stride, | |
627 | std::forward<F1>(f1), std::forward<F2>(f2)); | |
628 | } | |
629 | }; | |
630 | #endif | |
631 | ||
632 | template <typename Executor, typename Parameters, typename R, | |
633 | typename Result> | |
634 | struct partitioner< | |
635 | parallel_task_execution_policy_shim<Executor, Parameters>, | |
636 | R, Result, parallel::traits::static_partitioner_tag> | |
637 | : partitioner<parallel_task_execution_policy, R, Result, | |
638 | parallel::traits::static_partitioner_tag> | |
639 | {}; | |
640 | ||
641 | template <typename Executor, typename Parameters, typename R, | |
642 | typename Result> | |
643 | struct partitioner< | |
644 | parallel_task_execution_policy_shim<Executor, Parameters>, | |
645 | R, Result, parallel::traits::auto_partitioner_tag> | |
646 | : partitioner<parallel_task_execution_policy, R, Result, | |
647 | parallel::traits::auto_partitioner_tag> | |
648 | {}; | |
649 | ||
650 | template <typename Executor, typename Parameters, typename R, | |
651 | typename Result> | |
652 | struct partitioner< | |
653 | parallel_task_execution_policy_shim<Executor, Parameters>, | |
654 | R, Result, parallel::traits::default_partitioner_tag> | |
655 | : partitioner<parallel_task_execution_policy, R, Result, | |
656 | parallel::traits::static_partitioner_tag> | |
657 | {}; | |
658 | ||
659 | /////////////////////////////////////////////////////////////////////// | |
660 | template <typename ExPolicy, typename R, typename Result> | |
661 | struct partitioner<ExPolicy, R, Result, | |
662 | parallel::traits::default_partitioner_tag> | |
663 | : partitioner<ExPolicy, R, Result, | |
664 | parallel::traits::static_partitioner_tag> | |
665 | {}; | |
666 | } | |
667 | ||
668 | /////////////////////////////////////////////////////////////////////////// | |
669 | template <typename ExPolicy, typename R = void, typename Result = R, | |
670 | typename PartTag = typename parallel::traits::extract_partitioner< | |
671 | typename hpx::util::decay<ExPolicy>::type | |
672 | >::type> | |
673 | struct partitioner | |
674 | : detail::partitioner< | |
675 | typename hpx::util::decay<ExPolicy>::type, R, Result, PartTag> | |
676 | {}; | |
677 | }}} | |
678 | ||
679 | #endif | |
680 |
Copyright (c) 2006-2012 Rogue Wave Software, Inc. All Rights Reserved.
Patents pending.