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