DDC 0.1.0
Loading...
Searching...
No Matches
parallel_transform_reduce.hpp
1// Copyright (C) The DDC development team, see COPYRIGHT.md file
2//
3// SPDX-License-Identifier: MIT
4
5#pragma once
6
7#include <cstddef>
8#include <string>
9#include <type_traits>
10#include <utility>
11
12#include <Kokkos_Core.hpp>
13
14#include "ddc/ddc_to_kokkos_execution_policy.hpp"
15#include "ddc/detail/kokkos.hpp"
16#include "ddc/discrete_domain.hpp"
17#include "ddc/discrete_element.hpp"
18#include "ddc/reducer.hpp"
19
20namespace ddc {
21
22namespace detail {
23
24template <class Reducer>
25struct ddc_to_kokkos_reducer;
26
27template <class T>
28struct ddc_to_kokkos_reducer<reducer::sum<T>>
29{
30 using type = Kokkos::Sum<T>;
31};
32
33template <class T>
34struct ddc_to_kokkos_reducer<reducer::prod<T>>
35{
36 using type = Kokkos::Prod<T>;
37};
38
39template <class T>
40struct ddc_to_kokkos_reducer<reducer::land<T>>
41{
42 using type = Kokkos::LAnd<T>;
43};
44
45template <class T>
46struct ddc_to_kokkos_reducer<reducer::lor<T>>
47{
48 using type = Kokkos::LOr<T>;
49};
50
51template <class T>
52struct ddc_to_kokkos_reducer<reducer::band<T>>
53{
54 using type = Kokkos::BAnd<T>;
55};
56
57template <class T>
58struct ddc_to_kokkos_reducer<reducer::bor<T>>
59{
60 using type = Kokkos::BOr<T>;
61};
62
63template <class T>
64struct ddc_to_kokkos_reducer<reducer::bxor<T>>
65{
66 static_assert(std::is_same_v<T, T>, "This reducer is not yet implemented");
67};
68
69template <class T>
70struct ddc_to_kokkos_reducer<reducer::min<T>>
71{
72 using type = Kokkos::Min<T>;
73};
74
75template <class T>
76struct ddc_to_kokkos_reducer<reducer::max<T>>
77{
78 using type = Kokkos::Max<T>;
79};
80
81template <class T>
82struct ddc_to_kokkos_reducer<reducer::minmax<T>>
83{
84 using type = Kokkos::MinMax<T>;
85};
86
87/// Alias template to transform a DDC reducer type to a Kokkos reducer type
88template <class Reducer>
89using ddc_to_kokkos_reducer_t = typename ddc_to_kokkos_reducer<Reducer>::type;
90
91template <class Reducer, class Functor, class... DDims>
92class TransformReducerKokkosLambdaAdapter
93{
94 template <class T>
95 using index_type = DiscreteElementType;
96
97 Reducer reducer;
98
99 Functor functor;
100
101public:
102 TransformReducerKokkosLambdaAdapter(Reducer const& r, Functor const& f) : reducer(r), functor(f)
103 {
104 }
105
106 template <std::size_t N = sizeof...(DDims), std::enable_if_t<(N == 0), bool> = true>
107 void operator()([[maybe_unused]] index_type<void> unused_id, typename Reducer::value_type& a)
108 const
109 {
110 a = reducer(a, functor(DiscreteElement<>()));
111 }
112
113 template <std::size_t N = sizeof...(DDims), std::enable_if_t<(N == 0), bool> = true>
114 KOKKOS_FUNCTION void operator()(
115 use_annotated_operator,
116 [[maybe_unused]] index_type<void> unused_id,
117 typename Reducer::value_type& a) const
118
119 {
120 a = reducer(a, functor(DiscreteElement<>()));
121 }
122
123 template <std::size_t N = sizeof...(DDims), std::enable_if_t<(N > 0), bool> = true>
124 void operator()(index_type<DDims>... ids, typename Reducer::value_type& a) const
125 {
126 a = reducer(a, functor(DiscreteElement<DDims...>(ids...)));
127 }
128
129
130 template <std::size_t N = sizeof...(DDims), std::enable_if_t<(N > 0), bool> = true>
131 KOKKOS_FUNCTION void operator()(
132 use_annotated_operator,
133 index_type<DDims>... ids,
134 typename Reducer::value_type& a) const
135 {
136 a = reducer(a, functor(DiscreteElement<DDims...>(ids...)));
137 }
138};
139
140/** A parallel reduction over a nD domain using the default Kokkos execution space
141 * @param[in] label name for easy identification of the parallel_for_each algorithm
142 * @param[in] execution_space a Kokkos execution space where the loop will be executed on
143 * @param[in] domain the range over which to apply the algorithm
144 * @param[in] neutral the neutral element of the reduction operation
145 * @param[in] reduce a binary FunctionObject that will be applied in unspecified order to the
146 * results of transform, the results of other reduce and neutral.
147 * @param[in] transform a unary FunctionObject that will be applied to each element of the input
148 * range. The return type must be acceptable as input to reduce
149 */
150template <class ExecSpace, class... DDims, class T, class BinaryReductionOp, class UnaryTransformOp>
151T transform_reduce_kokkos(
152 std::string const& label,
153 ExecSpace const& execution_space,
154 DiscreteDomain<DDims...> const& domain,
155 T neutral,
156 BinaryReductionOp const& reduce,
157 UnaryTransformOp const& transform) noexcept
158{
159 T result = neutral;
160 Kokkos::parallel_reduce(
161 label,
162 ddc_to_kokkos_execution_policy(execution_space, domain),
163 TransformReducerKokkosLambdaAdapter<
164 BinaryReductionOp,
165 UnaryTransformOp,
166 DDims...>(reduce, transform),
167 ddc_to_kokkos_reducer_t<BinaryReductionOp>(result));
168 return result;
169}
170
171} // namespace detail
172
173/** A reduction over a nD domain using a given `Kokkos` execution space
174 * @param[in] label name for easy identification of the parallel_for_each algorithm
175 * @param[in] execution_space a Kokkos execution space where the loop will be executed on
176 * @param[in] domain the range over which to apply the algorithm
177 * @param[in] neutral the neutral element of the reduction operation
178 * @param[in] reduce a binary FunctionObject that will be applied in unspecified order to the
179 * results of transform, the results of other reduce and neutral.
180 * @param[in] transform a unary FunctionObject that will be applied to each element of the input
181 * range. The return type must be acceptable as input to reduce
182 */
183template <class ExecSpace, class... DDims, class T, class BinaryReductionOp, class UnaryTransformOp>
185 std::string const& label,
186 ExecSpace const& execution_space,
187 DiscreteDomain<DDims...> const& domain,
188 T neutral,
189 BinaryReductionOp&& reduce,
190 UnaryTransformOp&& transform) noexcept
191{
192 return detail::transform_reduce_kokkos(
193 label,
194 execution_space,
195 domain,
196 neutral,
197 std::forward<BinaryReductionOp>(reduce),
198 std::forward<UnaryTransformOp>(transform));
199}
200
201/** A reduction over a nD domain using a given `Kokkos` execution space
202 * @param[in] execution_space a Kokkos execution space where the loop will be executed on
203 * @param[in] domain the range over which to apply the algorithm
204 * @param[in] neutral the neutral element of the reduction operation
205 * @param[in] reduce a binary FunctionObject that will be applied in unspecified order to the
206 * results of transform, the results of other reduce and neutral.
207 * @param[in] transform a unary FunctionObject that will be applied to each element of the input
208 * range. The return type must be acceptable as input to reduce
209 */
210template <class ExecSpace, class... DDims, class T, class BinaryReductionOp, class UnaryTransformOp>
211std::enable_if_t<Kokkos::is_execution_space_v<ExecSpace>, T> parallel_transform_reduce(
212 ExecSpace const& execution_space,
213 DiscreteDomain<DDims...> const& domain,
214 T neutral,
215 BinaryReductionOp&& reduce,
216 UnaryTransformOp&& transform) noexcept
217{
218 return detail::transform_reduce_kokkos(
219 "ddc_parallel_transform_reduce_default",
220 execution_space,
221 domain,
222 neutral,
223 std::forward<BinaryReductionOp>(reduce),
224 std::forward<UnaryTransformOp>(transform));
225}
226
227/** A reduction over a nD domain using the `Kokkos` default execution space
228 * @param[in] label name for easy identification of the parallel_for_each algorithm
229 * @param[in] domain the range over which to apply the algorithm
230 * @param[in] neutral the neutral element of the reduction operation
231 * @param[in] reduce a binary FunctionObject that will be applied in unspecified order to the
232 * results of transform, the results of other reduce and neutral.
233 * @param[in] transform a unary FunctionObject that will be applied to each element of the input
234 * range. The return type must be acceptable as input to reduce
235 */
236template <class... DDims, class T, class BinaryReductionOp, class UnaryTransformOp>
238 std::string const& label,
239 DiscreteDomain<DDims...> const& domain,
240 T neutral,
241 BinaryReductionOp&& reduce,
242 UnaryTransformOp&& transform) noexcept
243{
244 return parallel_transform_reduce(
245 label,
246 Kokkos::DefaultExecutionSpace(),
247 domain,
248 neutral,
249 std::forward<BinaryReductionOp>(reduce),
250 std::forward<UnaryTransformOp>(transform));
251}
252
253/** A reduction over a nD domain using the `Kokkos` default execution space
254 * @param[in] domain the range over which to apply the algorithm
255 * @param[in] neutral the neutral element of the reduction operation
256 * @param[in] reduce a binary FunctionObject that will be applied in unspecified order to the
257 * results of transform, the results of other reduce and neutral.
258 * @param[in] transform a unary FunctionObject that will be applied to each element of the input
259 * range. The return type must be acceptable as input to reduce
260 */
261template <class... DDims, class T, class BinaryReductionOp, class UnaryTransformOp>
263 DiscreteDomain<DDims...> const& domain,
264 T neutral,
265 BinaryReductionOp&& reduce,
266 UnaryTransformOp&& transform) noexcept
267{
268 return parallel_transform_reduce(
269 "ddc_parallel_transform_reduce_default",
270 Kokkos::DefaultExecutionSpace(),
271 domain,
272 neutral,
273 std::forward<BinaryReductionOp>(reduce),
274 std::forward<UnaryTransformOp>(transform));
275}
276
277} // namespace ddc
friend class DiscreteDomain
KOKKOS_DEFAULTED_FUNCTION constexpr DiscreteElement()=default
The top-level namespace of DDC.
std::enable_if_t< Kokkos::is_execution_space_v< ExecSpace >, T > parallel_transform_reduce(ExecSpace const &execution_space, DiscreteDomain< DDims... > const &domain, T neutral, BinaryReductionOp &&reduce, UnaryTransformOp &&transform) noexcept
A reduction over a nD domain using a given Kokkos execution space.
T parallel_transform_reduce(std::string const &label, DiscreteDomain< DDims... > const &domain, T neutral, BinaryReductionOp &&reduce, UnaryTransformOp &&transform) noexcept
A reduction over a nD domain using the Kokkos default execution space.
T parallel_transform_reduce(std::string const &label, ExecSpace const &execution_space, DiscreteDomain< DDims... > const &domain, T neutral, BinaryReductionOp &&reduce, UnaryTransformOp &&transform) noexcept
A reduction over a nD domain using a given Kokkos execution space.
T parallel_transform_reduce(DiscreteDomain< DDims... > const &domain, T neutral, BinaryReductionOp &&reduce, UnaryTransformOp &&transform) noexcept
A reduction over a nD domain using the Kokkos default execution space.