DDC 0.4.1
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 KOKKOS_FUNCTION void operator()(
108 [[maybe_unused]] index_type<void> unused_id,
109 typename Reducer::value_type& a) const
110
111 {
112 a = reducer(a, functor(DiscreteElement<>()));
113 }
114
115 template <std::size_t N = sizeof...(DDims), std::enable_if_t<(N > 0), bool> = true>
116 KOKKOS_FUNCTION void operator()(index_type<DDims>... ids, typename Reducer::value_type& a) const
117 {
118 a = reducer(a, functor(DiscreteElement<DDims...>(ids...)));
119 }
120};
121
122/** A parallel reduction over a nD domain using the default Kokkos execution space
123 * @param[in] label name for easy identification of the parallel_for_each algorithm
124 * @param[in] execution_space a Kokkos execution space where the loop will be executed on
125 * @param[in] domain the range over which to apply the algorithm
126 * @param[in] neutral the neutral element of the reduction operation
127 * @param[in] reduce a binary FunctionObject that will be applied in unspecified order to the
128 * results of transform, the results of other reduce and neutral.
129 * @param[in] transform a unary FunctionObject that will be applied to each element of the input
130 * range. The return type must be acceptable as input to reduce
131 */
132template <class ExecSpace, class... DDims, class T, class BinaryReductionOp, class UnaryTransformOp>
133T transform_reduce_kokkos(
134 std::string const& label,
135 ExecSpace const& execution_space,
136 DiscreteDomain<DDims...> const& domain,
137 T neutral,
138 BinaryReductionOp const& reduce,
139 UnaryTransformOp const& transform) noexcept
140{
141 T result = neutral;
142 Kokkos::parallel_reduce(
143 label,
144 ddc_to_kokkos_execution_policy(execution_space, domain),
145 TransformReducerKokkosLambdaAdapter<
146 BinaryReductionOp,
147 UnaryTransformOp,
148 DDims...>(reduce, transform),
149 ddc_to_kokkos_reducer_t<BinaryReductionOp>(result));
150 return result;
151}
152
153} // namespace detail
154
155/** A reduction over a nD domain using a given `Kokkos` execution space
156 * @param[in] label name for easy identification of the parallel_for_each algorithm
157 * @param[in] execution_space a Kokkos execution space where the loop will be executed on
158 * @param[in] domain the range over which to apply the algorithm
159 * @param[in] neutral the neutral element of the reduction operation
160 * @param[in] reduce a binary FunctionObject that will be applied in unspecified order to the
161 * results of transform, the results of other reduce and neutral.
162 * @param[in] transform a unary FunctionObject that will be applied to each element of the input
163 * range. The return type must be acceptable as input to reduce
164 */
165template <class ExecSpace, class... DDims, class T, class BinaryReductionOp, class UnaryTransformOp>
167 std::string const& label,
168 ExecSpace const& execution_space,
169 DiscreteDomain<DDims...> const& domain,
170 T neutral,
171 BinaryReductionOp&& reduce,
172 UnaryTransformOp&& transform) noexcept
173{
174 return detail::transform_reduce_kokkos(
175 label,
176 execution_space,
177 domain,
178 neutral,
179 std::forward<BinaryReductionOp>(reduce),
180 std::forward<UnaryTransformOp>(transform));
181}
182
183/** A reduction over a nD domain using a given `Kokkos` execution space
184 * @param[in] execution_space a Kokkos execution space where the loop will be executed on
185 * @param[in] domain the range over which to apply the algorithm
186 * @param[in] neutral the neutral element of the reduction operation
187 * @param[in] reduce a binary FunctionObject that will be applied in unspecified order to the
188 * results of transform, the results of other reduce and neutral.
189 * @param[in] transform a unary FunctionObject that will be applied to each element of the input
190 * range. The return type must be acceptable as input to reduce
191 */
192template <class ExecSpace, class... DDims, class T, class BinaryReductionOp, class UnaryTransformOp>
193std::enable_if_t<Kokkos::is_execution_space_v<ExecSpace>, T> parallel_transform_reduce(
194 ExecSpace const& execution_space,
195 DiscreteDomain<DDims...> const& domain,
196 T neutral,
197 BinaryReductionOp&& reduce,
198 UnaryTransformOp&& transform) noexcept
199{
200 return detail::transform_reduce_kokkos(
201 "ddc_parallel_transform_reduce_default",
202 execution_space,
203 domain,
204 neutral,
205 std::forward<BinaryReductionOp>(reduce),
206 std::forward<UnaryTransformOp>(transform));
207}
208
209/** A reduction over a nD domain using the `Kokkos` default execution space
210 * @param[in] label name for easy identification of the parallel_for_each algorithm
211 * @param[in] domain the range over which to apply the algorithm
212 * @param[in] neutral the neutral element of the reduction operation
213 * @param[in] reduce a binary FunctionObject that will be applied in unspecified order to the
214 * results of transform, the results of other reduce and neutral.
215 * @param[in] transform a unary FunctionObject that will be applied to each element of the input
216 * range. The return type must be acceptable as input to reduce
217 */
218template <class... DDims, class T, class BinaryReductionOp, class UnaryTransformOp>
220 std::string const& label,
221 DiscreteDomain<DDims...> const& domain,
222 T neutral,
223 BinaryReductionOp&& reduce,
224 UnaryTransformOp&& transform) noexcept
225{
226 return parallel_transform_reduce(
227 label,
228 Kokkos::DefaultExecutionSpace(),
229 domain,
230 neutral,
231 std::forward<BinaryReductionOp>(reduce),
232 std::forward<UnaryTransformOp>(transform));
233}
234
235/** A reduction over a nD domain using the `Kokkos` default execution space
236 * @param[in] domain the range over which to apply the algorithm
237 * @param[in] neutral the neutral element of the reduction operation
238 * @param[in] reduce a binary FunctionObject that will be applied in unspecified order to the
239 * results of transform, the results of other reduce and neutral.
240 * @param[in] transform a unary FunctionObject that will be applied to each element of the input
241 * range. The return type must be acceptable as input to reduce
242 */
243template <class... DDims, class T, class BinaryReductionOp, class UnaryTransformOp>
245 DiscreteDomain<DDims...> const& domain,
246 T neutral,
247 BinaryReductionOp&& reduce,
248 UnaryTransformOp&& transform) noexcept
249{
250 return parallel_transform_reduce(
251 "ddc_parallel_transform_reduce_default",
252 Kokkos::DefaultExecutionSpace(),
253 domain,
254 neutral,
255 std::forward<BinaryReductionOp>(reduce),
256 std::forward<UnaryTransformOp>(transform));
257}
258
259} // 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.