kokkos-execution 0.0.1
Loading...
Searching...
No Matches
test_then.cpp
Go to the documentation of this file.
4
7
23
35
36namespace Tests::GraphImpl {
37
38using namespace Kokkos::utils::callbacks;
39
58
60consteval bool test_sndr_traits() {
62 using schd_sndr_t = typename ThenTest::schedule_sender_t;
63
66 using then_sndr_t = stdexec::transform_sender_result_t<
67 decltype(stdexec::then(std::declval<schd_sndr_t>(), std::declval<functor_t>())),
68 stdexec::env<>
69 >;
70
73 static_assert(std::same_as<Kokkos::Execution::Impl::exec_of_t<then_sndr_t>, TEST_EXECUTION_SPACE>);
74
77
78 return true;
79}
80
81static_assert(test_sndr_traits());
82
85 typename ThenTest::scheduler_t,
86 stdexec::then_t,
88>());
89
91consteval bool test_sndr_nothrow_transformable() {
92 using sndr_then_t =
93 decltype(stdexec::schedule(std::declval<typename ThenTest::scheduler_t>()) | stdexec::then(Tests::Utils::Functors::NoOp<false, false, false>{}));
94
95 static_assert(std::same_as<
96 sndr_then_t,
97 stdexec::then_t::__sender<
100 >
101 >);
102
103 static_assert(stdexec::__detail::__has_nothrow_transform_sender<
105 stdexec::set_value_t,
106 sndr_then_t&&,
107 stdexec::env<>
108 >);
109
110 using sndr_then_maythrow_on_move_t =
111 decltype(stdexec::schedule(std::declval<typename ThenTest::scheduler_t>()) | stdexec::then(Tests::Utils::Functors::NoOp<false, false, true>{}));
112
113 static_assert(!stdexec::__detail::__has_nothrow_transform_sender<
114 Kokkos::Execution::GraphImpl::Domain,
115 stdexec::set_value_t,
116 sndr_then_maythrow_on_move_t&&,
117 stdexec::env<>
118 >);
119
120 return true;
121}
122
123static_assert(test_sndr_nothrow_transformable());
124
126consteval bool test_sndr_nothrow_connectable() {
128 static_assert(!std::is_nothrow_constructible_v<Kokkos::Experimental::Graph<TEST_EXECUTION_SPACE>>);
129
130 using sndr_then_t =
131 decltype(stdexec::schedule(std::declval<typename ThenTest::scheduler_t>()) | stdexec::then(Tests::Utils::Functors::NoOp<false, false, false>{}));
132
133 static_assert(!stdexec::__nothrow_connectable<sndr_then_t, Tests::Utils::SinkReceiver>);
134
135 return true;
136}
137
138static_assert(test_sndr_nothrow_connectable());
139
143
144 using sndr_t =
145 decltype(stdexec::schedule(std::declval<typename ThenTest::scheduler_t>()) | stdexec::then(functor_t{}) | stdexec::then(functor_t{}));
146 using connect_result_t = stdexec::connect_result_t<sndr_t, Tests::Utils::SinkReceiver>;
147
148 static_assert(stdexec::__is_instance_of<connect_result_t, Kokkos::Execution::GraphImpl::OpState>);
149
150 using root_t = typename ThenTest::graph_t::root_t;
151 using then_A_t = Kokkos::Experimental::GraphNodeRef<
152 TEST_EXECUTION_SPACE,
153 Kokkos::Impl::GraphNodeThenImpl<TEST_EXECUTION_SPACE, Kokkos::Experimental::ThenPolicy<>, functor_t>,
154 root_t
155 >;
156 using then_B_t = Kokkos::Experimental::GraphNodeRef<
157 TEST_EXECUTION_SPACE,
158 Kokkos::Impl::GraphNodeThenImpl<TEST_EXECUTION_SPACE, Kokkos::Experimental::ThenPolicy<>, functor_t>,
159 then_A_t
160 >;
161
162 static_assert(std::same_as<typename connect_result_t::predecessor_t, root_t>);
163 static_assert(std::same_as<typename connect_result_t::node_t, then_B_t>);
164
165 return true;
166}
167
168static_assert(test_then_op_state_traits());
169
174TEST_F(ThenTest, then_schedule) {
175 const view_s_t data(Kokkos::view_alloc(exec, "data - shared space"));
176
177 const context_t gctx{exec};
178
180
181 auto sndr = stdexec::schedule(gctx.get_scheduler())
182 | stdexec::then(functor_t{.prev = 0, .value = 4, .data = data.data()})
183 | stdexec::then(functor_t{.prev = 4, .value = 3, .data = data.data()});
184
185 using sndr_t = decltype(sndr);
186
187 static_assert(std::same_as<
188 stdexec::transform_sender_result_t<sndr_t, stdexec::env<>>,
190 TEST_EXECUTION_SPACE,
191 stdexec::then_t::__sender<functor_t, typename ThenTest::schedule_sender_t>,
192 functor_t
193 >
194 >);
195
197 static_assert(std::same_as<stdexec::__domain_of_t<stdexec::env_of_t<sndr_t>>, stdexec::default_domain>);
198 static_assert(std::same_as<
199 stdexec::__detail::__completing_domain_t<stdexec::set_value_t, sndr_t>,
201 >);
202
204 static_assert(std::same_as<
206 typename ThenTest::scheduler_t
207 >);
208
209 ASSERT_EQ(data(), 0) << "Eager execution is not allowed.";
210
211 const auto recorded_events = Tests::Utils::record_sync_wait<recorder_listener_t>(
212 std::move(sndr)); // NOLINT(performance-move-const-arg)
213
214 ASSERT_THAT(
215 recorded_events,
216 testing::ElementsAre(
219 recorded_events.at(0), device_handle, MATCHER_FOR_GRAPH_ROOT_NODE_OF(recorded_events.at(0))),
221 recorded_events.at(0), device_handle, MATCHER_FOR_GRAPH_NODE_OF(recorded_events.at(1))),
222 MATCHER_FOR_GRAPH_SUBMIT(exec, recorded_events.at(0)),
224
225 ASSERT_EQ(data(), 7);
226}
227
229TEST_F(ThenTest, then_schedule_node_type) {
231
232 using expt_node_t = Kokkos::Experimental::GraphNodeRef<
233 TEST_EXECUTION_SPACE,
234 Kokkos::Impl::GraphNodeThenImpl<TEST_EXECUTION_SPACE, Kokkos::Experimental::ThenPolicy<>, functor_t>,
235 Kokkos::Experimental::GraphNodeRef<
236 TEST_EXECUTION_SPACE,
237 Kokkos::Impl::GraphNodeThenImpl<TEST_EXECUTION_SPACE, Kokkos::Experimental::ThenPolicy<>, functor_t>,
238 Kokkos::Experimental::GraphNodeRef<TEST_EXECUTION_SPACE, Kokkos::Experimental::GraphNodeRootTag>
239 >
240 >;
241
242 const context_t gctx{exec};
243
244 stdexec::sync_wait(
245 stdexec::schedule(gctx.get_scheduler()) | stdexec::then(functor_t{}) | stdexec::then(functor_t{})
247}
248
253TEST_F(ThenTest, then_starts_on) {
254 const view_s_t data(Kokkos::view_alloc(exec, "data - shared space"));
255
256 const context_t gctx{exec};
257
259 auto chain = stdexec::just() | THEN_INCREMENT(data);
260
263 using chain_t = decltype(chain);
264
265 static_assert(
266 stdexec::get_completion_signatures<chain_t>()
267 == stdexec::completion_signatures<stdexec::set_value_t(), stdexec::set_error_t(std::exception_ptr)>{});
269 static_assert(
270 std::same_as<stdexec::__completion_domain_of_t<stdexec::set_value_t, chain_t>, stdexec::indeterminate_domain<>>);
271
273 auto starts_on = stdexec::starts_on(gctx.get_scheduler(), std::move(chain));
274
275 using starts_on_t = decltype(starts_on);
276
278 static_assert(stdexec::__has_eptr_completion<chain_t>);
279 static_assert(!stdexec::dependent_sender<starts_on_t>);
280 static_assert(
281 stdexec::get_completion_signatures<starts_on_t>()
282 == stdexec::completion_signatures<stdexec::set_value_t(), stdexec::set_error_t(std::exception_ptr)>{});
283
285 static_assert(stdexec::__completes_where_it_starts<stdexec::set_value_t, stdexec::env_of_t<chain_t>>);
287 static_assert(std::same_as<
290 >);
291 static_assert(std::same_as<
292 stdexec::__completion_domain_of_t<stdexec::set_value_t, starts_on_t, stdexec::env<>>,
294 >);
295
296 ASSERT_EQ(data(), 0) << "Eager execution is not allowed.";
297
298 const auto recorded_events = Tests::Utils::record_sync_wait<recorder_listener_t>(std::move(starts_on));
299
300 ASSERT_THAT(
301 recorded_events,
302 testing::ElementsAre(
305 recorded_events.at(0), device_handle, MATCHER_FOR_GRAPH_ROOT_NODE_OF(recorded_events.at(0))),
306 MATCHER_FOR_GRAPH_SUBMIT(exec, recorded_events.at(0)),
307 MATCHER_FOR_BEGIN_FENCE(exec, dispatch_label(exec, "after dispatch"))));
308
309 ASSERT_EQ(data(), 1);
310}
311
313TEST_F(ThenTest, forwarding_env) {
314 const view_s_t data(Kokkos::view_alloc(exec, "data - shared space"));
315
316 std::atomic<size_t> count = 0;
317
318 int value;
319
320 const context_t gctx{exec};
321
322 stdexec::sender auto sndr =
323 stdexec::read_env(stdexec::get_allocator)
324 | stdexec::then([&value](auto allocator) { value = Tests::Utils::round_trip_allocate(allocator, 42); })
325 | stdexec::continues_on(gctx.get_scheduler())
327 | stdexec::write_env(stdexec::prop{stdexec::get_allocator, Tests::Utils::TrackingAllocator<int>{&count}});
328
329 ASSERT_EQ(data(), 0) << "Eager execution is not allowed.";
330
332
333 const auto recorded_events = Tests::Utils::record_sync_wait<recorder_listener_t>(std::move(sndr));
334
335 ASSERT_THAT(
336 recorded_events,
337 testing::ElementsAre(
340 recorded_events.at(0), device_handle, MATCHER_FOR_GRAPH_ROOT_NODE_OF(recorded_events.at(0))),
341 MATCHER_FOR_GRAPH_SUBMIT(exec, recorded_events.at(0)),
342 MATCHER_FOR_BEGIN_FENCE(exec, dispatch_label(exec, "after dispatch"))));
343
344 ASSERT_EQ(data(), 1);
345
346 ASSERT_EQ(value, 42);
347 ASSERT_EQ(count, 1);
348}
349
350} // namespace Tests::GraphImpl
constexpr std::string dispatch_label(const Exec &, const std::string_view label)
Get the dispatch label from Exec and label.
#define MATCHER_FOR_BEGIN_FENCE(_exec_, _label_)
RecorderListener< ConjunctionMatcher< EventDiscardMatcher< TEST_EXECUTION_SPACE >, GraphEventDiscardMatcher< TEST_EXECUTION_SPACE > >, BeginFenceEvent, BeginParallelForEvent, AllocateDataEvent, DeallocateDataEvent, Kokkos::Execution::Impl::RecordEvent, Kokkos::Execution::Impl::WaitEvent, Kokkos::Execution::GraphImpl::GraphAddNodeEvent, Kokkos::Execution::GraphImpl::GraphCreateEvent, Kokkos::Execution::GraphImpl::GraphInstantiateEvent, Kokkos::Execution::GraphImpl::GraphSubmitEvent > recorder_listener_t
Definition test_then.cpp:44
Concept for a sender whose completion scheduler is Kokkos::Execution::GraphImpl::Scheduler.
Concept that constrains the type of a sender that dispatches a functor for execution.
#define KOKKOS_EXECUTION_TEST_UTILS_GRAPH_FENCE(_exec_)
#define THEN_INCREMENT(_data_)
Add a then using Tests::Utils::Functors::Increment that may throw. // NOLINTNEXTLINE(cppcoreguideline...
Definition increment.hpp:64
std::invoke_result_t< stdexec::get_completion_scheduler_t< Tag >, stdexec::env_of_t< Sndr >, Env... > completion_scheduler_of_t
Retrieve the completion scheduler for a given completion tag.
consteval bool test_sndr_nothrow_transformable()
Definition test_bulk.cpp:90
consteval bool test_then_op_state_traits()
consteval bool test_sndr_traits()
Definition test_bulk.cpp:57
consteval bool test_sndr_nothrow_connectable()
constexpr check_node_type_t< NodeType > check_node_type
The provided type NodeType is compared without cv type qualifiers during connect.
auto record_sync_wait(Sndr &&sndr)
Definition sync_wait.hpp:14
consteval bool check_continues_on_after_just_stopped()
constexpr check_rcvr_env_queryable_with_t< true, Queries... > check_rcvr_env_queryable_with
auto round_trip_allocate(Allocator &allocator, T &&value)
auto get_scheduler() const noexcept -> GraphImpl::Scheduler< execution_space >
Definition graph.hpp:134
Event to be sent to Kokkos::utils::callbacks::dispatch when a Kokkos graph node is added.
Definition events.hpp:49
Event to be sent to Kokkos::utils::callbacks::dispatch when a Kokkos graph is created.
Definition events.hpp:28
Event to be sent to Kokkos::utils::callbacks::dispatch when a Kokkos graph is instantiated.
Definition events.hpp:85
Event to be sent to Kokkos::utils::callbacks::dispatch when a Kokkos graph is submitted.
Definition events.hpp:98
Sender for stdexec::then.
Definition then.hpp:64
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
Similar to EventDiscardMatcher, for graph-related events.
Definition events.hpp:83
decltype(std::declval< const context_t >().get_scheduler()) scheduler_t
Definition context.hpp:34
decltype(stdexec::schedule(std::declval< scheduler_t >())) schedule_sender_t
Definition context.hpp:35
Kokkos::View< value_t, Kokkos::SharedSpace > view_s_t
Definition context.hpp:38
Load the value at data and check it is equal to prev. Then, add value to it.
A minimal tracking allocator.
#define MATCHER_FOR_GRAPH_CREATE(_device_handle_)
Definition events.hpp:17
#define MATCHER_FOR_GRAPH_ADDNODE(_graph_create_event_variant_, _device_handle_, _predecessor_,...)
Definition events.hpp:24
#define MATCHER_FOR_GRAPH_SUBMIT(_exec_, _graph_create_event_variant_)
Definition events.hpp:71
#define MATCHER_FOR_GRAPH_ROOT_NODE_OF(_graph_create_event_)
Definition events.hpp:51
#define MATCHER_FOR_GRAPH_NODE_OF(_graph_add_node_event_)
Definition events.hpp:55