kokkos-execution 0.0.1
Loading...
Searching...
No Matches
test_completion_signal.cpp
Go to the documentation of this file.
3
5
10
22
23namespace Tests::Impl {
24
25using namespace Kokkos::utils::callbacks;
26
28 : public Tests::Utils::ExecutionSpaceContextTest<TEST_EXECUTION_SPACE>
30 public:
33 Kokkos::RangePolicy<TEST_EXECUTION_SPACE>,
35 >;
36
42 >;
43
44 public:
46 : data(Kokkos::view_alloc(exec, "data - shared space"))
47 , esc{exec}
48 , pfor_data{
49 {"hello from pfor"},
51 Kokkos::RangePolicy<TEST_EXECUTION_SPACE>(0, size)} {
52 }
53
54 protected:
55 static constexpr size_t size = 10;
59};
60
63 using completion_signal_inline_fence_exec_t = Kokkos::Execution::Impl::CompletionSignal<
65 TEST_EXECUTION_SPACE,
67 >;
68
69 static_assert(sizeof(completion_signal_inline_fence_exec_t) == sizeof(Tests::Utils::SinkReceiver));
70
71 using completion_signal_schedule_wait_event_t = Kokkos::Execution::Impl::CompletionSignal<
73 TEST_EXECUTION_SPACE,
75 >;
76
77 static_assert(
78 sizeof(completion_signal_schedule_wait_event_t)
81
82 using completion_signal_order_on_exec_t = Kokkos::Execution::Impl::CompletionSignal<
84 TEST_EXECUTION_SPACE,
86 >;
87
88 static_assert(
89 sizeof(completion_signal_order_on_exec_t)
91
92 using completion_signal_depend_on_event_t = Kokkos::Execution::Impl::CompletionSignal<
94 TEST_EXECUTION_SPACE,
96 >;
97
99 static_assert(
100 sizeof(completion_signal_depend_on_event_t)
102
103 return true;
104}
105
106static_assert(test_completion_signal_traits());
107
109TEST_F(CompletionSignalTest, inline_fence_exec_policy) {
110 auto op_state = stdexec::connect(
111 stdexec::schedule(esc.get_scheduler())
114 pfor_data.policy_or_iter_space,
115 pfor_data.functor),
117
118 static_assert(std::same_as<
119 typename decltype(op_state)::completion_signal_policy_t,
121 >);
122 static_assert(!Kokkos::Execution::Impl::signals_submitted<decltype(op_state)>);
123
124 ASSERT_THAT(
125 recorder_listener_t::record([&]() { op_state.start(); }),
126 testing::ElementsAre(MATCHER_FOR_BEGIN_FENCE(exec, dispatch_label(exec, "after dispatch"))));
127
128 ASSERT_EQ(data(), size / 2 * (size - 1));
129}
130
131template <Kokkos::ExecutionSpace Exec, bool SubmittedOrderOn, bool SubmittedDependOn>
132struct Receiver {
133 using receiver_concept = std::conditional_t<
134 SubmittedOrderOn || SubmittedDependOn,
136 stdexec::receiver_tag
137 >;
138
140 stdexec::run_loop* loop;
141
142 void set_value() && noexcept {
143 loop->finish();
144 }
145
146 template <typename Error>
147 void set_error(Error&&) && noexcept {
148 loop->finish();
149 }
150
151 void submitted() && noexcept requires(SubmittedOrderOn)
152 {
153 loop->finish();
154 }
155
156 void submitted(Kokkos::Execution::Impl::OptionalConstEventRef<Exec> dep) && noexcept requires(SubmittedDependOn)
157 {
158 if (dep.has_value()) {
160 }
161 loop->finish();
162 }
163
164 [[nodiscard]]
165 constexpr auto get_env() const noexcept {
167 stdexec::prop{stdexec::get_delegation_scheduler, loop->get_scheduler()}, state->exec);
168 }
169};
170
172TEST_F(CompletionSignalTest, schedule_wait_event_policy) {
174 GTEST_SKIP() << "The execution space does not have non-blocking dispatch.";
175 }
176
177 const auto [exec_A, exec_B] = Kokkos::Experimental::partition_space(exec, 1, 1);
178 const context_t esc_A{exec_A}, esc_B{exec_B};
179
180 stdexec::run_loop loop;
181
182 auto op_state = stdexec::connect(
183 stdexec::schedule(esc_A.get_scheduler())
186 pfor_data.policy_or_iter_space,
187 pfor_data.functor),
188 Receiver<TEST_EXECUTION_SPACE, false, false>{&esc_B.m_state, &loop});
189
190 const auto recorded_events_before_run = recorder_listener_t::record([&]() { op_state.start(); });
191
192 ASSERT_THAT(recorded_events_before_run, testing::ElementsAre(MATCHER_FOR_RECORD_EVENT(exec_A)));
193
194 const auto recorded_events_after_run = recorder_listener_t::record([&]() { loop.run(); });
195
196 ASSERT_THAT(
197 recorded_events_after_run, testing::ElementsAre(MATCHER_FOR_WAIT_EVENT(recorded_events_before_run.at(0))));
198
199 ASSERT_EQ(data(), size / 2 * (size - 1));
200}
201
203TEST_F(CompletionSignalTest, order_on_exec_policy) {
205 std::optional<std::tuple<>> result;
206
207 auto op_state = stdexec::connect(
208 stdexec::schedule(esc.get_scheduler())
211 pfor_data.policy_or_iter_space,
212 pfor_data.functor),
214 .state = std::addressof(esc.m_state),
215 .runloop_state = std::addressof(runloop_state),
216 .result = std::addressof(result)});
217
218 static_assert(std::same_as<
219 typename decltype(op_state)::completion_signal_policy_t,
221 >);
222 static_assert(Kokkos::Execution::Impl::signals_submitted<decltype(op_state)>);
223
224 ASSERT_THAT(
225 recorder_listener_t::record([&]() { op_state.start(); }),
226 testing::ElementsAre(MATCHER_FOR_BEGIN_FENCE(exec, dispatch_label(exec, "sync_wait"))));
227
228 ASSERT_EQ(data(), size / 2 * (size - 1));
229
230 runloop_state.loop.run();
231}
232
234TEST_F(CompletionSignalTest, depend_on_event_policy) {
235 const auto [exec_A, exec_B] = Kokkos::Experimental::partition_space(exec, 1, 1);
236 const context_t esc_A{exec_A}, esc_B{exec_B};
237
238 stdexec::run_loop loop;
239
240 auto op_state = stdexec::connect(
241 stdexec::schedule(esc_A.get_scheduler())
244 pfor_data.policy_or_iter_space,
245 pfor_data.functor),
246 Receiver<TEST_EXECUTION_SPACE, false, true>{&esc_B.m_state, &loop});
247
249 static_assert(std::same_as<
250 typename decltype(op_state)::completion_signal_policy_t,
252 >);
253 static_assert(Kokkos::Execution::Impl::signals_submitted<decltype(op_state)>);
254
255 const auto recorded_events = recorder_listener_t::record([&]() { op_state.start(); });
256
257 if (Tests::Utils::are_same_instances(exec_A, exec_B)) {
258 ASSERT_THAT(recorded_events, testing::IsEmpty());
259 } else {
260 ASSERT_THAT(
261 recorded_events,
262 testing::ElementsAre(MATCHER_FOR_RECORD_EVENT(exec_A), MATCHER_FOR_WAIT_EVENT(recorded_events.at(0))));
263 }
264
265 ASSERT_EQ(data(), size / 2 * (size - 1));
266
267 loop.run();
268}
269
270} // namespace Tests::Impl
constexpr std::string dispatch_label(const Exec &, const std::string_view label)
Get the dispatch label from Exec and label.
#define MATCHER_FOR_WAIT_EVENT(_record_event_variant_)
#define MATCHER_FOR_RECORD_EVENT(_exec_)
#define MATCHER_FOR_BEGIN_FENCE(_exec_, _label_)
Kokkos::Execution::Impl::ParallelForData< Tests::Utils::Functors::SumIndices< view_s_t >, Kokkos::RangePolicy< TEST_EXECUTION_SPACE >, Kokkos::Execution::Impl::Label< std::string > > parallel_for_data_t
RecorderListener< EventDiscardMatcher< TEST_EXECUTION_SPACE >, BeginFenceEvent, Kokkos::Execution::Impl::RecordEvent, Kokkos::Execution::Impl::WaitEvent > recorder_listener_t
constexpr auto join_env_with_exec(Env &&env, const Exec &exec) noexcept
Unconditionally join exec to env.
Definition env.hpp:16
OptionalRef< const Event< Exec > > OptionalConstEventRef
Optionally stores a reference to a const Impl::Event.
Definition event.hpp:183
std::optional< Event< Exec > > event_storage_t
Definition event.hpp:179
void wait(const Event< Exec > &... events)
Wait for events to complete.
Definition event.hpp:157
constexpr decltype(auto) get_property(Data &&data) noexcept
constexpr parallel_for_t parallel_for
consteval bool test_completion_signal_traits()
bool are_same_instances(const Exec &exec, const OtherExec &other_exec)
Definition kokkos.hpp:18
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
Receiver for stdexec::sync_wait.
Definition sync_wait.hpp:45
Inspired by https://github.com/NVIDIA/stdexec/blob/16076a81efa4477513e6ede9c2741fd034ecef99/include/s...
Definition sync_wait.hpp:30
Event to be sent to Kokkos::utils::callbacks::dispatch when calling wait.
Definition event.hpp:80
void submitted(Kokkos::Execution::Impl::OptionalConstEventRef< Exec > dep) &&noexcept
void set_error(Error &&) &&noexcept
std::conditional_t< SubmittedOrderOn||SubmittedDependOn, Kokkos::Execution::Impl::SubmittedReceiverTag, stdexec::receiver_tag > receiver_concept
constexpr auto get_env() const noexcept
Kokkos::Execution::Impl::State< Exec > const * state
Kokkos::Execution::ExecutionSpaceContext< Exec > context_t
Definition context.hpp:33
A receiver that can handle all completions and does nothing with them.