9
9
// RUN: %{build} -fsycl-device-code-split=per_kernel %{mathflags} -o %t.out
10
10
// RUN: %{run} %t.out
11
11
12
- // FIXME: enable opaque pointers support
13
- // REQUIRES: TEMPORARY_DISABLED
14
-
15
12
// This test checks extended math operations. Combinations of
16
13
// - argument type - half, float
17
14
// - math function - sin, cos, ..., div_ieee, pow
29
26
using namespace sycl ;
30
27
using namespace sycl ::ext::intel;
31
28
29
+ #ifdef SATURATION_ON
30
+ #define ESIMD_SATURATION_TAG \
31
+ esimd::saturation_on_tag {}
32
+ #define ESIMD_SATURATE (T, x ) esimd::saturate<T>(x)
33
+ #define HOST_SATURATE (x ) std::max(0 .0f , std::min((x), 1 .0f ))
34
+ #else
35
+ #define ESIMD_SATURATION_TAG \
36
+ esimd::saturation_off_tag {}
37
+ #define ESIMD_SATURATE (T, x ) (x)
38
+ #define HOST_SATURATE (x ) (x)
39
+ #endif
40
+
32
41
// --- Data initialization functions
33
42
34
43
// Initialization data for trigonometric functions' input.
@@ -105,22 +114,17 @@ enum class MathOp {
105
114
106
115
// --- Template functions calculating given math operation on host and device
107
116
108
- enum ArgKind {
109
- AllVec,
110
- AllSca,
111
- Sca1Vec2,
112
- Sca2Vec1
113
- };
117
+ enum ArgKind { AllVec, AllSca, Sca1Vec2, Sca2Vec1 };
114
118
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 ;
119
+ template <class T , int N, MathOp Op, int Args = AllVec> struct ESIMDf ;
120
+ template <class T , int N, MathOp Op, int Args = AllVec> struct BinESIMDf ;
121
+ template <class T , int N, MathOp Op, int Args = AllVec> struct SYCLf ;
118
122
119
123
template <class T , MathOp Op> struct HostFunc ;
120
124
121
125
#define DEFINE_HOST_OP (Op, HostOp ) \
122
126
template <class T > struct HostFunc <T, MathOp::Op> { \
123
- T operator ()(T X) { return HostOp; } \
127
+ T operator ()(T X) { return HOST_SATURATE ( HostOp) ; } \
124
128
};
125
129
126
130
DEFINE_HOST_OP (sin, std::sin(X));
@@ -139,7 +143,7 @@ DEFINE_HOST_OP(log2, std::log2(X));
139
143
140
144
#define DEFINE_HOST_BIN_OP (Op, HostOp ) \
141
145
template <class T > struct HostFunc <T, MathOp::Op> { \
142
- T operator ()(T X, T Y) { return HostOp; } \
146
+ T operator ()(T X, T Y) { return HOST_SATURATE ( HostOp) ; } \
143
147
};
144
148
145
149
DEFINE_HOST_BIN_OP (div_ieee, X / Y);
@@ -151,12 +155,12 @@ DEFINE_HOST_BIN_OP(pow, std::pow(X, Y));
151
155
template <class T , int N> struct ESIMDf <T, N, MathOp::Op, AllVec> { \
152
156
esimd::simd<T, N> \
153
157
operator ()(esimd::simd<T, N> X) const SYCL_ESIMD_FUNCTION { \
154
- return esimd::Op<T, N>(X); \
158
+ return esimd::Op<T, N>(X, ESIMD_SATURATION_TAG); \
155
159
} \
156
160
}; \
157
161
template <class T , int N> struct ESIMDf <T, N, MathOp::Op, AllSca> { \
158
162
esimd::simd<T, N> operator ()(T X) const SYCL_ESIMD_FUNCTION { \
159
- return esimd::Op<T, N>(X); \
163
+ return esimd::Op<T, N>(X, ESIMD_SATURATION_TAG); \
160
164
} \
161
165
};
162
166
@@ -177,26 +181,26 @@ DEFINE_ESIMD_DEVICE_OP(log2);
177
181
#define DEFINE_ESIMD_DEVICE_BIN_OP (Op ) \
178
182
template <class T , int N> struct BinESIMDf <T, N, MathOp::Op, AllSca> { \
179
183
esimd::simd<T, N> operator ()(T X, T Y) const SYCL_ESIMD_FUNCTION { \
180
- return esimd::Op<T, N>(X, Y); \
184
+ return esimd::Op<T, N>(X, Y, ESIMD_SATURATION_TAG); \
181
185
} \
182
186
}; \
183
187
template <class T , int N> struct BinESIMDf <T, N, MathOp::Op, AllVec> { \
184
188
esimd::simd<T, N> \
185
189
operator ()(esimd::simd<T, N> X, \
186
190
esimd::simd<T, N> Y) const SYCL_ESIMD_FUNCTION { \
187
- return esimd::Op<T, N>(X, Y); \
191
+ return esimd::Op<T, N>(X, Y, ESIMD_SATURATION_TAG); \
188
192
} \
189
193
}; \
190
194
template <class T , int N> struct BinESIMDf <T, N, MathOp::Op, Sca1Vec2> { \
191
195
esimd::simd<T, N> \
192
196
operator ()(T X, esimd::simd<T, N> Y) const SYCL_ESIMD_FUNCTION { \
193
- return esimd::Op<T, N>(X, Y); \
197
+ return esimd::Op<T, N>(X, Y, ESIMD_SATURATION_TAG); \
194
198
} \
195
199
}; \
196
200
template <class T , int N> struct BinESIMDf <T, N, MathOp::Op, Sca2Vec1> { \
197
201
esimd::simd<T, N> operator ()(esimd::simd<T, N> X, \
198
202
T Y) const SYCL_ESIMD_FUNCTION { \
199
- return esimd::Op<T, N>(X, Y); \
203
+ return esimd::Op<T, N>(X, Y, ESIMD_SATURATION_TAG); \
200
204
} \
201
205
};
202
206
@@ -208,12 +212,12 @@ DEFINE_ESIMD_DEVICE_BIN_OP(pow);
208
212
esimd::simd<T, N> \
209
213
operator ()(esimd::simd<T, N> X) const SYCL_ESIMD_FUNCTION { \
210
214
/* T must be float for SYCL, so not a template parameter for sycl::Op*/ \
211
- return sycl::Op<N>(X); \
215
+ return ESIMD_SATURATE (T, sycl::Op<N>(X)); \
212
216
} \
213
217
}; \
214
218
template <class T , int N> struct SYCLf <T, N, MathOp::Op, AllSca> { \
215
219
esimd::simd<T, N> operator ()(T X) const SYCL_ESIMD_FUNCTION { \
216
- return sycl::Op<N>(X); \
220
+ return ESIMD_SATURATE (T, sycl::Op<N>(X)); \
217
221
} \
218
222
};
219
223
@@ -307,10 +311,11 @@ struct BinaryDeviceFunc {
307
311
template <class T , int N, MathOp Op,
308
312
template <class , int , MathOp, int > class Kernel ,
309
313
typename InitF = InitNarrow<T>>
310
- bool test (queue &Q, const std::string &Name,
311
- InitF Init = InitNarrow<T>{}, float delta = 0 .0f ) {
314
+ bool test (queue &Q, const std::string &Name, InitF Init = InitNarrow<T>{},
315
+ float delta = 0 .0f ) {
312
316
313
- constexpr size_t Size = 1024 * 128 ;
317
+ constexpr size_t Size =
318
+ std::is_same_v<T, sycl::half> ? (16 * 128 ) : (1024 * 128 );
314
319
constexpr bool IsBinOp = (Op == MathOp::div_ieee) || (Op == MathOp::pow);
315
320
316
321
T *A = new T[Size];
@@ -322,9 +327,9 @@ bool test(queue &Q, const std::string &Name,
322
327
Init (A, B, Size);
323
328
}
324
329
const char *kind =
325
- std::is_same_v<Kernel<T, N, Op, AllVec>, ESIMDf<T, N, Op, AllVec>>
326
- ? " ESIMD"
327
- : " SYCL" ;
330
+ std::is_same_v<Kernel<T, N, Op, AllVec>, ESIMDf<T, N, Op, AllVec>>
331
+ ? " ESIMD"
332
+ : " SYCL" ;
328
333
std::cout << " " << Name << " test, kind=" << kind << " ...\n " ;
329
334
330
335
try {
@@ -343,19 +348,21 @@ bool test(queue &Q, const std::string &Name,
343
348
auto PC = BufC.template get_access <access::mode::write>(CGH);
344
349
if constexpr (IsBinOp) {
345
350
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);
351
+ BinaryDeviceFunc<T, N, Op, Kernel, decltype (PA), decltype (PC)> F (PA, PB,
352
+ PC);
348
353
CGH.parallel_for (nd_range<1 >{GlobalRange, LocalRange}, F);
349
354
} else {
350
- UnaryDeviceFunc<T, N, Op, Kernel, decltype (PA), decltype (PC)> F (PA,
351
- PC);
355
+ UnaryDeviceFunc<T, N, Op, Kernel, decltype (PA), decltype (PC)> F (PA, PC);
352
356
CGH.parallel_for (nd_range<1 >{GlobalRange, LocalRange}, F);
353
357
}
354
358
});
355
359
E.wait ();
356
360
} catch (sycl::exception &Exc) {
357
361
std::cout << " *** ERROR. SYCL exception caught: << " << Exc.what ()
358
362
<< " \n " ;
363
+ delete[] A;
364
+ delete[] B;
365
+ delete[] C;
359
366
return false ;
360
367
}
361
368
@@ -375,15 +382,19 @@ bool test(queue &Q, const std::string &Name,
375
382
}
376
383
CheckT Test = C[I];
377
384
378
- if (delta == 0 .0f ) {
379
- delta = sizeof (T) > 2 ? 0.0001 : 0.01 ;
380
- }
385
+ if (delta == 0 .0f )
386
+ delta = 0.0001 ;
387
+ if constexpr (sizeof (T) <= 2 )
388
+ delta = delta + delta;
381
389
382
390
bool BothFinite = std::isfinite (Test) && std::isfinite (Gold);
383
391
if (BothFinite && std::abs (Test - Gold) > delta) {
384
392
if (++ErrCnt < 10 ) {
385
393
std::cout << " failed at index " << I << " , " << Test
386
394
<< " != " << Gold << " (gold)\n " ;
395
+ std::cout << " A = " << (T)A[I] << " , B = " << (T)B[I]
396
+ << " , diff = " << std::abs (Test - Gold)
397
+ << " , max-delta = " << delta << " \n " ;
387
398
}
388
399
}
389
400
}
@@ -442,10 +453,9 @@ template <class T, int N> bool testESIMDDivIEEE(queue &Q) {
442
453
443
454
template <class T , int N> bool testESIMDPow (queue &Q) {
444
455
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 );
456
+ std::cout << " --- TESTING ESIMD pow, T=" << typeid (T).name () << " , N = " << N
457
+ << " ...\n " ;
458
+ Pass &= test<T, N, MathOp::pow, BinESIMDf>(Q, " pow" , InitBin<T>{}, 0.1 );
449
459
return Pass;
450
460
}
451
461
@@ -468,9 +478,16 @@ template <class T, int N> bool testSYCL(queue &Q) {
468
478
469
479
int main (void ) {
470
480
queue Q (esimd_test::ESIMDSelector, esimd_test::createExceptionHandler ());
481
+ esimd_test::printTestLabel (Q);
471
482
auto Dev = Q.get_device ();
472
- std::cout << " Running on " << Dev.get_info <sycl::info::device::name>()
473
- << " \n " ;
483
+ #ifndef SKIP_NEW_GPU_DRIVER_VERSION_CHECK
484
+ if (!esimd_test::isGPUDriverGE (Q, esimd_test::GPUDriverOS::LinuxAndWindows,
485
+ " 27012" , " 101.4576" )) {
486
+ std::cout << " Skipped. The test requires GPU driver 1.3.27012 or newer.\n " ;
487
+ return 0 ;
488
+ }
489
+ #endif
490
+
474
491
bool Pass = true ;
475
492
#ifdef TEST_IEEE_DIV_REM
476
493
Pass &= testESIMDSqrtIEEE<float , 16 >(Q);
@@ -479,7 +496,7 @@ int main(void) {
479
496
Pass &= testESIMDSqrtIEEE<double , 32 >(Q);
480
497
Pass &= testESIMDDivIEEE<double , 32 >(Q);
481
498
}
482
- #else // !TEST_IEEE_DIV_REM
499
+ #else // !TEST_IEEE_DIV_REM
483
500
Pass &= testESIMD<half, 8 >(Q);
484
501
Pass &= testESIMD<float , 16 >(Q);
485
502
Pass &= testESIMD<float , 32 >(Q);
0 commit comments