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