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 TEST_EXECUTION_SPACE,
67 functor_t,
68 Kokkos::RangePolicy<TEST_EXECUTION_SPACE, Kokkos::IndexType<int>>,
70 >
71 >
72 >);
73
76 static_assert(std::same_as<Kokkos::Execution::Impl::exec_of_t<bulk_sndr_t>, TEST_EXECUTION_SPACE>);
77
80
81 return true;
82}
83
84static_assert(test_sndr_traits());
85
88 using sndr_bulk_t =
89 decltype(stdexec::schedule(std::declval<typename BulkTest::scheduler_t>()) | stdexec::bulk(stdexec::par, 1, Tests::Utils::Functors::NoOp<false, false, false>{}));
90
91 static_assert(stdexec::__detail::__has_nothrow_transform_sender<
93 stdexec::set_value_t,
94 sndr_bulk_t&&,
95 stdexec::env<>
96 >);
97
98 using sndr_bulk_maythrow_on_move_t =
99 decltype(stdexec::schedule(std::declval<typename BulkTest::scheduler_t>()) | stdexec::bulk(stdexec::par, 1, Tests::Utils::Functors::NoOp<false, false, true>{}));
100
101 static_assert(!stdexec::__detail::__has_nothrow_transform_sender<
103 stdexec::set_value_t,
104 sndr_bulk_maythrow_on_move_t&&,
105 stdexec::env<>
106 >);
107
108 using sndr_bulk_maythrow_on_copy_t =
109 decltype(stdexec::schedule(std::declval<typename BulkTest::scheduler_t>()) | stdexec::bulk(stdexec::par, 1, Tests::Utils::Functors::NoOp<false, true, false>{}));
110
111 static_assert(!stdexec::__detail::__has_nothrow_transform_sender<
113 stdexec::set_value_t,
114 const sndr_bulk_maythrow_on_copy_t&,
115 stdexec::env<>
116 >);
117
118 static_assert(
119 !noexcept(stdexec::transform_sender(std::declval<const sndr_bulk_maythrow_on_copy_t&>(), stdexec::env<>{})));
120
121 return true;
122}
123
124static_assert(test_sndr_nothrow_transformable());
125
128 typename BulkTest::scheduler_t,
129 stdexec::bulk_t,
130 stdexec::parallel_policy,
131 int,
133>());
134
140 using sndr_t = decltype(stdexec::bulk(
141 stdexec::schedule(std::declval<typename BulkTest::context_t>().get_scheduler()),
142 stdexec::par,
143 1,
145
146 static_assert(!std::is_const_v<sndr_t>);
147
149 using op_state_from_sndr_const_ref_t = stdexec::connect_result_t<const sndr_t&, Tests::Utils::SinkReceiver>;
150
151 static_assert(std::same_as<
152 op_state_from_sndr_const_ref_t,
154 const typename BulkTest::schedule_sender_t&,
157 TEST_EXECUTION_SPACE,
160 Kokkos::RangePolicy<TEST_EXECUTION_SPACE, Kokkos::IndexType<int>>,
162 >
163 >
164 >
165 >);
166
167 return true;
168}
169
170static_assert(test_op_state_passed_by_const_ref());
171
173TEST_F(BulkTest, bulk) {
174 constexpr size_t size = 10;
175
176 const view_s_t data(Kokkos::view_alloc(exec, "data - shared space"));
177
178 const context_t esc{exec};
179
180 auto chain = stdexec::schedule(esc.get_scheduler()) | BULK_SUM_INDICES(size, data);
181
182 using chain_t = decltype(chain);
183
185 static_assert(std::same_as<stdexec::__domain_of_t<stdexec::env_of_t<chain_t>>, stdexec::default_domain>);
186 static_assert(std::same_as<
187 stdexec::__detail::__completing_domain_t<stdexec::set_value_t, chain_t>,
189 >);
190
192 static_assert(std::same_as<
193 decltype(stdexec::get_completion_scheduler<stdexec::set_value_t>(stdexec::get_env(chain))),
195 >);
196
197 ASSERT_EQ(data(), 0) << "Eager execution is not allowed.";
198
199 ASSERT_THAT(
201 testing::ElementsAre(
204
205 ASSERT_EQ(data(), size / 2 * (size - 1));
206}
207
209TEST_F(BulkTest, no_spurious_copy_on_connect) {
210 const context_t esc{exec};
211
213
214 {
215 auto lvalue = stdexec::schedule(esc.get_scheduler())
216 | stdexec::bulk(stdexec::par, 42, Tests::Utils::Functors::Counter{});
217
218 [[maybe_unused]]
219 const auto lop_state = stdexec::connect(lvalue, Tests::Utils::SinkReceiver{});
220
224 }
225
227
228 {
229 auto rvalue = stdexec::schedule(esc.get_scheduler())
230 | stdexec::bulk(stdexec::par, 42, Tests::Utils::Functors::Counter{});
231
232 [[maybe_unused]]
233 const auto rop_state = stdexec::connect(std::move(rvalue), Tests::Utils::SinkReceiver{});
234
238 }
239}
240
242TEST_F(BulkTest, forwarding_env) {
243 constexpr size_t size = 10;
244
245 const view_s_t data(Kokkos::view_alloc(exec, "data - shared space"));
246
247 std::atomic<size_t> count = 0;
248
249 int value;
250
251 const context_t esc{exec};
252
253 stdexec::sender auto sndr =
254 stdexec::read_env(stdexec::get_allocator)
255 | stdexec::then([&value](auto allocator) { value = Tests::Utils::round_trip_allocate(allocator, 42); })
256 | stdexec::continues_on(esc.get_scheduler())
258 | stdexec::write_env(stdexec::prop{stdexec::get_allocator, Tests::Utils::TrackingAllocator<int>{&count}});
259
260 ASSERT_EQ(data(), 0) << "Eager execution is not allowed.";
261
262 const auto recorded_events = Tests::Utils::record_sync_wait<recorder_listener_t>(std::move(sndr));
263
264 ASSERT_THAT(recorded_events, [&]() {
266 return testing::ElementsAre(
269 MATCHER_FOR_WAIT_EVENT(recorded_events.at(1)));
270 } else {
271 return testing::ElementsAre(
273 MATCHER_FOR_BEGIN_FENCE(exec, dispatch_label(exec, "after dispatch")));
274 }
275 }());
276
277 ASSERT_EQ(data(), size / 2 * (size - 1));
278
279 ASSERT_EQ(value, 42);
280 ASSERT_EQ(count, 1);
281}
282
283} // 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_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:87
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< 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
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::Execution::ExecutionSpaceContext< Exec > context_t
Definition context.hpp:33
Count construction, move/copy construction, move/copy assignment and destruction atomically on host.
Definition counter.hpp:14
static std::atomic< unsigned int > move_assignments
Definition counter.hpp:20
static std::atomic< unsigned int > copy_constructions
Definition counter.hpp:17
static std::atomic< unsigned int > copy_assignments
Definition counter.hpp:18
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)...