29
29
using namespace sycl ;
30
30
using namespace sycl ::ext::intel;
31
31
32
+ #ifdef SATURATION_ON
33
+ #define ESIMD_SATURATION_TAG \
34
+ esimd::saturation_on_tag {}
35
+ #define ESIMD_SATURATE (T, x ) esimd::saturate<T>(x)
36
+ #define HOST_SATURATE (x ) std::max(0 .0f , std::min((x), 1 .0f ))
37
+ #else
38
+ #define ESIMD_SATURATION_TAG \
39
+ esimd::saturation_off_tag {}
40
+ #define ESIMD_SATURATE (T, x ) (x)
41
+ #define HOST_SATURATE (x ) (x)
42
+ #endif
43
+
32
44
// --- Data initialization functions
33
45
34
46
// Initialization data for trigonometric functions' input.
@@ -105,22 +117,17 @@ enum class MathOp {
105
117
106
118
// --- Template functions calculating given math operation on host and device
107
119
108
- enum ArgKind {
109
- AllVec,
110
- AllSca,
111
- Sca1Vec2,
112
- Sca2Vec1
113
- };
120
+ enum ArgKind { AllVec, AllSca, Sca1Vec2, Sca2Vec1 };
114
121
115
- template <class T , int N, MathOp Op, int Args= AllVec> struct ESIMDf ;
116
- template <class T , int N, MathOp Op, int Args= AllVec> struct BinESIMDf ;
117
- template <class T , int N, MathOp Op, int Args= AllVec> struct SYCLf ;
122
+ template <class T , int N, MathOp Op, int Args = AllVec> struct ESIMDf ;
123
+ template <class T , int N, MathOp Op, int Args = AllVec> struct BinESIMDf ;
124
+ template <class T , int N, MathOp Op, int Args = AllVec> struct SYCLf ;
118
125
119
126
template <class T , MathOp Op> struct HostFunc ;
120
127
121
128
#define DEFINE_HOST_OP (Op, HostOp ) \
122
129
template <class T > struct HostFunc <T, MathOp::Op> { \
123
- T operator ()(T X) { return HostOp; } \
130
+ T operator ()(T X) { return HOST_SATURATE ( HostOp) ; } \
124
131
};
125
132
126
133
DEFINE_HOST_OP (sin, std::sin(X));
@@ -139,7 +146,7 @@ DEFINE_HOST_OP(log2, std::log2(X));
139
146
140
147
#define DEFINE_HOST_BIN_OP (Op, HostOp ) \
141
148
template <class T > struct HostFunc <T, MathOp::Op> { \
142
- T operator ()(T X, T Y) { return HostOp; } \
149
+ T operator ()(T X, T Y) { return HOST_SATURATE ( HostOp) ; } \
143
150
};
144
151
145
152
DEFINE_HOST_BIN_OP (div_ieee, X / Y);
@@ -151,12 +158,12 @@ DEFINE_HOST_BIN_OP(pow, std::pow(X, Y));
151
158
template <class T , int N> struct ESIMDf <T, N, MathOp::Op, AllVec> { \
152
159
esimd::simd<T, N> \
153
160
operator ()(esimd::simd<T, N> X) const SYCL_ESIMD_FUNCTION { \
154
- return esimd::Op<T, N>(X); \
161
+ return esimd::Op<T, N>(X, ESIMD_SATURATION_TAG); \
155
162
} \
156
163
}; \
157
164
template <class T , int N> struct ESIMDf <T, N, MathOp::Op, AllSca> { \
158
165
esimd::simd<T, N> operator ()(T X) const SYCL_ESIMD_FUNCTION { \
159
- return esimd::Op<T, N>(X); \
166
+ return esimd::Op<T, N>(X, ESIMD_SATURATION_TAG); \
160
167
} \
161
168
};
162
169
@@ -177,26 +184,26 @@ DEFINE_ESIMD_DEVICE_OP(log2);
177
184
#define DEFINE_ESIMD_DEVICE_BIN_OP (Op ) \
178
185
template <class T , int N> struct BinESIMDf <T, N, MathOp::Op, AllSca> { \
179
186
esimd::simd<T, N> operator ()(T X, T Y) const SYCL_ESIMD_FUNCTION { \
180
- return esimd::Op<T, N>(X, Y); \
187
+ return esimd::Op<T, N>(X, Y, ESIMD_SATURATION_TAG); \
181
188
} \
182
189
}; \
183
190
template <class T , int N> struct BinESIMDf <T, N, MathOp::Op, AllVec> { \
184
191
esimd::simd<T, N> \
185
192
operator ()(esimd::simd<T, N> X, \
186
193
esimd::simd<T, N> Y) const SYCL_ESIMD_FUNCTION { \
187
- return esimd::Op<T, N>(X, Y); \
194
+ return esimd::Op<T, N>(X, Y, ESIMD_SATURATION_TAG); \
188
195
} \
189
196
}; \
190
197
template <class T , int N> struct BinESIMDf <T, N, MathOp::Op, Sca1Vec2> { \
191
198
esimd::simd<T, N> \
192
199
operator ()(T X, esimd::simd<T, N> Y) const SYCL_ESIMD_FUNCTION { \
193
- return esimd::Op<T, N>(X, Y); \
200
+ return esimd::Op<T, N>(X, Y, ESIMD_SATURATION_TAG); \
194
201
} \
195
202
}; \
196
203
template <class T , int N> struct BinESIMDf <T, N, MathOp::Op, Sca2Vec1> { \
197
204
esimd::simd<T, N> operator ()(esimd::simd<T, N> X, \
198
205
T Y) const SYCL_ESIMD_FUNCTION { \
199
- return esimd::Op<T, N>(X, Y); \
206
+ return esimd::Op<T, N>(X, Y, ESIMD_SATURATION_TAG); \
200
207
} \
201
208
};
202
209
@@ -208,12 +215,12 @@ DEFINE_ESIMD_DEVICE_BIN_OP(pow);
208
215
esimd::simd<T, N> \
209
216
operator ()(esimd::simd<T, N> X) const SYCL_ESIMD_FUNCTION { \
210
217
/* T must be float for SYCL, so not a template parameter for sycl::Op*/ \
211
- return sycl::Op<N>(X); \
218
+ return ESIMD_SATURATE (T, sycl::Op<N>(X)); \
212
219
} \
213
220
}; \
214
221
template <class T , int N> struct SYCLf <T, N, MathOp::Op, AllSca> { \
215
222
esimd::simd<T, N> operator ()(T X) const SYCL_ESIMD_FUNCTION { \
216
- return sycl::Op<N>(X); \
223
+ return ESIMD_SATURATE (T, sycl::Op<N>(X)); \
217
224
} \
218
225
};
219
226
@@ -307,10 +314,11 @@ struct BinaryDeviceFunc {
307
314
template <class T , int N, MathOp Op,
308
315
template <class , int , MathOp, int > class Kernel ,
309
316
typename InitF = InitNarrow<T>>
310
- bool test (queue &Q, const std::string &Name,
311
- InitF Init = InitNarrow<T>{}, float delta = 0 .0f ) {
317
+ bool test (queue &Q, const std::string &Name, InitF Init = InitNarrow<T>{},
318
+ float delta = 0 .0f ) {
312
319
313
- constexpr size_t Size = 1024 * 128 ;
320
+ constexpr size_t Size =
321
+ std::is_same_v<T, sycl::half> ? (16 * 128 ) : (1024 * 128 );
314
322
constexpr bool IsBinOp = (Op == MathOp::div_ieee) || (Op == MathOp::pow);
315
323
316
324
T *A = new T[Size];
@@ -322,9 +330,9 @@ bool test(queue &Q, const std::string &Name,
322
330
Init (A, B, Size);
323
331
}
324
332
const char *kind =
325
- std::is_same_v<Kernel<T, N, Op, AllVec>, ESIMDf<T, N, Op, AllVec>>
326
- ? " ESIMD"
327
- : " SYCL" ;
333
+ std::is_same_v<Kernel<T, N, Op, AllVec>, ESIMDf<T, N, Op, AllVec>>
334
+ ? " ESIMD"
335
+ : " SYCL" ;
328
336
std::cout << " " << Name << " test, kind=" << kind << " ...\n " ;
329
337
330
338
try {
@@ -343,12 +351,11 @@ bool test(queue &Q, const std::string &Name,
343
351
auto PC = BufC.template get_access <access::mode::write>(CGH);
344
352
if constexpr (IsBinOp) {
345
353
auto PB = BufB.template get_access <access::mode::read>(CGH);
346
- BinaryDeviceFunc<T, N, Op, Kernel, decltype (PA), decltype (PC)> F (
347
- PA, PB, PC);
354
+ BinaryDeviceFunc<T, N, Op, Kernel, decltype (PA), decltype (PC)> F (PA, PB,
355
+ PC);
348
356
CGH.parallel_for (nd_range<1 >{GlobalRange, LocalRange}, F);
349
357
} else {
350
- UnaryDeviceFunc<T, N, Op, Kernel, decltype (PA), decltype (PC)> F (PA,
351
- PC);
358
+ UnaryDeviceFunc<T, N, Op, Kernel, decltype (PA), decltype (PC)> F (PA, PC);
352
359
CGH.parallel_for (nd_range<1 >{GlobalRange, LocalRange}, F);
353
360
}
354
361
});
@@ -384,6 +391,7 @@ bool test(queue &Q, const std::string &Name,
384
391
if (++ErrCnt < 10 ) {
385
392
std::cout << " failed at index " << I << " , " << Test
386
393
<< " != " << Gold << " (gold)\n " ;
394
+ std::cout << " A = " << (T)A[I] << " , B = " << (T)B[I] << " \n " ;
387
395
}
388
396
}
389
397
}
@@ -442,10 +450,9 @@ template <class T, int N> bool testESIMDDivIEEE(queue &Q) {
442
450
443
451
template <class T , int N> bool testESIMDPow (queue &Q) {
444
452
bool Pass = true ;
445
- std::cout << " --- TESTING ESIMD pow, T=" << typeid (T).name ()
446
- << " , N = " << N << " ...\n " ;
447
- Pass &= test<T, N, MathOp::pow, BinESIMDf>(
448
- Q, " pow" , InitBin<T>{}, 0.1 );
453
+ std::cout << " --- TESTING ESIMD pow, T=" << typeid (T).name () << " , N = " << N
454
+ << " ...\n " ;
455
+ Pass &= test<T, N, MathOp::pow, BinESIMDf>(Q, " pow" , InitBin<T>{}, 0.1 );
449
456
return Pass;
450
457
}
451
458
@@ -479,7 +486,7 @@ int main(void) {
479
486
Pass &= testESIMDSqrtIEEE<double , 32 >(Q);
480
487
Pass &= testESIMDDivIEEE<double , 32 >(Q);
481
488
}
482
- #else // !TEST_IEEE_DIV_REM
489
+ #else // !TEST_IEEE_DIV_REM
483
490
Pass &= testESIMD<half, 8 >(Q);
484
491
Pass &= testESIMD<float , 16 >(Q);
485
492
Pass &= testESIMD<float , 32 >(Q);
0 commit comments