Skip to content

Commit d88ef3b

Browse files
authored
[SYCL] Add Specialization constants extension intro document. (#2503)
Signed-off-by: Konstantin S Bobrovsky <[email protected]>
1 parent c36a141 commit d88ef3b

File tree

1 file changed

+72
-0
lines changed

1 file changed

+72
-0
lines changed
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
# Specialization constants.
2+
3+
Specialization constant is basically a variable in a SYCL program set by host
4+
code and used in device code which appears to be constant for the online (JIT)
5+
compiler of the device code. Things like optimal tile size in a tiled matrix
6+
multiplication kernel may depend on the hardware and can be expressed via a
7+
specialization constant for better code generation.
8+
9+
This version of oneAPI provides experimental implementation of specialization
10+
constants based on the
11+
[proposal](https://github.com/codeplaysoftware/standards-proposals/blob/master/spec-constant/index.md)
12+
from Codeplay.
13+
14+
**NOTE:** _In future versions it may be superseded by [SYCL 2020
15+
specification](https://www.khronos.org/registry/SYCL/specs/sycl-2020-provisional.pdf)._
16+
17+
A specialization constant is identified by a C++ type name, similarly to a
18+
kernel, its value is set via `program::set_spec_constant` class API and is
19+
"frozen" once the program is built. The following example shows how
20+
different values of a specialization constant can be used within the same
21+
kernel:
22+
23+
```cpp
24+
for (int i = 0; i < n_sc_sets; i++) {
25+
cl::sycl::program program(q.get_context());
26+
const int *sc_set = &sc_vals[i][0];
27+
cl::sycl::ONEAPI::experimental::spec_constant<int32_t, SC0> sc0 =
28+
program.set_spec_constant<SC0>(sc_set[0]);
29+
cl::sycl::ONEAPI::experimental::spec_constant<int32_t, SC1> sc1 =
30+
program.set_spec_constant<SC1>(sc_set[1]);
31+
32+
program.build_with_kernel_type<KernelAAA>();
33+
34+
try {
35+
cl::sycl::buffer<int, 1> buf(vec.data(), vec.size());
36+
37+
q.submit([&](cl::sycl::handler &cgh) {
38+
auto acc = buf.get_access<cl::sycl::access::mode::write>(cgh);
39+
cgh.single_task<KernelAAA>(
40+
program.get_kernel<KernelAAA>(),
41+
[=]() {
42+
acc[i] = sc0.get() + sc1.get();
43+
});
44+
});
45+
} catch (cl::sycl::exception &e) {
46+
std::cout << "*** Exception caught: " << e.what() << "\n";
47+
return 1;
48+
}
49+
...
50+
}
51+
```
52+
Here the values of specialization constants `SC0` and `SC1` are changed on
53+
every loop iteration. All what's needed is re-creating a `program` class
54+
instance, setting new values and rebuilding it via
55+
`program::build_with_kernel_type`. JIT compiler will effectively replace
56+
`sc0.get()` and `sc1.get()` within thhe device code with the corresponding
57+
constant values (`sc_vals[i][0]` and `sc_vals[i][1]`). Full runnable example
58+
can be found on
59+
[github](https://github.com/intel/llvm/blob/sycl/sycl/test/spec_const/spec_const_redefine.cpp).
60+
61+
Specialization constants can be used in programs compiled Ahead-Of-Time, in this
62+
case a specialization constant takes default value for its type (as specified by
63+
[C++ standard](https://en.cppreference.com/w/cpp/language/value_initialization)).
64+
65+
#### Limitations
66+
- The implementation does not support the `template <unsigned NID> struct spec_constant_id`
67+
API design for interoperability with OpenCL - to set specializataion constants
68+
in SYCL programs originating from external SPIRV modules and wrapped by OpenCL
69+
program objects. In SPIRV/OpenCL specialization constants are identified by an
70+
integer number, and the `spec_constant_id` class models that.
71+
- Only primitive numeric types are supported.
72+

0 commit comments

Comments
 (0)