kokkos-execution 0.0.1
Loading...
Searching...
No Matches
test_then.cpp
Go to the documentation of this file.
4
7
22
34
35namespace Tests::GraphImpl {
36
37using namespace Kokkos::utils::callbacks;
38
57
59consteval bool test_sndr_traits() {
61 using schd_sndr_t = typename ThenTest::schedule_sender_t;
62
65 using then_sndr_t = stdexec::transform_sender_result_t<
66 decltype(stdexec::then(std::declval<schd_sndr_t>(), std::declval<functor_t>())),
67 stdexec::env<>
68 >;
69
72 static_assert(std::same_as<Kokkos::Execution::Impl::exec_of_t<then_sndr_t>, TEST_EXECUTION_SPACE>);
73
76
77 return true;
78}
79static_assert(test_sndr_traits());
80
83 typename ThenTest::scheduler_t,
84 stdexec::then_t,
86>());
87
89consteval bool test_sndr_nothrow_transformable() {
90 using sndr_then_t =
91 decltype(stdexec::schedule(std::declval<typename ThenTest::scheduler_t>()) | stdexec::then(Tests::Utils::Functors::NoOp<false, false, false>{}));
92
93 static_assert(std::same_as<
94 stdexec::__demangle_t<sndr_then_t>,
96 stdexec::then_t,
99 >
100 >);
101
102 static_assert(stdexec::__detail::__has_nothrow_transform_sender<
104 stdexec::set_value_t,
105 sndr_then_t&&,
106 stdexec::env<>
107 >);
108
109 using sndr_then_maythrow_on_move_t =
110 decltype(stdexec::schedule(std::declval<typename ThenTest::scheduler_t>()) | stdexec::then(Tests::Utils::Functors::NoOp<false, false, true>{}));
111
112 static_assert(!stdexec::__detail::__has_nothrow_transform_sender<
113 Kokkos::Execution::GraphImpl::Domain,
114 stdexec::set_value_t,
115 sndr_then_maythrow_on_move_t&&,
116 stdexec::env<>
117 >);
118
119 return true;
120}
121static_assert(test_sndr_nothrow_transformable());
122
124consteval bool test_sndr_nothrow_connectable() {
126 static_assert(!std::is_nothrow_constructible_v<Kokkos::Experimental::Graph<TEST_EXECUTION_SPACE>>);
127
128 using sndr_then_t =
129 decltype(stdexec::schedule(std::declval<typename ThenTest::scheduler_t>()) | stdexec::then(Tests::Utils::Functors::NoOp<false, false, false>{}));
130
131 static_assert(!stdexec::__nothrow_connectable<sndr_then_t, Tests::Utils::SinkReceiver>);
132
133 return true;
134}
135static_assert(test_sndr_nothrow_connectable());
136
138consteval bool test_then_opstate_traits() {
140
141 using sndr_t =
142 decltype(stdexec::schedule(std::declval<typename ThenTest::scheduler_t>()) | stdexec::then(functor_t{}) | stdexec::then(functor_t{}));
143 using connect_result_t = stdexec::connect_result_t<sndr_t, Tests::Utils::SinkReceiver>;
144
145 static_assert(stdexec::__is_instance_of<connect_result_t, Kokkos::Execution::GraphImpl::OpState>);
146
147 using root_t = typename ThenTest::graph_t::root_t;
148 using then_A_t = Kokkos::Experimental::GraphNodeRef<
149 TEST_EXECUTION_SPACE,
150 Kokkos::Impl::GraphNodeThenImpl<TEST_EXECUTION_SPACE, Kokkos::Experimental::ThenPolicy<>, functor_t>,
151 root_t
152 >;
153 using then_B_t = Kokkos::Experimental::GraphNodeRef<
154 TEST_EXECUTION_SPACE,
155 Kokkos::Impl::GraphNodeThenImpl<TEST_EXECUTION_SPACE, Kokkos::Experimental::ThenPolicy<>, functor_t>,
156 then_A_t
157 >;
158
159 static_assert(std::same_as<typename connect_result_t::predecessor_t, root_t>);
160 static_assert(std::same_as<typename connect_result_t::node_t, then_B_t>);
161
162 return true;
163}
164static_assert(test_then_opstate_traits());
165
170TEST_F(ThenTest, then_schedule) {
171 const view_s_t data(Kokkos::view_alloc(exec, "data - shared space"));
172
173 const context_t gctx{exec};
174
176
177 auto sndr = stdexec::schedule(gctx.get_scheduler())
178 | stdexec::then(functor_t{.prev = 0, .value = 4, .data = data.data()})
179 | stdexec::then(functor_t{.prev = 4, .value = 3, .data = data.data()});
180
181 using sndr_t = decltype(sndr);
182
183 static_assert(std::same_as<
184 stdexec::__demangle_t<stdexec::transform_sender_result_t<sndr_t, stdexec::env<>>>,
186 TEST_EXECUTION_SPACE,
188 functor_t
189 >
190 >);
191
193 static_assert(std::same_as<stdexec::__domain_of_t<stdexec::env_of_t<sndr_t>>, stdexec::default_domain>);
194 static_assert(std::same_as<
195 stdexec::__detail::__completing_domain_t<stdexec::set_value_t, sndr_t>,
197 >);
198
200 static_assert(std::same_as<
202 typename ThenTest::scheduler_t
203 >);
204
205 ASSERT_EQ(data(), 0) << "Eager execution is not allowed.";
206
207 const auto recorded_events = Tests::Utils::record_sync_wait<recorder_listener_t>(
208 std::move(sndr)); // NOLINT(performance-move-const-arg)
209
210 ASSERT_THAT(
211 recorded_events,
212 testing::ElementsAre(
214 MATCHER_FOR_GRAPH_ADDNODE(recorded_events.at(0), device_handle, nullptr),
216 recorded_events.at(0), device_handle, MATCHER_FOR_GRAPH_NODE_OF(recorded_events.at(1))),
217 MATCHER_FOR_GRAPH_SUBMIT(exec, recorded_events.at(0)),
219
220 ASSERT_EQ(data(), 7);
221}
222
227TEST_F(ThenTest, then_starts_on) {
228 const view_s_t data(Kokkos::view_alloc(exec, "data - shared space"));
229
230 const context_t gctx{exec};
231
233 auto work = stdexec::just() | THEN_INCREMENT(data);
234
237 using work_t = decltype(work);
238
241 work_t,
242 stdexec::__mset<stdexec::set_error_t(std::exception_ptr), stdexec::set_value_t()>
243 >);
244 static_assert(
245 std::same_as<stdexec::__completion_domain_of_t<stdexec::set_value_t, work_t>, stdexec::indeterminate_domain<>>);
246
248 auto sndr = stdexec::starts_on(gctx.get_scheduler(), std::move(work));
249
250 using sndr_t = decltype(sndr);
251
253 static_assert(stdexec::dependent_sender<sndr_t>);
255 static_assert(std::same_as<
257 typename ThenTest::scheduler_t
258 >);
260 sndr_t,
261 stdexec::__mset<stdexec::set_value_t(), stdexec::set_error_t(std::exception_ptr)>,
262 stdexec::env<>
263 >);
264
266 static_assert(std::same_as<
267 stdexec::__completion_domain_of_t<stdexec::set_value_t, sndr_t, stdexec::env<>>,
269 >);
270
271 ASSERT_EQ(data(), 0) << "Eager execution is not allowed.";
272
273 const auto recorded_events = Tests::Utils::record_sync_wait<recorder_listener_t>(std::move(sndr));
274
275 ASSERT_THAT(
276 recorded_events,
277 testing::ElementsAre(
279 MATCHER_FOR_GRAPH_ADDNODE(recorded_events.at(0), device_handle, nullptr),
280 MATCHER_FOR_GRAPH_SUBMIT(exec, recorded_events.at(0)),
281 MATCHER_FOR_BEGIN_FENCE(exec, dispatch_label(exec, "after dispatch"))));
282
283 ASSERT_EQ(data(), 1);
284}
285
287TEST_F(ThenTest, forwarding_env) {
288 const view_s_t data(Kokkos::view_alloc(exec, "data - shared space"));
289
290 std::atomic<size_t> count = 0;
291
292 int value;
293
294 const context_t gctx{exec};
295
296 stdexec::sender auto sndr =
297 stdexec::read_env(stdexec::get_allocator)
298 | stdexec::then([&value](auto allocator) { value = Tests::Utils::round_trip_allocate(allocator, 42); })
299 | stdexec::continues_on(gctx.get_scheduler())
301 | stdexec::write_env(stdexec::prop{stdexec::get_allocator, Tests::Utils::TrackingAllocator<int>{&count}});
302
303 ASSERT_EQ(data(), 0) << "Eager execution is not allowed.";
304
306
307 const auto recorded_events = Tests::Utils::record_sync_wait<recorder_listener_t>(std::move(sndr));
308
309 ASSERT_THAT(
310 recorded_events,
311 testing::ElementsAre(
313 MATCHER_FOR_GRAPH_ADDNODE(recorded_events.at(0), device_handle, nullptr),
314 MATCHER_FOR_GRAPH_SUBMIT(exec, recorded_events.at(0)),
315 MATCHER_FOR_BEGIN_FENCE(exec, dispatch_label(exec, "after dispatch"))));
316
317 ASSERT_EQ(data(), 1);
318
319 ASSERT_EQ(value, 42);
320 ASSERT_EQ(count, 1);
321}
322
323} // namespace Tests::GraphImpl
constexpr std::string dispatch_label(const Exec &, Label &&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:43
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:59
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:89
consteval bool test_then_opstate_traits()
consteval bool test_sndr_traits()
Definition test_bulk.cpp:57
consteval bool test_sndr_nothrow_connectable()
typename stdexec::__basic_sender< Args... >::type basic_sender_t
See https://github.com/NVIDIA/stdexec/pull/1873#discussion_r2834863237.
Definition stdexec.hpp:12
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< Exec >
Definition graph.hpp:126
Event to be sent to Kokkos::utils::callbacks::dispatch when a Kokkos graph node is added.
Definition events.hpp:35
Event to be sent to Kokkos::utils::callbacks::dispatch when a Kokkos graph is created.
Definition events.hpp:16
Event to be sent to Kokkos::utils::callbacks::dispatch when a Kokkos graph is instantiated.
Definition events.hpp:65
Event to be sent to Kokkos::utils::callbacks::dispatch when a Kokkos graph is submitted.
Definition events.hpp:76
Sender for stdexec::then.
Definition then.hpp:51
Event to be sent to Kokkos::utils::callbacks::dispatch when calling record.
Definition event.hpp:54
Event to be sent to Kokkos::utils::callbacks::dispatch when calling wait.
Definition event.hpp:75
Similar to EventDiscardMatcher, for graph-related events.
Definition events.hpp:76
decltype(std::declval< const context_t >().get_scheduler()) scheduler_t
Definition context.hpp:28
decltype(stdexec::schedule(std::declval< scheduler_t >())) schedule_sender_t
Definition context.hpp:29
Kokkos::View< value_t, Kokkos::SharedSpace > view_s_t
Definition context.hpp:32
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_SUBMIT(_exec_, _graph_create_event_variant_)
Definition events.hpp:63
#define MATCHER_FOR_GRAPH_ADDNODE(_graph_create_event_variant_, _device_handle_, _predecessor_)
Definition events.hpp:24
#define MATCHER_FOR_GRAPH_NODE_OF(_graph_add_node_event_)
Definition events.hpp:47