kokkos-execution 0.0.1
Loading...
Searching...
No Matches
test_fork_join.cpp
Go to the documentation of this file.
2PRAGMA_DIAGNOSTIC_PUSH
4#include "exec/fork_join.hpp"
5#include "exec/static_thread_pool.hpp"
6PRAGMA_DIAGNOSTIC_POP
7
10
12
20
32
34
35using namespace Kokkos::utils::callbacks;
36
50
52TEST_F(ForkJoinTest, diamond) {
53 const view_s_t data(Kokkos::view_alloc("data - shared space"));
54
55 experimental::execution::static_thread_pool pool{4};
56 const context_t esc{exec};
57
58 auto sndr =
59 stdexec::schedule(pool.get_scheduler())
60 | stdexec::then(Tests::Utils::Functors::LoadCheckAdd<int, false>{.prev = 0, .value = 4, .data = data.data()})
61 | experimental::execution::fork_join(
62 stdexec::continues_on(esc.get_scheduler())
64 | THEN_INCREMENT_ATOMIC(System, data) | stdexec::continues_on(pool.get_scheduler()),
65 stdexec::continues_on(pool.get_scheduler()) | THEN_INCREMENT_ATOMIC(System, data))
66 | stdexec::continues_on(esc.get_scheduler())
67 | stdexec::then(
68 Tests::Utils::Functors::LoadCheckAdd<int, on_device>{.prev = 6, .value = 3, .data = data.data()})
69 | stdexec::continues_on(pool.get_scheduler())
70 | stdexec::then(Tests::Utils::Functors::LoadCheckAdd<int, false>{.prev = 9, .value = 5, .data = data.data()});
71
72 ASSERT_EQ(data(), 0) << "Eager execution is not allowed.";
73
75
76 ASSERT_THAT(
78 testing::ElementsAre(
82 MATCHER_FOR_BEGIN_FENCE(exec, dispatch_label(exec, "schedule_from"))));
83
84 ASSERT_EQ(data(), 14);
85}
86
92TEST_F(ForkJoinTest, continues_on) {
93 const view_s_t data(Kokkos::view_alloc(exec, "data - shared space"));
94
95 const context_t esc{exec};
96
97 auto sndr = stdexec::just() | stdexec::continues_on(esc.get_scheduler())
98 | experimental::execution::fork_join(
99 stdexec::continues_on(esc.get_scheduler()) | THEN_INCREMENT_ATOMIC(Device, data),
100 stdexec::continues_on(esc.get_scheduler()) | THEN_INCREMENT_ATOMIC(Device, data));
101
102 static_assert(stdexec::__sender_for<decltype(sndr), experimental::execution::fork_join_t>);
103
104 ASSERT_EQ(data(), 0) << "Eager execution is not allowed.";
105
106 const auto recorded_events = Tests::Utils::record_sync_wait<recorder_listener_t>(
107 std::move(sndr)); // NOLINT(performance-move-const-arg)
108
109 ASSERT_THAT(recorded_events, [&]() {
111 return testing::ElementsAre(
116 MATCHER_FOR_WAIT_EVENT(recorded_events.at(1)),
117 MATCHER_FOR_WAIT_EVENT(recorded_events.at(3)));
118 } else {
119 return testing::ElementsAre(
121 MATCHER_FOR_BEGIN_FENCE(exec, dispatch_label(exec, "after dispatch")),
123 MATCHER_FOR_BEGIN_FENCE(exec, dispatch_label(exec, "after dispatch")));
124 }
125 }());
126
127 ASSERT_EQ(data(), 2);
128}
129
135TEST_F(ForkJoinTest, continues_on_bulk) {
136 const view_s_t data(Kokkos::view_alloc(exec, "data - shared space"));
137
138 const context_t esc{exec};
139
140 auto sndr = stdexec::just() | stdexec::continues_on(esc.get_scheduler()) | BULK_SUM_INDICES(2, data)
141 | experimental::execution::fork_join(
142 stdexec::continues_on(esc.get_scheduler()) | THEN_INCREMENT_ATOMIC(Device, data),
143 stdexec::continues_on(esc.get_scheduler()) | THEN_INCREMENT_ATOMIC(Device, data));
144
145 static_assert(stdexec::__sender_for<decltype(sndr), experimental::execution::fork_join_t>);
146
147 ASSERT_EQ(data(), 0) << "Eager execution is not allowed.";
148
149 const auto recorded_events = Tests::Utils::record_sync_wait<recorder_listener_t>(std::move(sndr));
150
151 ASSERT_THAT(recorded_events, [&]() {
153 return testing::ElementsAre(
156 MATCHER_FOR_WAIT_EVENT(recorded_events.at(1)),
161 MATCHER_FOR_WAIT_EVENT(recorded_events.at(4)),
162 MATCHER_FOR_WAIT_EVENT(recorded_events.at(6)));
163 } else {
164 return testing::ElementsAre(
166 MATCHER_FOR_BEGIN_FENCE(exec, dispatch_label(exec, "after dispatch")),
168 MATCHER_FOR_BEGIN_FENCE(exec, dispatch_label(exec, "after dispatch")),
170 MATCHER_FOR_BEGIN_FENCE(exec, dispatch_label(exec, "after dispatch")));
171 }
172 }());
173
174 ASSERT_EQ(data(), 3);
175}
176
177} // namespace Tests::ExecutionSpaceImpl
constexpr std::string dispatch_label(const Exec &, const std::string_view label)
Get the dispatch label from Exec and label.
#define MATCHER_FOR_BEGIN_SINGLE(_exec_, _label_)
#define MATCHER_FOR_WAIT_EVENT(_record_event_variant_)
#define MATCHER_FOR_BEGIN_PFOR(_exec_, _label_)
#define MATCHER_FOR_RECORD_EVENT(_exec_)
#define MATCHER_FOR_BEGIN_FENCE(_exec_, _label_)
RecorderListener< EventDiscardMatcher< TEST_EXECUTION_SPACE >, BeginFenceEvent, BeginParallelForEvent, BeginSingleEvent, Kokkos::Execution::Impl::RecordEvent, Kokkos::Execution::Impl::WaitEvent > recorder_listener_t
#define KOKKOS_EXECUTION_THREADS_THROWS_ON_SYNC_WAIT_ASSERT_AND_SKIP(_sndr_)
Definition context.hpp:76
#define KOKKOS_EXECUTION_STDEXEC_PRAGMA_DIAGNOSTIC_IGNORED
Basic list of ignored diagnostics when including anything from stdexec.
#define THEN_INCREMENT_ATOMIC(_scope_, _data_)
Same as THEN_INCREMENT, using Tests::Utils::atomic_fetch_add. // NOLINTNEXTLINE(cppcoreguidelines-mac...
Definition increment.hpp:68
auto record_sync_wait(Sndr &&sndr)
Definition sync_wait.hpp:14
constexpr check_completion_scheduler_type_t< Tag, Schd > check_completion_scheduler_type
Matcher to filter out events that are just noise for tests.
auto get_scheduler() const noexcept -> ExecutionSpaceImpl::Scheduler< execution_space >
Event to be sent to Kokkos::utils::callbacks::dispatch when calling record.
Definition event.hpp:59
Event to be sent to Kokkos::utils::callbacks::dispatch when calling wait.
Definition event.hpp:80
Kokkos::Execution::ExecutionSpaceContext< Exec > context_t
Definition context.hpp:33
Load the value at data and check it is equal to prev. Then, add value to it.
#define BULK_SUM_INDICES(_size_, _data_)
Add a bulk using Tests::Utils::Functors::SumIndices. // NOLINTNEXTLINE(cppcoreguidelines-macro-usage)...