kokkos-execution 0.0.1
Loading...
Searching...
No Matches
test_parallel_for.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_for(42, functor_t{});
35
36 [[maybe_unused]]
37 const auto sndr_b = Kokkos::Execution::parallel_for(Kokkos::range_slice<size_t, size_t>{42, 43}, functor_t{});
38
39 return std::is_constant_evaluated();
40}
41
43
64
74
75static_assert(test_parallel_for_data_concept());
76
80 static_assert(std::is_aggregate_v<typename ParallelForDataTest::data_t>);
81 static_assert(std::is_aggregate_v<typename ParallelForDataTest::labeled_data_t>);
82 static_assert(std::is_aggregate_v<typename ParallelForDataTest::multi_data_t>);
83
85 static_assert(std::is_nothrow_move_constructible_v<typename ParallelForDataTest::data_t>);
86 static_assert(std::is_nothrow_move_constructible_v<typename ParallelForDataTest::labeled_data_t>);
87 static_assert(std::is_nothrow_move_constructible_v<typename ParallelForDataTest::multi_data_t>);
88
90 static_assert(
91 std::same_as<typename ParallelForDataTest::data_t::functor_t, typename ParallelForDataTest::functor_t>);
92 static_assert(std::same_as<
95 >);
96 static_assert(
97 std::same_as<typename ParallelForDataTest::data_t::properties_t, Kokkos::Execution::Impl::properties<>>);
98 static_assert(std::same_as<
101 >);
102
106
107 return true;
108}
109
110static_assert(test_parallel_for_data_traits());
111
114 static_assert(sizeof(typename ParallelForDataTest::functor_t) == 1);
115 static_assert(std::alignment_of_v<typename ParallelForDataTest::functor_t> == 1);
116
117 static_assert(sizeof(typename ParallelForDataTest::iter_space_t) == 8);
118 static_assert(std::alignment_of_v<typename ParallelForDataTest::iter_space_t> == 4);
119
120 static_assert(std::is_empty_v<typename ParallelForDataTest::functor_t>);
121 static_assert(std::is_standard_layout_v<typename ParallelForDataTest::data_t>);
122
123 static_assert(offsetof(typename ParallelForDataTest::data_t, functor) == 0);
124 static_assert(offsetof(typename ParallelForDataTest::data_t, policy_or_iter_space) == 4);
125
126 static_assert(sizeof(typename ParallelForDataTest::data_t) == 12);
127 static_assert(sizeof(typename ParallelForDataTest::labeled_data_t) == 32);
128
129 return true;
130}
131
132static_assert(test_parallel_for_data_size());
133
135TEST_F(ParallelForDataTest, transform_policy_or_iter_space) {
136 using labeled_data_iter_space_t = Kokkos::Execution::Impl::ParallelForData<
137 functor_t,
140 >;
141
142 using labeled_data_range_policy_t = Kokkos::Execution::Impl::ParallelForData<
143 functor_t,
144 Kokkos::RangePolicy<TEST_EXECUTION_SPACE>,
146 >;
147
148 constexpr labeled_data_iter_space_t with_iter_space{
150 functor_t{},
151 iter_space_t{4, 6}
152 };
153
154 const auto with_range_policy = with_iter_space.transform_policy_or_iter_space(
155 [](const auto& pol) { return Kokkos::RangePolicy<TEST_EXECUTION_SPACE>(pol.first, pol.last); });
156
157 static_assert(std::same_as<decltype(with_range_policy), const labeled_data_range_policy_t>);
158
159 ASSERT_EQ(with_range_policy.policy_or_iter_space.begin(), 4);
160 ASSERT_EQ(with_range_policy.policy_or_iter_space.end(), 6);
161}
162
169TEST_F(ParallelForDataTest, transform_policy_or_iter_space_perfectly_forwards_properties) {
170 using counter_t = Tests::Utils::Functors::Counter;
172
173 counter_t::reset();
174 {
175 data_with_counter_t from_xvalue{counter_t{}, counter_t{}, iter_space_t{}};
176 [[maybe_unused]]
177 const auto data_from_xvalue = std::move(from_xvalue).transform_policy_or_iter_space([](const auto&) {
178 return iter_space_t{4, 6};
179 });
180 ASSERT_EQ(counter_t::copy_assignments, 0);
181 ASSERT_EQ(counter_t::copy_constructions, 0);
182 ASSERT_EQ(counter_t::move_assignments, 0);
183#if defined(KOKKOS_COMPILER_CLANG) || defined(KOKKOS_COMPILER_INTEL_LLVM)
184 ASSERT_EQ(counter_t::move_constructions, 3);
185#else
186 ASSERT_EQ(counter_t::move_constructions, 2);
187#endif
188 }
189
190 counter_t::reset();
191 {
192 [[maybe_unused]]
193 const auto data_from_prvalue = data_with_counter_t{counter_t{}, counter_t{}, iter_space_t{}}
194 .transform_policy_or_iter_space(
195 [](const auto&) { return iter_space_t{4, 6}; });
196 ASSERT_EQ(counter_t::copy_assignments, 0);
197 ASSERT_EQ(counter_t::copy_constructions, 0);
198 ASSERT_EQ(counter_t::move_assignments, 0);
199#if defined(KOKKOS_COMPILER_CLANG) || defined(KOKKOS_COMPILER_INTEL_LLVM)
200 ASSERT_EQ(counter_t::move_constructions, 3);
201#else
202 ASSERT_EQ(counter_t::move_constructions, 2);
203#endif
204 }
205}
206
209 using label_t = std::string;
210 using policy_t = Kokkos::RangePolicy<TEST_EXECUTION_SPACE>;
211
212 static_assert(noexcept(Kokkos::Execution::parallel_for(
213 std::declval<label_t>(),
214 std::declval<policy_t>(),
216
217 static_assert(!noexcept(Kokkos::Execution::parallel_for(
218 std::declval<const label_t&>(),
219 std::declval<policy_t>(),
221
222 static_assert(!noexcept(Kokkos::Execution::parallel_for(
223 std::declval<const char*>(),
224 std::declval<policy_t>(),
226
227 static_assert(!noexcept(Kokkos::Execution::parallel_for(
228 std::declval<label_t>(),
229 std::declval<policy_t>(),
231
232 static_assert(!noexcept(Kokkos::Execution::parallel_for(
233 std::declval<label_t>(),
234 std::declval<policy_t>(),
236
237 static_assert(noexcept(
238 stdexec::just()
240 std::declval<label_t>(),
241 std::declval<policy_t>(),
243
244 static_assert(!noexcept(
245 stdexec::just()
247 std::declval<const label_t&>(),
248 std::declval<policy_t>(),
250
252 using label_of_string_t = Kokkos::Execution::Impl::Label<std::string>;
253
254 static_assert(noexcept(Kokkos::Execution::parallel_for(
255 stdexec::just(),
256 std::declval<policy_t>(),
258 std::declval<label_of_string_t>())));
259
260 static_assert(!noexcept(Kokkos::Execution::parallel_for(
261 stdexec::just(),
262 std::declval<policy_t>(),
264 std::declval<const label_of_string_t&>())));
265
266 return true;
267}
268
270
272consteval bool test_label_storage() {
274 const auto clsr_literal = Kokkos::Execution::parallel_for("label", 42, functor_t{});
275 const auto clsr_label = Kokkos::Execution::parallel_for(Kokkos::Execution::label("label"), 42, functor_t{});
276 static_assert(std::same_as<
277 decltype(clsr_literal),
278 const stdexec::__closure<
280 Kokkos::dims<1, int>,
281 functor_t,
283 >
284 >);
285 static_assert(std::same_as<
286 decltype(clsr_label),
287 const stdexec::__closure<
289 Kokkos::dims<1, int>,
290 functor_t,
292 >
293 >);
294
295 return true;
296}
297
298static_assert(test_label_storage());
299
303
304 const auto clsr_props = Kokkos::Execution::parallel_for(
305 stdexec::just(),
306 Kokkos::dims<1, int>{42},
307 functor_t{},
309 Utils::MyPropA{"sun"},
310 Utils::MyPropB{3.14});
311
312 static_assert(std::same_as<
313 decltype(clsr_props),
315 stdexec::just_t::__sender<>,
317 functor_t,
318 Kokkos::dims<1, int>,
322 >
323 >
324 >);
325
326 return true;
327}
328
329static_assert(test_parallel_for_many_properties());
330
334 using just_sndr_t = decltype(stdexec::just());
335
337 using label_t = std::string;
339 using policy_t = Kokkos::RangePolicy<TEST_EXECUTION_SPACE>;
342
344 static_assert(stdexec::__sender_for<pfor_sndr_t, Kokkos::Execution::parallel_for_t>);
345
346 static_assert(std::same_as<stdexec::__data_of<pfor_sndr_t>, pfor_data_t>);
347
348 static_assert(stdexec::__nbr_children_of<pfor_sndr_t> == 1);
349 static_assert(std::same_as<stdexec::__child_of<pfor_sndr_t>, just_sndr_t>);
350
351 return true;
352}
353
355
357TEST(ParallelForTest, closure_object_creation_perfectly_forwards_functor) {
358 using counter_t = Tests::Utils::Functors::Counter;
359
360 const Kokkos::RangePolicy<TEST_EXECUTION_SPACE> policy(0, 1);
361 counter_t counter;
362 counter_t::reset();
363
364 [[maybe_unused]]
365 const auto closure_from_lvalue_functor = Kokkos::Execution::parallel_for("label", policy, counter);
366
367 ASSERT_EQ(counter_t::copy_constructions, 1);
368 ASSERT_EQ(counter_t::move_constructions, 0);
369
370 [[maybe_unused]]
371 const auto closure_from_xvalue_functor = Kokkos::Execution::parallel_for("label", policy, std::move(counter));
372
373 ASSERT_EQ(counter_t::copy_constructions, 1);
374 ASSERT_EQ(counter_t::move_constructions, 1);
375
376 [[maybe_unused]]
377 const auto closure_from_prvalue_functor = Kokkos::Execution::parallel_for("label", policy, counter_t{});
378
379 ASSERT_EQ(counter_t::copy_constructions, 1);
380 ASSERT_EQ(counter_t::move_constructions, 2);
381}
382
383} // namespace Tests
Kokkos::Execution::Impl::ParallelForData< functor_t, iter_space_t > data_t
Tests::Utils::Functors::NoOp< false, false, false > functor_t
Kokkos::range_slice< int, int > iter_space_t
Kokkos::Execution::Impl::ParallelForData< functor_t, iter_space_t, Kokkos::Execution::Impl::Label< std::string_view > > labeled_data_t
Kokkos::Execution::Impl::ParallelForData< functor_t, iter_space_t, Kokkos::Execution::Impl::Label< std::string >, std::monostate > multi_data_t
consteval Impl::Label< std::string_view > label(std::string_view str) noexcept
Definition label.hpp:91
constexpr parallel_for_t parallel_for
consteval bool test_parallel_for_sndr_decomposition()
consteval bool test_parallel_for_noexcept_contract()
consteval bool test_parallel_for_in_constant_expression()
consteval bool test_parallel_for_data_size()
consteval bool test_parallel_for_data_traits()
consteval bool test_parallel_for_data_concept()
consteval bool test_label_storage()
consteval bool test_parallel_for_many_properties()
Type list of properties.
Custom algorithm for the Kokkos::parallel_for construct.
Count construction, move/copy construction, move/copy assignment and destruction atomically on host.
Definition counter.hpp:14