Skip to content
This repository was archived by the owner on Mar 28, 2023. It is now read-only.

Commit 22877f2

Browse files
authored
[SYCL] Porting tests for specialization constants (#191)
Converted 3 remaining tests for specialization constants to llvm-test-suite infrastructure. Signed-off-by: Pavel V Chupin <[email protected]>
1 parent 43f3f33 commit 22877f2

File tree

3 files changed

+435
-0
lines changed

3 files changed

+435
-0
lines changed
Lines changed: 208 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,208 @@
1+
// RUN: %clangxx -fsycl %s -o %t.out
2+
// RUN: %HOST_RUN_PLACEHOLDER %t.out
3+
// RUN: %CPU_RUN_PLACEHOLDER %t.out
4+
// RUN: %GPU_RUN_PLACEHOLDER %t.out
5+
// Specialization constants are not supported on FPGA h/w and emulator.
6+
// UNSUPPORTED: cuda
7+
//
8+
//==----------- specialization_constants.cpp -------------------------------==//
9+
//
10+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
11+
// See https://llvm.org/LICENSE.txt for license information.
12+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
13+
//
14+
//===----------------------------------------------------------------------===//
15+
// Basic checks for some primitive types
16+
17+
#include <CL/sycl.hpp>
18+
#include <chrono>
19+
#include <cstdint>
20+
#include <random>
21+
22+
#define HALF 0 // FIXME Spec constants do not support half type yet
23+
24+
class SpecializedKernel;
25+
26+
class MyBoolConst;
27+
class MyInt8Const;
28+
class MyUInt8Const;
29+
class MyInt16Const;
30+
class MyUInt16Const;
31+
class MyInt32Const;
32+
class MyUInt32Const;
33+
class MyInt64Const;
34+
class MyUInt64Const;
35+
class MyHalfConst;
36+
class MyFloatConst;
37+
class MyDoubleConst;
38+
39+
using namespace sycl;
40+
41+
unsigned seed = std::chrono::system_clock::now().time_since_epoch().count();
42+
std::mt19937_64 rnd(seed);
43+
44+
bool bool_ref = true;
45+
// Fetch a value at runtime.
46+
int8_t int8_ref = rnd() % std::numeric_limits<int8_t>::max();
47+
uint8_t uint8_ref = rnd() % std::numeric_limits<uint8_t>::max();
48+
int16_t int16_ref = rnd() % std::numeric_limits<int16_t>::max();
49+
uint16_t uint16_ref = rnd() % std::numeric_limits<uint16_t>::max();
50+
int32_t int32_ref = rnd() % std::numeric_limits<int32_t>::max();
51+
uint32_t uint32_ref = rnd() % std::numeric_limits<uint32_t>::max();
52+
int64_t int64_ref = rnd() % std::numeric_limits<int64_t>::max();
53+
uint64_t uint64_ref = rnd() % std::numeric_limits<uint64_t>::max();
54+
half half_ref = rnd() % std::numeric_limits<uint16_t>::max();
55+
float float_ref = rnd() % std::numeric_limits<uint32_t>::max();
56+
double double_ref = rnd() % std::numeric_limits<uint64_t>::max();
57+
58+
template <typename T1, typename T2>
59+
bool check(const T1 &test, const T2 &ref, cl::sycl::string_class type) {
60+
61+
if (test != ref) {
62+
std::cout << "Test != Reference: " << std::to_string(test)
63+
<< " != " << std::to_string(ref) << " for type: " << type << "\n";
64+
return false;
65+
}
66+
return true;
67+
}
68+
69+
int main(int argc, char **argv) {
70+
std::cout << "check specialization constants API. (seed =" << seed << "\n";
71+
72+
auto exception_handler = [&](sycl::exception_list exceptions) {
73+
for (std::exception_ptr const &e : exceptions) {
74+
try {
75+
std::rethrow_exception(e);
76+
} catch (sycl::exception const &e) {
77+
std::cout << "an async SYCL exception was caught: "
78+
<< string_class(e.what());
79+
}
80+
}
81+
};
82+
try {
83+
auto q = queue(exception_handler);
84+
program prog(q.get_context());
85+
86+
// Create specialization constants.
87+
ONEAPI::experimental::spec_constant<bool, MyBoolConst> i1 =
88+
prog.set_spec_constant<MyBoolConst>(bool_ref);
89+
ONEAPI::experimental::spec_constant<int8_t, MyInt8Const> i8 =
90+
prog.set_spec_constant<MyInt8Const>(int8_ref);
91+
ONEAPI::experimental::spec_constant<uint8_t, MyUInt8Const> ui8 =
92+
prog.set_spec_constant<MyUInt8Const>(uint8_ref);
93+
ONEAPI::experimental::spec_constant<int16_t, MyInt16Const> i16 =
94+
prog.set_spec_constant<MyInt16Const>(int16_ref);
95+
ONEAPI::experimental::spec_constant<uint16_t, MyUInt16Const> ui16 =
96+
prog.set_spec_constant<MyUInt16Const>(uint16_ref);
97+
ONEAPI::experimental::spec_constant<int32_t, MyInt32Const> i32 =
98+
prog.set_spec_constant<MyInt32Const>(int32_ref);
99+
ONEAPI::experimental::spec_constant<uint32_t, MyUInt32Const> ui32 =
100+
prog.set_spec_constant<MyUInt32Const>(uint32_ref);
101+
ONEAPI::experimental::spec_constant<int64_t, MyInt64Const> i64 =
102+
prog.set_spec_constant<MyInt64Const>(int64_ref);
103+
ONEAPI::experimental::spec_constant<uint64_t, MyUInt64Const> ui64 =
104+
prog.set_spec_constant<MyUInt64Const>(uint64_ref);
105+
#if HALF
106+
ONEAPI::experimental::spec_constant<cl::sycl::half, MyHalfConst> f16 =
107+
prog.set_spec_constant<MyHalfConst>(half_ref);
108+
#endif
109+
ONEAPI::experimental::spec_constant<float, MyFloatConst> f32 =
110+
prog.set_spec_constant<MyFloatConst>(float_ref);
111+
112+
ONEAPI::experimental::spec_constant<double, MyDoubleConst> f64 =
113+
prog.set_spec_constant<MyDoubleConst>(double_ref);
114+
115+
prog.build_with_kernel_type<SpecializedKernel>();
116+
117+
bool bool_test = 0;
118+
int8_t int8_test = 0;
119+
uint8_t uint8_test = 0;
120+
int16_t int16_test = 0;
121+
uint16_t uint16_test = 0;
122+
int32_t int32_test = 0;
123+
uint32_t uint32_test = 0;
124+
int64_t int64_test = 0;
125+
uint64_t uint64_test = 0;
126+
half half_test = 0;
127+
float float_test = 0;
128+
double double_test = 0;
129+
130+
{
131+
buffer<bool> bool_buf(&bool_test, 1);
132+
buffer<int8_t> int8_buf(&int8_test, 1);
133+
buffer<uint8_t> uint8_buf(&uint8_test, 1);
134+
buffer<int16_t> int16_buf(&int16_test, 1);
135+
buffer<uint16_t> uint16_buf(&uint16_test, 1);
136+
buffer<int32_t> int32_buf(&int32_test, 1);
137+
buffer<uint32_t> uint32_buf(&uint32_test, 1);
138+
buffer<int64_t> int64_buf(&int64_test, 1);
139+
buffer<uint64_t> uint64_buf(&uint64_test, 1);
140+
buffer<half> half_buf(&half_test, 1);
141+
buffer<float> float_buf(&float_test, 1);
142+
buffer<double> double_buf(&double_test, 1);
143+
144+
q.submit([&](handler &cgh) {
145+
auto bool_acc = bool_buf.get_access<access::mode::write>(cgh);
146+
auto int8_acc = int8_buf.get_access<access::mode::write>(cgh);
147+
auto uint8_acc = uint8_buf.get_access<access::mode::write>(cgh);
148+
auto int16_acc = int16_buf.get_access<access::mode::write>(cgh);
149+
auto uint16_acc = uint16_buf.get_access<access::mode::write>(cgh);
150+
auto int32_acc = int32_buf.get_access<access::mode::write>(cgh);
151+
auto uint32_acc = uint32_buf.get_access<access::mode::write>(cgh);
152+
auto int64_acc = int64_buf.get_access<access::mode::write>(cgh);
153+
auto uint64_acc = uint64_buf.get_access<access::mode::write>(cgh);
154+
auto half_acc = half_buf.get_access<access::mode::write>(cgh);
155+
auto float_acc = float_buf.get_access<access::mode::write>(cgh);
156+
auto double_acc = double_buf.get_access<access::mode::write>(cgh);
157+
cgh.single_task<SpecializedKernel>(prog.get_kernel<SpecializedKernel>(),
158+
[=]() {
159+
bool_acc[0] = i1.get();
160+
int8_acc[0] = i8.get();
161+
uint8_acc[0] = ui8.get();
162+
int16_acc[0] = i16.get();
163+
uint16_acc[0] = ui16.get();
164+
int32_acc[0] = i32.get();
165+
uint32_acc[0] = ui32.get();
166+
int64_acc[0] = i64.get();
167+
uint64_acc[0] = ui64.get();
168+
#if HALF
169+
half_acc[0] = f16.get();
170+
#endif
171+
float_acc[0] = f32.get();
172+
double_acc[0] = f64.get();
173+
});
174+
});
175+
}
176+
if (!check(bool_test, bool_ref, "bool"))
177+
return 1;
178+
if (!check(int8_test, int8_ref, "int8"))
179+
return 1;
180+
if (!check(uint8_test, uint8_ref, "uint8"))
181+
return 1;
182+
if (!check(int16_test, int16_ref, "int16"))
183+
return 1;
184+
if (!check(uint16_test, uint16_ref, "uint16"))
185+
return 1;
186+
if (!check(int32_test, int32_ref, "int32"))
187+
return 1;
188+
if (!check(uint32_test, uint32_ref, "uint32"))
189+
return 1;
190+
if (!check(int64_test, int64_ref, "int64"))
191+
return 1;
192+
if (!check(uint64_test, uint64_ref, "uint64"))
193+
return 1;
194+
#if HALF
195+
if (!check(half_test, half_ref, "half"))
196+
return 1;
197+
#endif
198+
if (!check(float_test, float_ref, "float"))
199+
return 1;
200+
if (!check(double_test, double_ref, "double"))
201+
return 1;
202+
} catch (const exception &e) {
203+
std::cout << "an async SYCL exception was caught: "
204+
<< string_class(e.what());
205+
return 1;
206+
}
207+
return 0;
208+
}
Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
// RUN: %clangxx -fsycl %s -o %t.out
2+
// RUN: %HOST_RUN_PLACEHOLDER %t.out
3+
// RUN: %CPU_RUN_PLACEHOLDER %t.out
4+
// RUN: %GPU_RUN_PLACEHOLDER %t.out
5+
// Specialization constants are not supported on FPGA h/w and emulator.
6+
// UNSUPPORTED: cuda
7+
//
8+
//==----------- specialization_constants_negative.cpp ----------------------==//
9+
//
10+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
11+
// See https://llvm.org/LICENSE.txt for license information.
12+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
13+
//
14+
//===----------------------------------------------------------------------===//
15+
// Checks for negative cases
16+
17+
#include <CL/sycl.hpp>
18+
#include <chrono>
19+
#include <cstdint>
20+
#include <random>
21+
22+
class SpecializedKernelNegative;
23+
24+
class MyUInt32ConstNegative;
25+
class MyDoubleConstNegative;
26+
27+
using namespace sycl;
28+
29+
unsigned seed = std::chrono::system_clock::now().time_since_epoch().count();
30+
std::mt19937_64 rnd(seed);
31+
32+
// Fetch a value at runtime.
33+
uint32_t uint32_ref = rnd() % std::numeric_limits<uint32_t>::max();
34+
double double_ref = rnd() % std::numeric_limits<uint64_t>::max();
35+
36+
template <typename T1, typename T2>
37+
bool check(const T1 &test, const T2 &ref, string_class type) {
38+
39+
if (test != ref) {
40+
std::cout << "Test != Reference: " << std::to_string(test)
41+
<< " != " << std::to_string(ref) << " for type: " << type << "\n";
42+
return false;
43+
}
44+
return true;
45+
}
46+
47+
int main(int argc, char **argv) {
48+
std::cout << "check specialization constants exceptions. (seed =" << seed
49+
<< "\n";
50+
51+
auto exception_handler = [&](sycl::exception_list exceptions) {
52+
for (std::exception_ptr const &e : exceptions) {
53+
try {
54+
std::rethrow_exception(e);
55+
} catch (sycl::exception const &e) {
56+
std::cout << "an async SYCL exception was caught: "
57+
<< string_class(e.what());
58+
}
59+
}
60+
};
61+
62+
try {
63+
auto q = queue(exception_handler);
64+
program prog(q.get_context());
65+
66+
// Create specialization constants.
67+
ONEAPI::experimental::spec_constant<uint32_t, MyUInt32ConstNegative> ui32 =
68+
prog.set_spec_constant<MyUInt32ConstNegative>(uint32_ref);
69+
70+
prog.build_with_kernel_type<SpecializedKernelNegative>();
71+
72+
// Excerpt from
73+
// https://github.com/codeplaysoftware/standards-proposals/pull/121:
74+
// Once the program is in a build state, the specialization constant
75+
// can no longer be changed for the program and call to
76+
// set_specialization_constant will throw a spec_const_error
77+
// exception.
78+
bool exception_was_thrown = false;
79+
try {
80+
ui32 = prog.set_spec_constant<MyUInt32ConstNegative>(uint32_ref + 1);
81+
} catch (const ONEAPI::experimental::spec_const_error &e) {
82+
exception_was_thrown = true;
83+
}
84+
if (!exception_was_thrown) {
85+
std::cout << "Exception wasn't thrown\n";
86+
return 1;
87+
}
88+
89+
uint32_t uint32_test = 0;
90+
{
91+
buffer<uint32_t> uint32_buf(&uint32_test, 1);
92+
93+
q.submit([&](handler &cgh) {
94+
auto uint32_acc = uint32_buf.get_access<access::mode::write>(cgh);
95+
cgh.single_task<SpecializedKernelNegative>(
96+
prog.get_kernel<SpecializedKernelNegative>(),
97+
[=]() { uint32_acc[0] = ui32.get(); });
98+
});
99+
}
100+
check(uint32_test, uint32_ref, "uint32");
101+
102+
} catch (const exception &e) {
103+
std::cout << "an async SYCL exception was caught: "
104+
<< string_class(e.what());
105+
return 1;
106+
}
107+
return 0;
108+
}

0 commit comments

Comments
 (0)