16 template <
typename W,
typename Op,
typename ReleaseHandler,
17 typename ForwardIterator,
typename... ForwardIterators>
18 inline void parallel_loop_generic(
const execution::parallel_policy<W>& policy,
21 ForwardIterator first,
23 ForwardIterators... firsts) {
30 std::size_t d = std::distance(first, last);
31 if (d <= policy.cutoff_count) {
33 execution::internal::to_sequenced_policy(policy),
35 op(std::forward<decltype(refs)>(refs)...);
37 first, last, firsts...);
41 auto mid = std::next(first, d / 2);
46 auto&& [p1, p2] = execution::internal::get_child_policies(policy);
50 execution::internal::get_workhint(policy),
52 parallel_loop_generic(p1, op, rh, first, mid, firsts...);
55 parallel_loop_generic(p2, op, rh, mid, last, std::next(firsts, d / 2)...);
57 if (!th.serialized()) {
66 if (!th.serialized()) {
71 template <
typename Op,
typename ForwardIterator,
typename... ForwardIterators>
72 inline void loop_generic(
const execution::sequenced_policy& policy,
74 ForwardIterator first,
76 ForwardIterators... firsts) {
77 execution::internal::assert_policy(policy);
79 execution::internal::to_sequenced_policy(policy),
81 op(std::forward<decltype(refs)>(refs)...);
83 first, last, firsts...);
86 template <
typename W,
typename Op,
typename ForwardIterator,
typename... ForwardIterators>
87 inline void loop_generic(
const execution::parallel_policy<W>& policy,
89 ForwardIterator first,
91 ForwardIterators... firsts) {
92 execution::internal::assert_policy(policy);
94 parallel_loop_generic(policy, op, rh, first, last, firsts...);
135 template <
typename ExecutionPolicy,
typename ForwardIterator,
typename Op>
136 inline void for_each(
const ExecutionPolicy& policy,
137 ForwardIterator first,
138 ForwardIterator last,
140 internal::loop_generic(policy, op, first, last);
182 template <
typename ExecutionPolicy,
typename ForwardIterator1,
typename ForwardIterator2,
typename Op>
183 inline void for_each(
const ExecutionPolicy& policy,
184 ForwardIterator1 first1,
185 ForwardIterator1 last1,
186 ForwardIterator2 first2,
188 internal::loop_generic(policy, op, first1, last1, first2);
232 template <
typename ExecutionPolicy,
typename ForwardIterator1,
typename ForwardIterator2,
233 typename ForwardIterator3,
typename Op>
234 inline void for_each(
const ExecutionPolicy& policy,
235 ForwardIterator1 first1,
236 ForwardIterator1 last1,
237 ForwardIterator2 first2,
238 ForwardIterator3 first3,
240 internal::loop_generic(policy, op, first1, last1, first2, first3);
246 template <
typename ExecutionPolicy,
typename ForwardIterator1,
typename ForwardIterator2,
247 typename ForwardIterator3,
typename ForwardIterator4,
typename Op>
248 inline void for_each(
const ExecutionPolicy& policy,
249 ForwardIterator1 first1,
250 ForwardIterator1 last1,
251 ForwardIterator2 first2,
252 ForwardIterator3 first3,
253 ForwardIterator4 first4,
255 internal::loop_generic(policy, op, first1, last1, first2, first3, first4);
261 template <
typename ExecutionPolicy,
typename ForwardIterator1,
typename ForwardIterator2,
262 typename ForwardIterator3,
typename ForwardIterator4,
typename ForwardIterator5,
typename Op>
263 inline void for_each(
const ExecutionPolicy& policy,
264 ForwardIterator1 first1,
265 ForwardIterator1 last1,
266 ForwardIterator2 first2,
267 ForwardIterator3 first3,
268 ForwardIterator4 first4,
269 ForwardIterator5 first5,
271 internal::loop_generic(policy, op, first1, last1, first2, first3, first4, first5);
277 template <
typename ExecutionPolicy,
typename ForwardIterator1,
typename ForwardIterator2,
278 typename ForwardIterator3,
typename ForwardIterator4,
typename ForwardIterator5,
279 typename ForwardIterator6,
typename Op>
280 inline void for_each(
const ExecutionPolicy& policy,
281 ForwardIterator1 first1,
282 ForwardIterator1 last1,
283 ForwardIterator2 first2,
284 ForwardIterator3 first3,
285 ForwardIterator4 first4,
286 ForwardIterator5 first5,
287 ForwardIterator6 first6,
289 internal::loop_generic(policy, op, first1, last1, first2, first3, first4, first5, first6);
295 template <
typename ExecutionPolicy,
typename ForwardIterator1,
typename ForwardIterator2,
296 typename ForwardIterator3,
typename ForwardIterator4,
typename ForwardIterator5,
297 typename ForwardIterator6,
typename ForwardIterator7,
typename Op>
298 inline void for_each(
const ExecutionPolicy& policy,
299 ForwardIterator1 first1,
300 ForwardIterator1 last1,
301 ForwardIterator2 first2,
302 ForwardIterator3 first3,
303 ForwardIterator4 first4,
304 ForwardIterator5 first5,
305 ForwardIterator6 first6,
306 ForwardIterator6 first7,
308 internal::loop_generic(policy, op, first1, last1, first2, first3, first4, first5, first6, first7);
314 template <
typename ExecutionPolicy,
typename ForwardIterator1,
typename ForwardIterator2,
315 typename ForwardIterator3,
typename ForwardIterator4,
typename ForwardIterator5,
316 typename ForwardIterator6,
typename ForwardIterator7,
typename ForwardIterator8,
typename Op>
317 inline void for_each(
const ExecutionPolicy& policy,
318 ForwardIterator1 first1,
319 ForwardIterator1 last1,
320 ForwardIterator2 first2,
321 ForwardIterator3 first3,
322 ForwardIterator4 first4,
323 ForwardIterator5 first5,
324 ForwardIterator6 first6,
325 ForwardIterator6 first7,
326 ForwardIterator6 first8,
328 internal::loop_generic(policy, op, first1, last1, first2, first3, first4, first5, first6, first7, first8);
331 ITYR_TEST_CASE(
"[ityr::pattern::serial_loop] serial for_each") {
341 count_iterator<long>(0),
342 count_iterator<long>(n),
343 [&](
long i) { count += i; });
349 count_iterator<long>(0),
350 count_iterator<long>(n),
351 count_iterator<long>(n),
352 [&](
long i,
long j) { count += i + j; });
358 count_iterator<long>(0),
359 count_iterator<long>(n),
360 count_iterator<long>(n),
361 count_iterator<long>(2 * n),
362 [&](
long i,
long j,
long k) { count += i + j + k; });
367 std::vector<long> mos1(count_iterator<long>(0),
368 count_iterator<long>(n));
370 std::vector<long> mos2;
373 mos1.begin(), mos1.end(),
374 std::back_inserter(mos2),
375 [&](
long i,
auto&& out) { out = i; });
380 mos2.begin(), mos2.end(),
381 [&](
long i) { count += i; });
386 std::vector<common::move_only_t> mos1(count_iterator<long>(0),
387 count_iterator<long>(n));
389 std::vector<common::move_only_t> mos2;
394 std::back_inserter(mos2),
395 [&](common::move_only_t&& in,
auto&& out) { out = std::move(in); });
400 mos2.begin(), mos2.end(),
401 [&](common::move_only_t& mo) { count += mo.value(); });
406 mos1.begin(), mos1.end(),
407 [&](common::move_only_t& mo) { ITYR_CHECK(mo.value() == -1); });
412 ori::global_ptr<long> gp = ori::malloc<long>(n);
416 count_iterator<long>(0),
417 count_iterator<long>(n),
419 [&](
long i,
long& out) {
new (&out)
long(i); });
427 [&](ori::global_ref<long> gr) { count += gr; });
437 [&](
long i) { count += i; });
442 ori::global_ptr<common::move_only_t> mos1 = ori::malloc<common::move_only_t>(n);
443 ori::global_ptr<common::move_only_t> mos2 = ori::malloc<common::move_only_t>(n);
450 [&](
long i, common::move_only_t& out) {
new (&out) common::move_only_t(i); });
457 [&](common::move_only_t&& in, common::move_only_t& out) {
new (&out) common::move_only_t(
std::move(in)); });
464 [&](
const common::move_only_t& mo) { count += mo.value(); });
471 [&](
const common::move_only_t& mo) {
ITYR_CHECK(mo.value() == -1); });
483 ITYR_TEST_CASE(
"[ityr::pattern::parallel_loop] parallel for_each") {
488 ori::global_ptr<int> p1 = ori::malloc_coll<int>(n);
489 ori::global_ptr<int> p2 = ori::malloc_coll<int>(n);
494 execution::sequenced_policy(100),
497 [&](
int& v) { v = count++; });
503 count_iterator<int>(0),
508 count_iterator<int>(0),
509 count_iterator<int>(n),
518 [=](
int x,
int& y) { y = x * 2; });
524 [=](
int& y) { y *= 2; });
528 count_iterator<int>(0),
529 count_iterator<int>(n),
531 [=](
int i,
int y) {
ITYR_CHECK(y == i * 4); });
581 template <
typename ExecutionPolicy,
typename ForwardIterator1,
582 typename ForwardIteratorD,
typename UnaryOp>
583 inline ForwardIteratorD
transform(
const ExecutionPolicy& policy,
584 ForwardIterator1 first1,
585 ForwardIterator1 last1,
586 ForwardIteratorD first_d,
588 if constexpr (ori::is_global_ptr_v<ForwardIterator1> ||
589 ori::is_global_ptr_v<ForwardIteratorD>) {
590 using value_type_d =
typename std::iterator_traits<ForwardIteratorD>::value_type;
595 internal::convert_to_global_iterator(first_d, internal::dest_checkout_mode_t<value_type_d>{}),
599 auto op = [=](
const auto& r1,
auto&& d) {
603 internal::loop_generic(policy, op, first1, last1, first_d);
605 return std::next(first_d, std::distance(first1, last1));
653 template <
typename ExecutionPolicy,
typename ForwardIterator1,
typename ForwardIterator2,
654 typename ForwardIteratorD,
typename BinaryOp>
655 inline ForwardIteratorD
transform(
const ExecutionPolicy& policy,
656 ForwardIterator1 first1,
657 ForwardIterator1 last1,
658 ForwardIterator2 first2,
659 ForwardIteratorD first_d,
660 BinaryOp binary_op) {
661 if constexpr (ori::is_global_ptr_v<ForwardIterator1> ||
662 ori::is_global_ptr_v<ForwardIterator2> ||
663 ori::is_global_ptr_v<ForwardIteratorD>) {
664 using value_type_d =
typename std::iterator_traits<ForwardIteratorD>::value_type;
670 internal::convert_to_global_iterator(first_d, internal::dest_checkout_mode_t<value_type_d>{}),
674 auto op = [=](
const auto& r1,
const auto& r2,
auto&& d) {
675 d = binary_op(r1, r2);
678 internal::loop_generic(policy, op, first1, last1, first2, first_d);
680 return std::next(first_d, std::distance(first1, last1));
684 ITYR_TEST_CASE(
"[ityr::pattern::parallel_loop] transform") {
689 ori::global_ptr<long> p1 = ori::malloc_coll<long>(n);
690 ori::global_ptr<long> p2 = ori::malloc_coll<long>(n);
695 execution::parallel_policy(100),
696 count_iterator<long>(0), count_iterator<long>(n), p1,
697 [](
long i) {
return i * 2; });
701 execution::parallel_policy(100),
702 count_iterator<long>(0), count_iterator<long>(n), p1, p2,
703 [](
long i,
long j) {
return i * j; });
706 execution::parallel_policy(100),
709 count_iterator<long>(0),
710 [=](
long v,
long i) {
ITYR_CHECK(v == i * i * 2); });
717 execution::sequenced_policy(100),
718 count_iterator<long>(0), count_iterator<long>(n), p1,
719 [](
long i) {
return i * 2; });
723 execution::sequenced_policy(100),
724 count_iterator<long>(0), count_iterator<long>(n), p1, p2,
725 [](
long i,
long j) {
return i * j; });
728 execution::sequenced_policy(100),
731 count_iterator<long>(0),
732 [=](
long v,
long i) {
ITYR_CHECK(v == i * i * 2); });
770 template <
typename ExecutionPolicy,
typename ForwardIterator,
typename T>
771 inline void fill(
const ExecutionPolicy& policy,
772 ForwardIterator first,
773 ForwardIterator last,
775 if constexpr (ori::is_global_ptr_v<ForwardIterator>) {
776 using value_type =
typename std::iterator_traits<ForwardIterator>::value_type;
779 internal::convert_to_global_iterator(first, internal::dest_checkout_mode_t<value_type>{}),
780 internal::convert_to_global_iterator(last , internal::dest_checkout_mode_t<value_type>{}),
784 auto op = [=](
auto&& d) {
788 internal::loop_generic(policy, op, first, last);
792 ITYR_TEST_CASE(
"[ityr::pattern::parallel_loop] fill") {
797 ori::global_ptr<long> p = ori::malloc_coll<long>(n);
801 fill(execution::parallel_policy(100), p, p + n, val);
804 execution::parallel_policy(100),
855 template <
typename ExecutionPolicy,
typename ForwardIterator1,
typename ForwardIteratorD>
856 inline ForwardIteratorD
copy(
const ExecutionPolicy& policy,
857 ForwardIterator1 first1,
858 ForwardIterator1 last1,
859 ForwardIteratorD first_d) {
860 if constexpr (ori::is_global_ptr_v<ForwardIterator1> ||
861 ori::is_global_ptr_v<ForwardIteratorD>) {
862 using value_type1 =
typename std::iterator_traits<ForwardIterator1>::value_type;
863 using value_type_d =
typename std::iterator_traits<ForwardIteratorD>::value_type;
866 internal::convert_to_global_iterator(first1 , internal::src_checkout_mode_t<value_type1>{}),
867 internal::convert_to_global_iterator(last1 , internal::src_checkout_mode_t<value_type1>{}),
868 internal::convert_to_global_iterator(first_d, internal::dest_checkout_mode_t<value_type_d>{}));
871 auto op = [=](
auto&& r1,
auto&& d) {
872 d = std::forward<decltype(r1)>(r1);
875 internal::loop_generic(policy, op, first1, last1, first_d);
877 return std::next(first_d, std::distance(first1, last1));
881 ITYR_TEST_CASE(
"[ityr::pattern::parallel_loop] copy") {
886 ori::global_ptr<long> p1 = ori::malloc_coll<long>(n);
887 ori::global_ptr<long> p2 = ori::malloc_coll<long>(n);
891 execution::parallel_policy(100),
894 count_iterator<long>(0),
895 [=](
long& v,
long i) { v = i * 2; });
897 copy(execution::parallel_policy(100), p1, p1 + n, p2);
900 execution::parallel_policy(100),
903 count_iterator<long>(0),
904 [=](
long v,
long i) {
ITYR_CHECK(v == i * 2); });
933 template <
typename ExecutionPolicy,
typename ForwardIterator1,
typename ForwardIteratorD>
934 inline ForwardIteratorD
move(
const ExecutionPolicy& policy,
935 ForwardIterator1 first1,
936 ForwardIterator1 last1,
937 ForwardIteratorD first_d) {
938 if constexpr (ori::is_global_ptr_v<ForwardIterator1> ||
939 ori::is_global_ptr_v<ForwardIteratorD>) {
940 using value_type1 =
typename std::iterator_traits<ForwardIterator1>::value_type;
941 using value_type_d =
typename std::iterator_traits<ForwardIteratorD>::value_type;
944 internal::convert_to_global_iterator(first1 , internal::src_checkout_mode_t<value_type1>{}),
945 internal::convert_to_global_iterator(last1 , internal::src_checkout_mode_t<value_type1>{}),
946 internal::convert_to_global_iterator(first_d, internal::dest_checkout_mode_t<value_type_d>{}));
954 ITYR_TEST_CASE(
"[ityr::pattern::parallel_loop] move") {
959 ori::global_ptr<common::move_only_t> p1 = ori::malloc_coll<common::move_only_t>(n);
960 ori::global_ptr<common::move_only_t> p2 = ori::malloc_coll<common::move_only_t>(n);
964 execution::parallel_policy(100),
967 count_iterator<long>(0),
968 [=](common::move_only_t& r,
long i) {
new (&r) common::move_only_t(i * 2); });
970 move(execution::parallel_policy(100), p1, p1 + n, p2);
973 execution::parallel_policy(100),
976 count_iterator<long>(0),
977 [=](
const common::move_only_t& r,
long i) {
ITYR_CHECK(r.value() == i * 2); });
1013 template <
typename ExecutionPolicy,
typename B
idirectionalIterator>
1014 inline void reverse(
const ExecutionPolicy& policy,
1015 BidirectionalIterator first,
1016 BidirectionalIterator last) {
1017 if constexpr (ori::is_global_ptr_v<BidirectionalIterator>) {
1024 auto op = [=](
auto&& r1,
auto&& r2) {
1030 auto d = std::distance(first, last);
1055 template <
typename ExecutionPolicy,
typename B
idirectionalIterator1,
typename B
idirectionalIteratorD>
1057 BidirectionalIterator1 first1,
1058 BidirectionalIterator1 last1,
1059 BidirectionalIteratorD first_d) {
1064 ITYR_TEST_CASE(
"[ityr::pattern::parallel_loop] reverse") {
1069 ori::global_ptr<long> p1 = ori::malloc_coll<long>(n);
1070 ori::global_ptr<long> p2 = ori::malloc_coll<long>(n);
1074 execution::parallel_policy(100),
1077 count_iterator<long>(0),
1078 [=](
long& v,
long i) { v = i; });
1080 reverse(execution::parallel_policy(100), p1, p1 + n);
1082 reverse_copy(execution::parallel_policy(100), p1, p1 + n, p2);
1085 execution::parallel_policy(100),
1089 count_iterator<long>(0),
1090 [=](
long v1,
long v2,
long i) {
1134 template <
typename ExecutionPolicy,
typename B
idirectionalIterator>
1135 inline BidirectionalIterator
rotate(
const ExecutionPolicy& policy,
1136 BidirectionalIterator first,
1137 BidirectionalIterator middle,
1138 BidirectionalIterator last) {
1140 if (first == middle)
return last;
1141 if (middle == last)
return first;
1144 [=] {
reverse(policy, first, middle); },
1145 [=] {
reverse(policy, middle, last); });
1148 return std::next(first, std::distance(middle, last));
1187 template <
typename ExecutionPolicy,
typename ForwardIterator1,
typename ForwardIteratorD>
1189 ForwardIterator1 first1,
1190 ForwardIterator1 middle1,
1191 ForwardIterator1 last1,
1192 ForwardIteratorD first_d) {
1194 [=] {
copy(policy, middle1, last1, first_d); },
1195 [=] {
auto middle_d = std::next(first_d, std::distance(middle1, last1));
1196 return copy(policy, first1, middle1, middle_d); });
1200 ITYR_TEST_CASE(
"[ityr::pattern::parallel_loop] rotate") {
1205 ori::global_ptr<long> p1 = ori::malloc_coll<long>(n);
1206 ori::global_ptr<long> p2 = ori::malloc_coll<long>(n);
1210 execution::parallel_policy(100),
1213 count_iterator<long>(0),
1214 [=](
long& v,
long i) { v = i; });
1217 rotate(execution::parallel_policy(100), p1, p1 + shift, p1 + n);
1220 execution::parallel_policy(100),
1221 p1, p1 + (n - shift), p1 + n, p2);
1224 execution::parallel_policy(100),
1228 count_iterator<long>(0),
1229 [=](
long v1,
long v2,
long i) {
#define ITYR_SUBCASE(name)
Definition: util.hpp:41
#define ITYR_CHECK(cond)
Definition: util.hpp:48
constexpr read_write_t read_write
Read+Write checkout mode.
Definition: checkout_span.hpp:39
constexpr read_t read
Read-only checkout mode.
Definition: checkout_span.hpp:19
constexpr write_t write
Write-only checkout mode.
Definition: checkout_span.hpp:29
constexpr parallel_policy par
Default parallel execution policy for iterator-based loop functions.
Definition: execution.hpp:89
constexpr sequenced_policy seq
Default serial execution policy for iterator-based loop functions.
Definition: execution.hpp:83
void fini()
Definition: ito.hpp:45
auto root_exec(Fn &&fn, Args &&... args)
Definition: ito.hpp:50
void task_group_begin(task_group_data *tgdata)
Definition: ito.hpp:105
void init(MPI_Comm comm=MPI_COMM_WORLD)
Definition: ito.hpp:41
void poll(PreSuspendCallback &&pre_suspend_cb, PostSuspendCallback &&post_suspend_cb)
Definition: ito.hpp:96
constexpr with_callback_t with_callback
Definition: thread.hpp:11
void task_group_end(PreSuspendCallback &&pre_suspend_cb, PostSuspendCallback &&post_suspend_cb)
Definition: ito.hpp:112
scheduler::task_group_data task_group_data
Definition: ito.hpp:103
void fini()
Definition: ori.hpp:49
void init(MPI_Comm comm=MPI_COMM_WORLD)
Definition: ori.hpp:45
void free(global_ptr< T > ptr, std::size_t count)
Definition: ori.hpp:75
auto release_lazy()
Definition: ori.hpp:200
void free_coll(global_ptr< T > ptr)
Definition: ori.hpp:70
core::instance::instance_type::release_handler release_handler
Definition: ori.hpp:204
void poll()
Definition: ori.hpp:224
void release()
Definition: ori.hpp:196
void acquire()
Definition: ori.hpp:206
Definition: allocator.hpp:16
global_reverse_iterator< global_iterator< T, Mode > > make_reverse_iterator(ori::global_ptr< T > gptr, Mode mode)
Make a reverse iterator for global memory.
Definition: global_iterator.hpp:333
BidirectionalIterator rotate(const ExecutionPolicy &policy, BidirectionalIterator first, BidirectionalIterator middle, BidirectionalIterator last)
Rotate a range.
Definition: parallel_loop.hpp:1135
BidirectionalIteratorD reverse_copy(const ExecutionPolicy &policy, BidirectionalIterator1 first1, BidirectionalIterator1 last1, BidirectionalIteratorD first_d)
Copy a reversed range to another.
Definition: parallel_loop.hpp:1056
ForwardIteratorD copy(const ExecutionPolicy &policy, ForwardIterator1 first1, ForwardIterator1 last1, ForwardIteratorD first_d)
Copy a range to another.
Definition: parallel_loop.hpp:856
auto parallel_invoke(Args &&... args)
Fork parallel tasks and join them.
Definition: parallel_invoke.hpp:238
ForwardIteratorD transform(const ExecutionPolicy &policy, ForwardIterator1 first1, ForwardIterator1 last1, ForwardIteratorD first_d, UnaryOp unary_op)
Transform elements in a given range and store them in another range.
Definition: parallel_loop.hpp:583
ForwardIteratorD rotate_copy(const ExecutionPolicy &policy, ForwardIterator1 first1, ForwardIterator1 middle1, ForwardIterator1 last1, ForwardIteratorD first_d)
Copy a rotated range to another.
Definition: parallel_loop.hpp:1188
void for_each(const ExecutionPolicy &policy, ForwardIterator first, ForwardIterator last, Op op)
Apply an operator to each element in a range.
Definition: parallel_loop.hpp:136
void fill(const ExecutionPolicy &policy, ForwardIterator first, ForwardIterator last, const T &value)
Fill a range with a given value.
Definition: parallel_loop.hpp:771
void swap(global_vector< T > &v1, global_vector< T > &v2) noexcept
Definition: global_vector.hpp:664
void reverse(const ExecutionPolicy &policy, BidirectionalIterator first, BidirectionalIterator last)
Reverse a range.
Definition: parallel_loop.hpp:1014
global_iterator< T, Mode > make_global_iterator(ori::global_ptr< T > gptr, Mode)
Make a global iterator to enable/disable automatic checkout.
Definition: global_iterator.hpp:158
global_move_iterator< global_iterator< T, internal::src_checkout_mode_t< T > > > make_move_iterator(ori::global_ptr< T > gptr)
Make a global iterator for moving objects.
Definition: global_iterator.hpp:258
ForwardIteratorD move(const ExecutionPolicy &policy, ForwardIterator1 first1, ForwardIterator1 last1, ForwardIteratorD first_d)
Move a range to another.
Definition: parallel_loop.hpp:934