kokkos-execution 0.0.1
Loading...
Searching...
No Matches
test_parallel_reduce.cpp
Go to the documentation of this file.
1#include "gtest/gtest.h"
2
3#include "Kokkos_Macros.hpp"
4#ifdef KOKKOS_ENABLE_EXPERIMENTAL_CXX20_MODULES
5import kokkos.core;
6#else
7# include "Kokkos_Core.hpp"
8#endif
9
11
15
26
27namespace Tests {
28
32
33 [[maybe_unused]]
34 const auto sndr_a = Kokkos::Execution::parallel_reduce(42, functor_t{}, functor_t{});
35
36 [[maybe_unused]]
37 const auto sndr_b =
38 Kokkos::Execution::parallel_reduce(Kokkos::range_slice<size_t, size_t>{42, 43}, functor_t{}, functor_t{});
39
40 return std::is_constant_evaluated();
41}
42
44
68
78
80
84 static_assert(std::is_aggregate_v<typename ParallelReduceDataTest::data_t>);
85 static_assert(std::is_aggregate_v<typename ParallelReduceDataTest::labeled_data_t>);
86 static_assert(std::is_aggregate_v<typename ParallelReduceDataTest::multi_data_t>);
87
89 static_assert(std::is_nothrow_move_constructible_v<typename ParallelReduceDataTest::data_t>);
90 static_assert(std::is_nothrow_move_constructible_v<typename ParallelReduceDataTest::labeled_data_t>);
91 static_assert(std::is_nothrow_move_constructible_v<typename ParallelReduceDataTest::multi_data_t>);
92
94 static_assert(
95 std::same_as<typename ParallelReduceDataTest::data_t::functor_t, typename ParallelReduceDataTest::functor_t>);
96 static_assert(std::same_as<
99 >);
100 static_assert(
101 std::same_as<typename ParallelReduceDataTest::data_t::reducer_t, typename ParallelReduceDataTest::reducer_t>);
102 static_assert(
103 std::same_as<typename ParallelReduceDataTest::data_t::properties_t, Kokkos::Execution::Impl::properties<>>);
104 static_assert(std::same_as<
107 >);
108
112
113 return true;
114}
115
116static_assert(test_parallel_reduce_data_traits());
117
120 static_assert(sizeof(typename ParallelReduceDataTest::functor_t) == 1);
121 static_assert(std::alignment_of_v<typename ParallelReduceDataTest::functor_t> == 1);
122
123 static_assert(sizeof(typename ParallelReduceDataTest::iter_space_t) == 8);
124 static_assert(std::alignment_of_v<typename ParallelReduceDataTest::iter_space_t> == 4);
125
126 static_assert(sizeof(typename ParallelReduceDataTest::reducer_t) == 1);
127 static_assert(std::alignment_of_v<typename ParallelReduceDataTest::reducer_t> == 1);
128
129 static_assert(std::is_empty_v<typename ParallelReduceDataTest::functor_t>);
130 static_assert(std::is_standard_layout_v<typename ParallelReduceDataTest::data_t>);
131 static_assert(std::is_empty_v<typename ParallelReduceDataTest::reducer_t>);
132
133 static_assert(offsetof(typename ParallelReduceDataTest::data_t, functor) == 0);
134 static_assert(offsetof(typename ParallelReduceDataTest::data_t, policy_or_iter_space) == 4);
135 static_assert(offsetof(typename ParallelReduceDataTest::data_t, reducer) == 12);
136
137 static_assert(sizeof(typename ParallelReduceDataTest::data_t) == 16);
138 static_assert(sizeof(typename ParallelReduceDataTest::labeled_data_t) == 32);
139
140 return true;
141}
142
143static_assert(test_parallel_reduce_data_size());
144
146TEST_F(ParallelReduceDataTest, transform_policy_or_iter_space) {
147 using labeled_data_iter_space_t = Kokkos::Execution::Impl::ParallelReduceData<
148 functor_t,
150 reducer_t,
152 >;
153
154 using labeled_data_range_policy_t = Kokkos::Execution::Impl::ParallelReduceData<
155 functor_t,
156 Kokkos::RangePolicy<TEST_EXECUTION_SPACE>,
157 reducer_t,
159 >;
160
161 constexpr labeled_data_iter_space_t with_iter_space{
163 functor_t{},
164 iter_space_t{4, 6},
165 reducer_t{}
166 };
167
168 const auto with_range_policy = with_iter_space.transform_policy_or_iter_space(
169 [](const auto& pol) { return Kokkos::RangePolicy<TEST_EXECUTION_SPACE>(pol.first, pol.last); });
170
171 static_assert(std::same_as<decltype(with_range_policy), const labeled_data_range_policy_t>);
172
173 ASSERT_EQ(with_range_policy.policy_or_iter_space.begin(), 4);
174 ASSERT_EQ(with_range_policy.policy_or_iter_space.end(), 6);
175}
176
187TEST_F(ParallelReduceDataTest, transform_policy_or_iter_space_perfectly_forwards_properties) {
188 using counter_t = Tests::Utils::Functors::Counter;
189 using data_with_counter_t =
191
192 counter_t::reset();
193 {
194 data_with_counter_t from_xvalue{counter_t{}, counter_t{}, iter_space_t{}, reducer_t{}};
195 [[maybe_unused]]
196 const auto data_from_xvalue = std::move(from_xvalue).transform_policy_or_iter_space([](const auto&) {
197 return iter_space_t{4, 6};
198 });
199 ASSERT_EQ(counter_t::copy_assignments, 0);
200 ASSERT_EQ(counter_t::copy_constructions, 0);
201 ASSERT_EQ(counter_t::move_assignments, 0);
202#if defined(KOKKOS_COMPILER_CLANG) || defined(KOKKOS_COMPILER_INTEL_LLVM)
203 ASSERT_EQ(counter_t::move_constructions, 3);
204#else
205 ASSERT_EQ(counter_t::move_constructions, 2);
206#endif
207 }
208
209 counter_t::reset();
210 {
211 [[maybe_unused]]
212 const auto data_from_prvalue = data_with_counter_t{counter_t{}, counter_t{}, iter_space_t{}, reducer_t{}}
213 .transform_policy_or_iter_space(
214 [](const auto&) { return iter_space_t{4, 6}; });
215 ASSERT_EQ(counter_t::copy_assignments, 0);
216 ASSERT_EQ(counter_t::copy_constructions, 0);
217 ASSERT_EQ(counter_t::move_assignments, 0);
218#if defined(KOKKOS_COMPILER_CLANG) || defined(KOKKOS_COMPILER_INTEL_LLVM)
219 ASSERT_EQ(counter_t::move_constructions, 3);
220#else
221 ASSERT_EQ(counter_t::move_constructions, 2);
222#endif
223 }
224}
225
228 using label_t = std::string;
229 using policy_t = Kokkos::RangePolicy<TEST_EXECUTION_SPACE>;
230 using reducer_t = Kokkos::View<int, TEST_EXECUTION_SPACE>;
231
232 static_assert(noexcept(Kokkos::Execution::parallel_reduce(
233 std::declval<label_t>(),
234 std::declval<policy_t>(),
236 std::declval<reducer_t>())));
237
238 static_assert(!noexcept(Kokkos::Execution::parallel_reduce(
239 std::declval<const label_t&>(),
240 std::declval<policy_t>(),
242 std::declval<reducer_t>())));
243
244 static_assert(!noexcept(Kokkos::Execution::parallel_reduce(
245 std::declval<const char*>(),
246 std::declval<policy_t>(),
248 std::declval<reducer_t>())));
249
250 static_assert(!noexcept(Kokkos::Execution::parallel_reduce(
251 std::declval<label_t>(),
252 std::declval<policy_t>(),
254 std::declval<reducer_t>())));
255
256 static_assert(!noexcept(Kokkos::Execution::parallel_reduce(
257 std::declval<label_t>(),
258 std::declval<policy_t>(),
260 std::declval<reducer_t>())));
261
262 static_assert(noexcept(
263 stdexec::just()
265 std::declval<label_t>(),
266 std::declval<policy_t>(),
268 std::declval<reducer_t>())));
269
270 static_assert(!noexcept(
271 stdexec::just()
273 std::declval<const label_t&>(),
274 std::declval<policy_t>(),
276 std::declval<reducer_t>())));
277
279 using label_of_string_t = Kokkos::Execution::Impl::Label<std::string>;
280
281 static_assert(noexcept(Kokkos::Execution::parallel_reduce(
282 stdexec::just(),
283 std::declval<policy_t>(),
285 std::declval<reducer_t>(),
286 std::declval<label_of_string_t>())));
287
288 static_assert(!noexcept(Kokkos::Execution::parallel_reduce(
289 stdexec::just(),
290 std::declval<policy_t>(),
292 std::declval<reducer_t>(),
293 std::declval<const label_of_string_t&>())));
294
295 return true;
296}
297
299
301consteval bool test_label_storage() {
303 const auto clsr_literal = Kokkos::Execution::parallel_reduce("label", 42, functor_t{}, functor_t{});
304 const auto clsr_label =
305 Kokkos::Execution::parallel_reduce(Kokkos::Execution::label("label"), 42, functor_t{}, functor_t{});
306 static_assert(std::same_as<
307 decltype(clsr_literal),
308 const stdexec::__closure<
309 Kokkos::Execution::parallel_reduce_t,
310 Kokkos::dims<1, int>,
311 functor_t,
312 functor_t,
314 >
315 >);
316 static_assert(std::same_as<
317 decltype(clsr_label),
318 const stdexec::__closure<
319 Kokkos::Execution::parallel_reduce_t,
320 Kokkos::dims<1, int>,
321 functor_t,
322 functor_t,
324 >
325 >);
326
327 return true;
328}
329
330static_assert(test_label_storage());
331
335 using reducer_t = functor_t;
336
337 const auto clsr_props = Kokkos::Execution::parallel_reduce(
338 stdexec::just(),
339 Kokkos::dims<1, int>{42},
340 functor_t{},
341 reducer_t{},
343 Utils::MyPropA{"sun"},
344 Utils::MyPropB{3.14});
345
346 static_assert(std::same_as<
347 decltype(clsr_props),
349 stdexec::just_t::__sender<>,
351 functor_t,
352 Kokkos::dims<1, int>,
353 reducer_t,
357 >
358 >
359 >);
360
361 return true;
362}
363
365
369 using just_sndr_t = decltype(stdexec::just());
370
374 using policy_t = Kokkos::RangePolicy<TEST_EXECUTION_SPACE>;
375 using reducer_t = Kokkos::View<int, TEST_EXECUTION_SPACE>;
378
380 static_assert(stdexec::__sender_for<pred_sndr_t, Kokkos::Execution::parallel_reduce_t>);
381
382 static_assert(std::same_as<stdexec::__data_of<pred_sndr_t>, pred_data_t>);
383
384 static_assert(stdexec::__nbr_children_of<pred_sndr_t> == 1);
385 static_assert(std::same_as<stdexec::__child_of<pred_sndr_t>, just_sndr_t>);
386
387 return true;
388}
389
391
393TEST(ParallelReduceTest, closure_object_creation_perfectly_forwards_functor) {
394 using counter_t = Tests::Utils::Functors::Counter;
395
396 const Kokkos::RangePolicy<TEST_EXECUTION_SPACE> policy(0, 1);
397 const Kokkos::View<int, TEST_EXECUTION_SPACE> reducer;
398 counter_t counter;
399 counter_t::reset();
400
401 [[maybe_unused]]
402 const auto closure_from_lvalue_functor = Kokkos::Execution::parallel_reduce("label", policy, counter, reducer);
403
404 ASSERT_EQ(counter_t::copy_constructions, 1);
405 ASSERT_EQ(counter_t::move_constructions, 0);
406
407 [[maybe_unused]]
408 const auto closure_from_xvalue_functor =
409 Kokkos::Execution::parallel_reduce("label", policy, std::move(counter), reducer);
410
411 ASSERT_EQ(counter_t::copy_constructions, 1);
412 ASSERT_EQ(counter_t::move_constructions, 1);
413
414 [[maybe_unused]]
415 const auto closure_from_prvalue_functor = Kokkos::Execution::parallel_reduce("label", policy, counter_t{}, reducer);
416
417 ASSERT_EQ(counter_t::copy_constructions, 1);
418 ASSERT_EQ(counter_t::move_constructions, 2);
419}
420
421} // namespace Tests
Kokkos::Execution::Impl::ParallelReduceData< functor_t, iter_space_t, reducer_t > data_t
Kokkos::range_slice< int, int > iter_space_t
Kokkos::Execution::Impl::ParallelReduceData< functor_t, iter_space_t, reducer_t, Kokkos::Execution::Impl::Label< std::string_view > > labeled_data_t
Kokkos::Execution::Impl::ParallelReduceData< functor_t, iter_space_t, reducer_t, Kokkos::Execution::Impl::Label< std::string >, std::monostate > multi_data_t
Tests::Utils::Functors::NoOp< false, false, false > functor_t
Label(T) -> Label< std::string >
consteval Impl::Label< std::string_view > label(std::string_view str) noexcept
Definition label.hpp:91
constexpr parallel_reduce_t parallel_reduce
consteval bool test_parallel_reduce_many_properties()
consteval bool test_parallel_reduce_data_size()
consteval bool test_parallel_reduce_in_constant_expression()
consteval bool test_parallel_reduce_sndr_decomposition()
consteval bool test_parallel_reduce_data_concept()
consteval bool test_parallel_reduce_data_traits()
consteval bool test_label_storage()
consteval bool test_parallel_reduce_noexcept_contract()
Type list of properties.
Count construction, move/copy construction, move/copy assignment and destruction atomically on host.
Definition counter.hpp:14