@@ -32,6 +32,38 @@ using cl::sycl::detail::is_sgeninteger;
32
32
using cl::sycl::detail::queue_impl;
33
33
using cl::sycl::detail::remove_AS;
34
34
35
+ // This type trait is used to detect if the atomic operation BinaryOperation
36
+ // used with operands of the type T is available for using in reduction.
37
+ // The order in which the atomic operations are performed may be arbitrary and
38
+ // thus may cause different results from run to run even on the same elements
39
+ // and on same device. The macro SYCL_REDUCTION_DETERMINISTIC prohibits using
40
+ // atomic operations for reduction and helps to produce stable results.
41
+ // SYCL_REDUCTION_DETERMINISTIC is a short term solution, which perhaps become
42
+ // deprecated eventually and is replaced by a sycl property passed to reduction.
43
+ template <typename T, class BinaryOperation >
44
+ using IsReduOptForFastAtomicFetch =
45
+ #ifdef SYCL_REDUCTION_DETERMINISTIC
46
+ bool_constant<false >;
47
+ #else
48
+ bool_constant<is_sgeninteger<T>::value &&
49
+ sycl::detail::IsValidAtomicType<T>::value &&
50
+ (sycl::detail::IsPlus<T, BinaryOperation>::value ||
51
+ sycl::detail::IsMinimum<T, BinaryOperation>::value ||
52
+ sycl::detail::IsMaximum<T, BinaryOperation>::value ||
53
+ sycl::detail::IsBitOR<T, BinaryOperation>::value ||
54
+ sycl::detail::IsBitXOR<T, BinaryOperation>::value ||
55
+ sycl::detail::IsBitAND<T, BinaryOperation>::value)>;
56
+ #endif
57
+
58
+ template <typename T, class BinaryOperation >
59
+ using IsReduOptForFastReduce =
60
+ bool_constant<((is_sgeninteger<T>::value &&
61
+ (sizeof (T) == 4 || sizeof (T) == 8 )) ||
62
+ is_sgenfloat<T>::value) &&
63
+ (sycl::detail::IsPlus<T, BinaryOperation>::value ||
64
+ sycl::detail::IsMinimum<T, BinaryOperation>::value ||
65
+ sycl::detail::IsMaximum<T, BinaryOperation>::value)>;
66
+
35
67
// std::tuple seems to be a) too heavy and b) not copyable to device now
36
68
// Thus sycl::detail::tuple is used instead.
37
69
// Switching from sycl::device::tuple to std::tuple can be done by re-defining
@@ -46,10 +78,6 @@ __SYCL_EXPORT size_t reduGetMaxWGSize(shared_ptr_class<queue_impl> Queue,
46
78
__SYCL_EXPORT size_t reduComputeWGSize (size_t NWorkItems, size_t MaxWGSize,
47
79
size_t &NWorkGroups);
48
80
49
-
50
-
51
-
52
-
53
81
// / Class that is used to represent objects that are passed to user's lambda
54
82
// / functions and representing users' reduction variable.
55
83
// / The generic version of the class represents those reductions of those
@@ -64,45 +92,45 @@ class reducer {
64
92
T getIdentity () const { return MIdentity; }
65
93
66
94
template <typename _T = T>
67
- enable_if_t <IsReduPlus <_T, BinaryOperation>::value &&
95
+ enable_if_t <sycl::detail::IsPlus <_T, BinaryOperation>::value &&
68
96
sycl::detail::is_geninteger<_T>::value>
69
97
operator ++() {
70
98
combine (static_cast <T>(1 ));
71
99
}
72
100
73
101
template <typename _T = T>
74
- enable_if_t <IsReduPlus <_T, BinaryOperation>::value &&
102
+ enable_if_t <sycl::detail::IsPlus <_T, BinaryOperation>::value &&
75
103
sycl::detail::is_geninteger<_T>::value>
76
104
operator ++(int ) {
77
105
combine (static_cast <T>(1 ));
78
106
}
79
107
80
108
template <typename _T = T>
81
- enable_if_t <IsReduPlus <_T, BinaryOperation>::value>
109
+ enable_if_t <sycl::detail::IsPlus <_T, BinaryOperation>::value>
82
110
operator +=(const _T &Partial) {
83
111
combine (Partial);
84
112
}
85
113
86
114
template <typename _T = T>
87
- enable_if_t <IsReduMultiplies <_T, BinaryOperation>::value>
115
+ enable_if_t <sycl::detail::IsMultiplies <_T, BinaryOperation>::value>
88
116
operator *=(const _T &Partial) {
89
117
combine (Partial);
90
118
}
91
119
92
120
template <typename _T = T>
93
- enable_if_t <IsReduBitOR <_T, BinaryOperation>::value>
121
+ enable_if_t <sycl::detail::IsBitOR <_T, BinaryOperation>::value>
94
122
operator |=(const _T &Partial) {
95
123
combine (Partial);
96
124
}
97
125
98
126
template <typename _T = T>
99
- enable_if_t <IsReduBitXOR <_T, BinaryOperation>::value>
127
+ enable_if_t <sycl::detail::IsBitXOR <_T, BinaryOperation>::value>
100
128
operator ^=(const _T &Partial) {
101
129
combine (Partial);
102
130
}
103
131
104
132
template <typename _T = T>
105
- enable_if_t <IsReduBitAND <_T, BinaryOperation>::value>
133
+ enable_if_t <sycl::detail::IsBitAND <_T, BinaryOperation>::value>
106
134
operator &=(const _T &Partial) {
107
135
combine (Partial);
108
136
}
@@ -150,45 +178,45 @@ class reducer<T, BinaryOperation,
150
178
}
151
179
152
180
template <typename _T = T>
153
- enable_if_t <IsReduPlus <_T, BinaryOperation>::value &&
181
+ enable_if_t <sycl::detail::IsPlus <_T, BinaryOperation>::value &&
154
182
sycl::detail::is_geninteger<_T>::value>
155
183
operator ++() {
156
184
combine (static_cast <T>(1 ));
157
185
}
158
186
159
187
template <typename _T = T>
160
- enable_if_t <IsReduPlus <_T, BinaryOperation>::value &&
188
+ enable_if_t <sycl::detail::IsPlus <_T, BinaryOperation>::value &&
161
189
sycl::detail::is_geninteger<_T>::value>
162
190
operator ++(int ) {
163
191
combine (static_cast <T>(1 ));
164
192
}
165
193
166
194
template <typename _T = T>
167
- enable_if_t <IsReduPlus <_T, BinaryOperation>::value>
195
+ enable_if_t <sycl::detail::IsPlus <_T, BinaryOperation>::value>
168
196
operator +=(const _T &Partial) {
169
197
combine (Partial);
170
198
}
171
199
172
200
template <typename _T = T>
173
- enable_if_t <IsReduMultiplies <_T, BinaryOperation>::value>
201
+ enable_if_t <sycl::detail::IsMultiplies <_T, BinaryOperation>::value>
174
202
operator *=(const _T &Partial) {
175
203
combine (Partial);
176
204
}
177
205
178
206
template <typename _T = T>
179
- enable_if_t <IsReduBitOR <_T, BinaryOperation>::value>
207
+ enable_if_t <sycl::detail::IsBitOR <_T, BinaryOperation>::value>
180
208
operator |=(const _T &Partial) {
181
209
combine (Partial);
182
210
}
183
211
184
212
template <typename _T = T>
185
- enable_if_t <IsReduBitXOR <_T, BinaryOperation>::value>
213
+ enable_if_t <sycl::detail::IsBitXOR <_T, BinaryOperation>::value>
186
214
operator ^=(const _T &Partial) {
187
215
combine (Partial);
188
216
}
189
217
190
218
template <typename _T = T>
191
- enable_if_t <IsReduBitAND <_T, BinaryOperation>::value>
219
+ enable_if_t <sycl::detail::IsBitAND <_T, BinaryOperation>::value>
192
220
operator &=(const _T &Partial) {
193
221
combine (Partial);
194
222
}
@@ -197,7 +225,7 @@ class reducer<T, BinaryOperation,
197
225
template <typename _T = T, class _BinaryOperation = BinaryOperation>
198
226
enable_if_t <std::is_same<typename remove_AS<_T>::type, T>::value &&
199
227
IsReduOptForFastAtomicFetch<T, _BinaryOperation>::value &&
200
- IsReduPlus <T, _BinaryOperation>::value>
228
+ sycl::detail::IsPlus <T, _BinaryOperation>::value>
201
229
atomic_combine (_T *ReduVarPtr) const {
202
230
atomic<T, access::address_space::global_space>(global_ptr<T>(ReduVarPtr))
203
231
.fetch_add (MValue);
@@ -207,7 +235,7 @@ class reducer<T, BinaryOperation,
207
235
template <typename _T = T, class _BinaryOperation = BinaryOperation>
208
236
enable_if_t <std::is_same<typename remove_AS<_T>::type, T>::value &&
209
237
IsReduOptForFastAtomicFetch<T, _BinaryOperation>::value &&
210
- IsReduBitOR <T, _BinaryOperation>::value>
238
+ sycl::detail::IsBitOR <T, _BinaryOperation>::value>
211
239
atomic_combine (_T *ReduVarPtr) const {
212
240
atomic<T, access::address_space::global_space>(global_ptr<T>(ReduVarPtr))
213
241
.fetch_or (MValue);
@@ -217,7 +245,7 @@ class reducer<T, BinaryOperation,
217
245
template <typename _T = T, class _BinaryOperation = BinaryOperation>
218
246
enable_if_t <std::is_same<typename remove_AS<_T>::type, T>::value &&
219
247
IsReduOptForFastAtomicFetch<T, _BinaryOperation>::value &&
220
- IsReduBitXOR <T, _BinaryOperation>::value>
248
+ sycl::detail::IsBitXOR <T, _BinaryOperation>::value>
221
249
atomic_combine (_T *ReduVarPtr) const {
222
250
atomic<T, access::address_space::global_space>(global_ptr<T>(ReduVarPtr))
223
251
.fetch_xor (MValue);
@@ -227,7 +255,7 @@ class reducer<T, BinaryOperation,
227
255
template <typename _T = T, class _BinaryOperation = BinaryOperation>
228
256
enable_if_t <std::is_same<typename remove_AS<_T>::type, T>::value &&
229
257
IsReduOptForFastAtomicFetch<T, _BinaryOperation>::value &&
230
- IsReduBitAND <T, _BinaryOperation>::value>
258
+ sycl::detail::IsBitAND <T, _BinaryOperation>::value>
231
259
atomic_combine (_T *ReduVarPtr) const {
232
260
atomic<T, access::address_space::global_space>(global_ptr<T>(ReduVarPtr))
233
261
.fetch_and (MValue);
@@ -237,7 +265,7 @@ class reducer<T, BinaryOperation,
237
265
template <typename _T = T, class _BinaryOperation = BinaryOperation>
238
266
enable_if_t <std::is_same<typename remove_AS<_T>::type, T>::value &&
239
267
IsReduOptForFastAtomicFetch<T, _BinaryOperation>::value &&
240
- IsReduMinimum <T, _BinaryOperation>::value>
268
+ sycl::detail::IsMinimum <T, _BinaryOperation>::value>
241
269
atomic_combine (_T *ReduVarPtr) const {
242
270
atomic<T, access::address_space::global_space>(global_ptr<T>(ReduVarPtr))
243
271
.fetch_min (MValue);
@@ -247,7 +275,7 @@ class reducer<T, BinaryOperation,
247
275
template <typename _T = T, class _BinaryOperation = BinaryOperation>
248
276
enable_if_t <std::is_same<typename remove_AS<_T>::type, T>::value &&
249
277
IsReduOptForFastAtomicFetch<T, _BinaryOperation>::value &&
250
- IsReduMaximum <T, _BinaryOperation>::value>
278
+ sycl::detail::IsMaximum <T, _BinaryOperation>::value>
251
279
atomic_combine (_T *ReduVarPtr) const {
252
280
atomic<T, access::address_space::global_space>(global_ptr<T>(ReduVarPtr))
253
281
.fetch_max (MValue);
0 commit comments