1717namespace syclex = sycl::ext::oneapi::experimental;
1818
1919constexpr size_t NumOps = 256 ;
20+ constexpr auto IdxSeq = std::make_index_sequence<NumOps>{};
21+
22+ static std::random_device RDev;
23+ static std::mt19937 RNG (RDev());
2024
2125template <typename T, size_t ... Is>
22- std::array<T, NumOps> apply (T *A, T *B, T *C, std::index_sequence<Is...>) {
26+ std::array<T, NumOps> apply (std::array<T, NumOps> &A, std::array<T, NumOps> &B,
27+ std::array<T, NumOps> &C,
28+ std::index_sequence<Is...>) {
2329 return std::array<T, NumOps>{
2430 syclex::ternary_bitwise<Is>(A[Is], B[Is], C[Is])...};
2531}
2632
2733template <typename T> void fillRandom (T *Dest) {
28- std::random_device RDev;
29- std::mt19937 RNG (RDev ());
3034 std::uniform_int_distribution<T> Dist;
3135 for (size_t I = 0 ; I < NumOps; ++I)
3236 Dest[I] = Dist (RNG);
3337}
3438
3539template <typename T, int N> void fillRandom (sycl::vec<T, N> *Dest) {
36- std::random_device RDev;
37- std::mt19937 RNG (RDev ());
3840 std::uniform_int_distribution<T> Dist;
3941 for (size_t I = 0 ; I < NumOps; ++I)
4042 for (size_t J = 0 ; J < N; ++J)
4143 Dest[I][J] = Dist (RNG);
4244}
4345
4446template <typename T, size_t N> void fillRandom (sycl::marray<T, N> *Dest) {
45- std::random_device RDev;
46- std::mt19937 RNG (RDev ());
4747 std::uniform_int_distribution<T> Dist;
4848 for (size_t I = 0 ; I < NumOps; ++I)
4949 for (size_t J = 0 ; J < N; ++J)
@@ -79,25 +79,26 @@ template <typename T, size_t N> std::string toString(sycl::marray<T, N> X) {
7979 return Result + " }" ;
8080}
8181
82- template <typename T> int Check (sycl::queue &Q, std::string_view TName) {
83- constexpr auto IdxSeq = std::make_index_sequence<NumOps>{};
84-
85- int Failed = 0 ;
86-
87- T *A = sycl::malloc_shared<T>(NumOps, Q);
88- T *B = sycl::malloc_shared<T>(NumOps, Q);
89- T *C = sycl::malloc_shared<T>(NumOps, Q);
90- auto *Out = sycl::malloc_shared<std::array<T, NumOps>>(1 , Q);
91-
92- fillRandom (A);
93- fillRandom (B);
94- fillRandom (C);
95-
96- Q.single_task ([=]() { *Out = apply (A, B, C, IdxSeq); }).wait_and_throw ();
82+ template <typename T> struct MemObj {
83+ std::array<T, NumOps> A;
84+ std::array<T, NumOps> B;
85+ std::array<T, NumOps> C;
86+ std::array<T, NumOps> Out;
87+ };
88+
89+ template <typename T> MemObj<T> *createMem (sycl::queue &Q) {
90+ MemObj<T> *Obj = sycl::malloc_shared<MemObj<T>>(NumOps, Q);
91+ fillRandom (Obj->A .data ());
92+ fillRandom (Obj->B .data ());
93+ fillRandom (Obj->C .data ());
94+ return Obj;
95+ }
9796
98- std::array<T, NumOps> DevResults = *Out;
99- std::array<T, NumOps> HostResults = apply (A, B, C, IdxSeq);
97+ template <typename T> int checkResult (MemObj<T> &Mem, std::string_view TName) {
98+ std::array<T, NumOps> &DevResults = Mem.Out ;
99+ std::array<T, NumOps> HostResults = apply (Mem.A , Mem.B , Mem.C , IdxSeq);
100100
101+ int Failed = 0 ;
101102 for (size_t I = 0 ; I < NumOps; ++I) {
102103 if (allTrue (DevResults[I] != HostResults[I])) {
103104 std::cout << " Failed check for type " << TName << " at index " << I
@@ -106,53 +107,92 @@ template <typename T> int Check(sycl::queue &Q, std::string_view TName) {
106107 ++Failed;
107108 }
108109 }
109-
110- sycl::free (A, Q);
111- sycl::free (B, Q);
112- sycl::free (C, Q);
113- sycl::free (Out, Q);
114-
115110 return Failed;
116111}
117112
118113int main () {
119114 sycl::queue Q;
120115
116+ auto *CharObj = createMem<char >(Q);
117+ auto *SCharObj = createMem<signed char >(Q);
118+ auto *UCharObj = createMem<unsigned char >(Q);
119+ auto *ShortObj = createMem<short >(Q);
120+ auto *UShortObj = createMem<unsigned short >(Q);
121+ auto *IntObj = createMem<int >(Q);
122+ auto *UIntObj = createMem<unsigned int >(Q);
123+ auto *LongObj = createMem<long >(Q);
124+ auto *ULongObj = createMem<unsigned long >(Q);
125+ auto *SChar2Obj = createMem<sycl::vec<int8_t , 2 >>(Q);
126+ auto *UShort8Obj = createMem<sycl::vec<uint16_t , 8 >>(Q);
127+ auto *Int2Obj = createMem<sycl::vec<int32_t , 2 >>(Q);
128+ auto *ULong8Obj = createMem<sycl::vec<uint64_t , 8 >>(Q);
129+ auto *CharMarrayObj = createMem<sycl::marray<char , 3 >>(Q);
130+ auto *UShortMarrayObj = createMem<sycl::marray<unsigned short , 3 >>(Q);
131+ auto *IntMarrayObj = createMem<sycl::marray<int , 3 >>(Q);
132+ auto *ULongMarrayObj = createMem<sycl::marray<unsigned long , 3 >>(Q);
133+
134+ Q.parallel_for (17 , [=](sycl::id<1 > Idx) {
135+ // We let the ID determine which memory object the work-item processes.
136+ size_t WorkCounter = 0 ;
137+ #define APPLY (MEM_OBJ ) \
138+ if ((WorkCounter++) == Idx[0 ]) \
139+ MEM_OBJ->Out = apply (MEM_OBJ->A , MEM_OBJ->B , MEM_OBJ->C , IdxSeq);
140+ APPLY (CharObj)
141+ APPLY (SCharObj)
142+ APPLY (UCharObj)
143+ APPLY (ShortObj)
144+ APPLY (UShortObj)
145+ APPLY (IntObj)
146+ APPLY (UIntObj)
147+ APPLY (LongObj)
148+ APPLY (ULongObj)
149+ APPLY (SChar2Obj)
150+ APPLY (UShort8Obj)
151+ APPLY (Int2Obj)
152+ APPLY (ULong8Obj)
153+ APPLY (CharMarrayObj)
154+ APPLY (UShortMarrayObj)
155+ APPLY (IntMarrayObj)
156+ APPLY (ULongMarrayObj)
157+ }).wait_and_throw ();
158+
121159 int Failed = 0 ;
122- #define CHECK (...) Failed += Check<__VA_ARGS__>(Q, #__VA_ARGS__);
123- CHECK (char )
124- CHECK (signed char )
125- CHECK (unsigned char )
126- CHECK (short )
127- CHECK (unsigned short )
128- CHECK (int )
129- CHECK (unsigned int )
130- CHECK (long )
131- CHECK (unsigned long )
132- CHECK (sycl::vec<int8_t , 2 >)
133- CHECK (sycl::vec<int8_t , 8 >)
134- CHECK (sycl::vec<uint8_t , 2 >)
135- CHECK (sycl::vec<uint8_t , 8 >)
136- CHECK (sycl::vec<int16_t , 2 >)
137- CHECK (sycl::vec<int16_t , 8 >)
138- CHECK (sycl::vec<uint16_t , 2 >)
139- CHECK (sycl::vec<uint16_t , 8 >)
140- CHECK (sycl::vec<int32_t , 2 >)
141- CHECK (sycl::vec<int32_t , 8 >)
142- CHECK (sycl::vec<uint32_t , 2 >)
143- CHECK (sycl::vec<uint32_t , 8 >)
144- CHECK (sycl::vec<int64_t , 2 >)
145- CHECK (sycl::vec<int64_t , 8 >)
146- CHECK (sycl::vec<uint64_t , 2 >)
147- CHECK (sycl::vec<uint64_t , 8 >)
148- CHECK (sycl::marray<char , 3 >)
149- CHECK (sycl::marray<signed char , 3 >)
150- CHECK (sycl::marray<unsigned char , 3 >)
151- CHECK (sycl::marray<short , 3 >)
152- CHECK (sycl::marray<unsigned short , 3 >)
153- CHECK (sycl::marray<int , 3 >)
154- CHECK (sycl::marray<unsigned int , 3 >)
155- CHECK (sycl::marray<long , 3 >)
156- CHECK (sycl::marray<unsigned long , 3 >)
160+
161+ Failed += checkResult (*CharObj, " char" );
162+ Failed += checkResult (*SCharObj, " signed char" );
163+ Failed += checkResult (*UCharObj, " unsigned char" );
164+ Failed += checkResult (*ShortObj, " short" );
165+ Failed += checkResult (*UShortObj, " unsigned short" );
166+ Failed += checkResult (*IntObj, " int" );
167+ Failed += checkResult (*UIntObj, " unsigned int" );
168+ Failed += checkResult (*LongObj, " long" );
169+ Failed += checkResult (*ULongObj, " unsigned long" );
170+ Failed += checkResult (*SChar2Obj, " sycl::vec<int8_t, 2>" );
171+ Failed += checkResult (*UShort8Obj, " sycl::vec<uint16_t, 8>" );
172+ Failed += checkResult (*Int2Obj, " sycl::vec<int32_t, 2>" );
173+ Failed += checkResult (*ULong8Obj, " sycl::vec<uint64_t, 8>" );
174+ Failed += checkResult (*CharMarrayObj, " sycl::marray<char, 3>" );
175+ Failed += checkResult (*UShortMarrayObj, " sycl::marray<unsigned short, 3>" );
176+ Failed += checkResult (*IntMarrayObj, " sycl::marray<int, 3>" );
177+ Failed += checkResult (*ULongMarrayObj, " sycl::marray<unsigned long, 3>" );
178+
179+ sycl::free (CharObj, Q);
180+ sycl::free (SCharObj, Q);
181+ sycl::free (UCharObj, Q);
182+ sycl::free (ShortObj, Q);
183+ sycl::free (UShortObj, Q);
184+ sycl::free (IntObj, Q);
185+ sycl::free (UIntObj, Q);
186+ sycl::free (LongObj, Q);
187+ sycl::free (ULongObj, Q);
188+ sycl::free (SChar2Obj, Q);
189+ sycl::free (UShort8Obj, Q);
190+ sycl::free (Int2Obj, Q);
191+ sycl::free (ULong8Obj, Q);
192+ sycl::free (CharMarrayObj, Q);
193+ sycl::free (UShortMarrayObj, Q);
194+ sycl::free (IntMarrayObj, Q);
195+ sycl::free (ULongMarrayObj, Q);
196+
157197 return Failed;
158198}
0 commit comments