kokkos-execution 0.0.1
Loading...
Searching...
No Matches
test_bulk.cpp
Go to the documentation of this file.
3
5
18
30
32
33using namespace Kokkos::utils::callbacks;
34
47
49consteval bool test_sndr_traits() {
51 using schd_sndr_t = typename BulkTest::schedule_sender_t;
52
55 using bulk_sndr_t = stdexec::transform_sender_result_t<
56 decltype(stdexec::bulk(std::declval<schd_sndr_t>(), stdexec::par, 1, std::declval<functor_t>())),
57 stdexec::env<>
58 >;
59
60 static_assert(std::same_as<
61 bulk_sndr_t,
63 stdexec::bulk_t,
64 schd_sndr_t,
65 std::string_view,
66 functor_t,
67 Kokkos::RangePolicy<TEST_EXECUTION_SPACE>
68 >
69 >);
70
73 static_assert(std::same_as<Kokkos::Execution::Impl::exec_of_t<bulk_sndr_t>, TEST_EXECUTION_SPACE>);
74
77
78 return true;
79}
80static_assert(test_sndr_traits());
81
84 using sndr_bulk_t =
85 decltype(stdexec::schedule(std::declval<typename BulkTest::scheduler_t>()) | stdexec::bulk(stdexec::par, 1, Tests::Utils::Functors::NoOp<false, false, false>{}));
86
87 static_assert(stdexec::__detail::__has_nothrow_transform_sender<
89 stdexec::set_value_t,
90 sndr_bulk_t&&,
91 stdexec::env<>
92 >);
93
94 using sndr_bulk_maythrow_on_move_t =
95 decltype(stdexec::schedule(std::declval<typename BulkTest::scheduler_t>()) | stdexec::bulk(stdexec::par, 1, Tests::Utils::Functors::NoOp<false, false, true>{}));
96
97 static_assert(!stdexec::__detail::__has_nothrow_transform_sender<
99 stdexec::set_value_t,
100 sndr_bulk_maythrow_on_move_t&&,
101 stdexec::env<>
102 >);
103
104 return true;
105}
106static_assert(test_sndr_nothrow_transformable());
107
110 typename BulkTest::scheduler_t,
111 stdexec::bulk_t,
112 stdexec::parallel_policy,
113 int,
115>());
116
122 using sndr_t = decltype(stdexec::bulk(
123 stdexec::schedule(std::declval<typename BulkTest::context_t>().get_scheduler()),
124 stdexec::par,
125 1,
127
128 static_assert(!std::is_const_v<sndr_t>);
129
131 using op_state_from_sndr_const_ref_t = stdexec::connect_result_t<const sndr_t&, Tests::Utils::SinkReceiver>;
132
133 static_assert(std::same_as<
134 op_state_from_sndr_const_ref_t,
136 const typename BulkTest::schedule_sender_t&,
139 std::string_view,
141 Kokkos::RangePolicy<TEST_EXECUTION_SPACE>
142 >
143 >
144 >);
145
146 return true;
147}
148static_assert(test_op_state_passed_by_const_ref());
149
151TEST_F(BulkTest, bulk) {
152 constexpr size_t size = 10;
153
154 const view_s_t data(Kokkos::view_alloc(exec, "data - shared space"));
155
156 const context_t esc{exec};
157
158 auto chain = stdexec::schedule(esc.get_scheduler()) | BULK_SUM_INDICES(size, data);
159
160 using chain_t = decltype(chain);
161
163 static_assert(std::same_as<stdexec::__domain_of_t<stdexec::env_of_t<chain_t>>, stdexec::default_domain>);
164 static_assert(std::same_as<
165 stdexec::__detail::__completing_domain_t<stdexec::set_value_t, chain_t>,
167 >);
168
170 static_assert(std::same_as<
171 decltype(stdexec::get_completion_scheduler<stdexec::set_value_t>(stdexec::get_env(chain))),
173 >);
174
175 ASSERT_EQ(data(), 0) << "Eager execution is not allowed.";
176
177 ASSERT_THAT(
179 testing::ElementsAre(
182
183 ASSERT_EQ(data(), size / 2 * (size - 1));
184}
185
187TEST_F(BulkTest, no_spurious_copy_on_connect) {
188 const context_t esc{exec};
189
191
192 {
193 auto lvalue = stdexec::schedule(esc.get_scheduler())
194 | stdexec::bulk(stdexec::par, 42, Tests::Utils::Functors::Counter{});
195
196 [[maybe_unused]]
197 auto lopstate = stdexec::connect(lvalue, Tests::Utils::SinkReceiver{});
198
202 }
203
205
206 {
207 auto rvalue = stdexec::schedule(esc.get_scheduler())
208 | stdexec::bulk(stdexec::par, 42, Tests::Utils::Functors::Counter{});
209
210 [[maybe_unused]]
211 auto ropstate = stdexec::connect(std::move(rvalue), Tests::Utils::SinkReceiver{});
212
216 }
217}
218
220TEST_F(BulkTest, forwarding_env) {
221 constexpr size_t size = 10;
222
223 const view_s_t data(Kokkos::view_alloc(exec, "data - shared space"));
224
225 std::atomic<size_t> count = 0;
226
227 int value;
228
229 const context_t esc{exec};
230
231 stdexec::sender auto sndr =
232 stdexec::read_env(stdexec::get_allocator)
233 | stdexec::then([&value](auto allocator) { value = Tests::Utils::round_trip_allocate(allocator, 42); })
234 | stdexec::continues_on(esc.get_scheduler())
236 | stdexec::write_env(stdexec::prop{stdexec::get_allocator, Tests::Utils::TrackingAllocator<int>{&count}});
237
238 ASSERT_EQ(data(), 0) << "Eager execution is not allowed.";
239
240 const auto recorded_events = Tests::Utils::record_sync_wait<recorder_listener_t>(std::move(sndr));
241
242 ASSERT_THAT(recorded_events, [&]() {
244 return testing::ElementsAre(
247 MATCHER_FOR_WAIT_EVENT(recorded_events.at(1)));
248 } else {
249 return testing::ElementsAre(
251 MATCHER_FOR_BEGIN_FENCE(exec, dispatch_label(exec, "after dispatch")));
252 }
253 }());
254
255 ASSERT_EQ(data(), size / 2 * (size - 1));
256
257 ASSERT_EQ(value, 42);
258 ASSERT_EQ(count, 1);
259}
260
261} // namespace Tests::ExecutionSpaceImpl
constexpr std::string dispatch_label(const Exec &, Label &&label)
Get the dispatch label from Exec and 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, Kokkos::Execution::Impl::RecordEvent, Kokkos::Execution::Impl::WaitEvent > recorder_listener_t
Definition test_bulk.cpp:39
Concept for a sender whose completion scheduler is Kokkos::Execution::ExecutionSpaceImpl::Scheduler.
Concept that constrains the type of a sender that dispatches a functor for execution.
constexpr bool test_op_state_passed_by_const_ref()
consteval bool test_sndr_traits()
Definition test_bulk.cpp:49
consteval bool test_sndr_nothrow_transformable()
Definition test_bulk.cpp:83
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)
Matcher to filter out events that are just noise for tests.
auto get_scheduler() const noexcept -> ExecutionSpaceImpl::Scheduler< Exec >
Event to be sent to Kokkos::utils::callbacks::dispatch when calling record.
Definition event.hpp:52
Event to be sent to Kokkos::utils::callbacks::dispatch when calling wait.
Definition event.hpp:73
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::Execution::ExecutionSpaceContext< Exec > context_t
Definition context.hpp:27
Count construction, move/copy construction, move/copy assignment and destruction atomically on host.
Definition counter.hpp:9
static std::atomic< unsigned int > move_assignments
Definition counter.hpp:15
static std::atomic< unsigned int > copy_constructions
Definition counter.hpp:12
static std::atomic< unsigned int > copy_assignments
Definition counter.hpp:13
A receiver that can handle all completions and does nothing with them.
A minimal tracking allocator.
#define BULK_SUM_INDICES(_size_, _data_)
Add a bulk using Tests::Utils::Functors::SumIndices. // NOLINTNEXTLINE(cppcoreguidelines-macro-usage)...