Skip to content

Commit 863383b

Browse files
authored
[SYCL] Add reduction overloads accepting span (#6019)
A new static member function "num_elements" is added to all reduction specializations to distinguish between scalar reductions and array reductions. A scalar reduction (all existing implementations of reduction) always has (num_elements == 1); an array reduction (this new specialization) has (num_elements == Extent), where Extent is the extent of the span. If (num_elements > 1), the implementation currently reduces each element separately. This allows array reductions to use the same amount of work-group local memory as a scalar reduction using the same T, but at the expense of additional synchronization calls. The notion of a reducer's "dimensionality" is now tied to the dimensionality of the reduction being performed (i.e. 0 for scalars, 1 for spans) and not to the dimensionality of the input accessor/buffer. This will simplify extending reductions to true multi-dimensional array reductions (i.e. with md_span). In future, the code handling the reduction packs could be generalized to handle more reduction/reducer types while making fewer assumptions about the reduction algorithm. Signed-off-by: John Pennycook [email protected]
1 parent da017f8 commit 863383b

File tree

4 files changed

+1283
-631
lines changed

4 files changed

+1283
-631
lines changed

sycl/include/CL/sycl/handler.hpp

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -240,9 +240,9 @@ class RoundedRangeKernelWithKH {
240240
namespace ext {
241241
namespace oneapi {
242242
namespace detail {
243-
template <typename T, class BinaryOperation, int Dims, bool IsUSM,
244-
access::placeholder IsPlaceholder>
245-
class reduction_impl;
243+
template <typename T, class BinaryOperation, int Dims, size_t Extent,
244+
class Algorithm>
245+
class reduction_impl_algo;
246246

247247
using cl::sycl::detail::enable_if_t;
248248
using cl::sycl::detail::queue_impl;
@@ -2682,11 +2682,11 @@ class __SYCL_EXPORT handler {
26822682
// Make stream class friend to be able to keep the list of associated streams
26832683
friend class stream;
26842684
friend class detail::stream_impl;
2685-
// Make reduction_impl friend to store buffers and arrays created for it
2686-
// in handler from reduction_impl methods.
2687-
template <typename T, class BinaryOperation, int Dims, bool IsUSM,
2688-
access::placeholder IsPlaceholder>
2689-
friend class ext::oneapi::detail::reduction_impl;
2685+
// Make reduction friends to store buffers and arrays created for it
2686+
// in handler from reduction methods.
2687+
template <typename T, class BinaryOperation, int Dims, size_t Extent,
2688+
class Algorithm>
2689+
friend class ext::oneapi::detail::reduction_impl_algo;
26902690

26912691
// This method needs to call the method finalize().
26922692
template <typename Reduction, typename... RestT>

sycl/include/CL/sycl/reduction.hpp

Lines changed: 80 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,9 @@ namespace sycl {
2020
template <typename T, typename AllocatorT, typename BinaryOperation>
2121
std::enable_if_t<has_known_identity<BinaryOperation, T>::value,
2222
ext::oneapi::detail::reduction_impl<
23-
T, BinaryOperation, 1, false, access::placeholder::true_t>>
23+
T, BinaryOperation, 0, 1,
24+
ext::oneapi::detail::default_reduction_algorithm<
25+
false, access::placeholder::true_t, 1>>>
2426
reduction(buffer<T, 1, AllocatorT> Var, handler &CGH, BinaryOperation,
2527
const property_list &PropList = {}) {
2628
bool InitializeToIdentity =
@@ -35,7 +37,9 @@ reduction(buffer<T, 1, AllocatorT> Var, handler &CGH, BinaryOperation,
3537
template <typename T, typename AllocatorT, typename BinaryOperation>
3638
std::enable_if_t<!has_known_identity<BinaryOperation, T>::value,
3739
ext::oneapi::detail::reduction_impl<
38-
T, BinaryOperation, 1, false, access::placeholder::true_t>>
40+
T, BinaryOperation, 0, 1,
41+
ext::oneapi::detail::default_reduction_algorithm<
42+
false, access::placeholder::true_t, 1>>>
3943
reduction(buffer<T, 1, AllocatorT>, handler &, BinaryOperation,
4044
const property_list &PropList = {}) {
4145
// TODO: implement reduction that works even when identity is not known.
@@ -49,9 +53,11 @@ reduction(buffer<T, 1, AllocatorT>, handler &, BinaryOperation,
4953
/// the given USM pointer \p Var, handler \p CGH, reduction operation
5054
/// \p Combiner, and optional reduction properties.
5155
template <typename T, typename BinaryOperation>
52-
std::enable_if_t<
53-
has_known_identity<BinaryOperation, T>::value,
54-
ext::oneapi::detail::reduction_impl<T, BinaryOperation, 1, true>>
56+
std::enable_if_t<has_known_identity<BinaryOperation, T>::value,
57+
ext::oneapi::detail::reduction_impl<
58+
T, BinaryOperation, 0, 1,
59+
ext::oneapi::detail::default_reduction_algorithm<
60+
true, access::placeholder::false_t, 1>>>
5561
reduction(T *Var, BinaryOperation, const property_list &PropList = {}) {
5662
bool InitializeToIdentity =
5763
PropList.has_property<property::reduction::initialize_to_identity>();
@@ -64,9 +70,11 @@ reduction(T *Var, BinaryOperation, const property_list &PropList = {}) {
6470
/// The reduction algorithm may be less efficient for this variant as the
6571
/// reduction identity is not known statically and it is not provided by user.
6672
template <typename T, typename BinaryOperation>
67-
std::enable_if_t<
68-
!has_known_identity<BinaryOperation, T>::value,
69-
ext::oneapi::detail::reduction_impl<T, BinaryOperation, 1, true>>
73+
std::enable_if_t<!has_known_identity<BinaryOperation, T>::value,
74+
ext::oneapi::detail::reduction_impl<
75+
T, BinaryOperation, 0, 1,
76+
ext::oneapi::detail::default_reduction_algorithm<
77+
true, access::placeholder::false_t, 1>>>
7078
reduction(T *, BinaryOperation, const property_list &PropList = {}) {
7179
// TODO: implement reduction that works even when identity is not known.
7280
(void)PropList;
@@ -79,8 +87,10 @@ reduction(T *, BinaryOperation, const property_list &PropList = {}) {
7987
/// reduction identity value \p Identity, reduction operation \p Combiner,
8088
/// and optional reduction properties.
8189
template <typename T, typename AllocatorT, typename BinaryOperation>
82-
ext::oneapi::detail::reduction_impl<T, BinaryOperation, 1, false,
83-
access::placeholder::true_t>
90+
ext::oneapi::detail::reduction_impl<
91+
T, BinaryOperation, 0, 1,
92+
ext::oneapi::detail::default_reduction_algorithm<
93+
false, access::placeholder::true_t, 1>>
8494
reduction(buffer<T, 1, AllocatorT> Var, handler &CGH, const T &Identity,
8595
BinaryOperation Combiner, const property_list &PropList = {}) {
8696
bool InitializeToIdentity =
@@ -92,13 +102,72 @@ reduction(buffer<T, 1, AllocatorT> Var, handler &CGH, const T &Identity,
92102
/// the given USM pointer \p Var, reduction identity value \p Identity,
93103
/// binary operation \p Combiner, and optional reduction properties.
94104
template <typename T, typename BinaryOperation>
95-
ext::oneapi::detail::reduction_impl<T, BinaryOperation, 1, true>
105+
ext::oneapi::detail::reduction_impl<
106+
T, BinaryOperation, 0, 1,
107+
ext::oneapi::detail::default_reduction_algorithm<
108+
true, access::placeholder::false_t, 1>>
96109
reduction(T *Var, const T &Identity, BinaryOperation Combiner,
97110
const property_list &PropList = {}) {
98111
bool InitializeToIdentity =
99112
PropList.has_property<property::reduction::initialize_to_identity>();
100113
return {Var, Identity, Combiner, InitializeToIdentity};
101114
}
102115

116+
#if __cplusplus >= 201703L
117+
/// Constructs a reduction object using the reduction variable referenced by
118+
/// the given sycl::span \p Span, reduction operation \p Combiner, and
119+
/// optional reduction properties.
120+
template <typename T, size_t Extent, typename BinaryOperation>
121+
std::enable_if_t<Extent != dynamic_extent &&
122+
has_known_identity<BinaryOperation, T>::value,
123+
ext::oneapi::detail::reduction_impl<
124+
T, BinaryOperation, 1, Extent,
125+
ext::oneapi::detail::default_reduction_algorithm<
126+
true, access::placeholder::false_t, 1>>>
127+
reduction(span<T, Extent> Span, BinaryOperation,
128+
const property_list &PropList = {}) {
129+
bool InitializeToIdentity =
130+
PropList.has_property<property::reduction::initialize_to_identity>();
131+
return {Span, InitializeToIdentity};
132+
}
133+
134+
/// Constructs a reduction object using the reduction variable referenced by
135+
/// the given sycl::span \p Span, reduction operation \p Combiner, and
136+
/// optional reduction properties.
137+
/// The reduction algorithm may be less efficient for this variant as the
138+
/// reduction identity is not known statically and it is not provided by user.
139+
template <typename T, size_t Extent, typename BinaryOperation>
140+
std::enable_if_t<Extent != dynamic_extent &&
141+
!has_known_identity<BinaryOperation, T>::value,
142+
ext::oneapi::detail::reduction_impl<
143+
T, BinaryOperation, 1, Extent,
144+
ext::oneapi::detail::default_reduction_algorithm<
145+
true, access::placeholder::false_t, 1>>>
146+
reduction(span<T, Extent> Span, BinaryOperation,
147+
const property_list &PropList = {}) {
148+
// TODO: implement reduction that works even when identity is not known.
149+
(void)PropList;
150+
throw runtime_error("Identity-less reductions with unknown identity are not "
151+
"supported yet.",
152+
PI_INVALID_VALUE);
153+
}
154+
155+
/// Constructs a reduction object using the reduction variable referenced by
156+
/// the given sycl::span \p Span, reduction identity value \p Identity,
157+
/// reduction operation \p Combiner, and optional reduction properties.
158+
template <typename T, size_t Extent, typename BinaryOperation>
159+
std::enable_if_t<Extent != dynamic_extent,
160+
ext::oneapi::detail::reduction_impl<
161+
T, BinaryOperation, 1, Extent,
162+
ext::oneapi::detail::default_reduction_algorithm<
163+
true, access::placeholder::false_t, 1>>>
164+
reduction(span<T, Extent> Span, const T &Identity, BinaryOperation Combiner,
165+
const property_list &PropList = {}) {
166+
bool InitializeToIdentity =
167+
PropList.has_property<property::reduction::initialize_to_identity>();
168+
return {Span, Identity, Combiner, InitializeToIdentity};
169+
}
170+
#endif
171+
103172
} // namespace sycl
104173
} // __SYCL_INLINE_NAMESPACE(cl)

0 commit comments

Comments
 (0)