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