Skip to content

Commit e2e02e2

Browse files
committed
[SYCL][Docs] Add design document for device aspect traits
This commit adds a design document for the `any_device_has` and `all_devices_have` SYCL 2020 traits. Signed-off-by: Larsen, Steffen <[email protected]>
1 parent 7f24cac commit e2e02e2

File tree

1 file changed

+117
-0
lines changed

1 file changed

+117
-0
lines changed
Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
# Implementation design for `sycl::any_device_has` and `sycl::all_devices_have`
2+
3+
This design document describes the implementation of the SYCL 2020 device aspect
4+
traits `any_device_has` and `all_devices_have` as described in the
5+
[SYCL 2020 Specification Rev. 6 Section 4.6.4.3][1].
6+
7+
In summary, `any_device_has<aspect>` and `all_devices_have<aspect>` must inherit
8+
from either `std::true_t` or `std::false_t` depending on whether the
9+
corresponding compilation environment can guarantee that any and all the
10+
supported devices support the `aspect`. Since DPC++ allows for compiling for
11+
multiple targets, these traits can be different when compiling for the
12+
individual targets and on host.
13+
14+
The design of these traits is inspired by the implementation of the
15+
[sycl\_ext\_oneapi\_device\_if][2] and
16+
[sycl\_ext\_oneapi\_device\_architecture][3] extensions as described in
17+
[DeviceIf.md][4]. Additionally, it leverages part of the design for optional
18+
kernel features, as described in [OptionalDeviceFeatures.md][5].
19+
20+
## Changes to the compiler driver
21+
22+
Using the `-fsycl-targets` options introduced in [DeviceIf.md][4] and the
23+
configuration file introduced in [OptionalDeviceFeatures.md][5], the compiler
24+
driver finds the set of all aspects supported by each specified target. Note
25+
that in this section we refer to aspects as their integral representation as
26+
specified in the device headers rather than by the names specified in the
27+
[SYCL 2020 specification][1].
28+
29+
For each target $t$ in `-fsycl-targets`, let $A^{any}_t$ be the set of aspects
30+
supported by any device supporting $t$ and let $A^{all}_t$ be the set of aspects
31+
supported by all devices supporting $t$. If $t$ has an entry in the
32+
configuration file, these sets are defined by the `aspects` list in that entry
33+
and $A^{any}_t = A^{all}_t$. If there is no entry for $t$ in the configuration
34+
file, then $A^{any}_t$ is the set of all aspects and $A^{all}_t = \emptyset$.
35+
36+
In the device-side compilation of a SYCL program for $t$ the driver defines the
37+
following macros:
38+
* `__SYCL_ALL_DEVICES_HAVE_`$i$`__` as `1` for all $i$ in $A^{all}_t$.
39+
* `__SYCL_ANY_DEVICE_HAS_ANY_ASPECT__` as `1` if $A^{any}_t$ is the set of all
40+
aspects.
41+
* `__SYCL_ANY_DEVICE_HAS_`$j$`__` as `1` for all $j$ in $A^{any}_t$ if
42+
`__SYCL_ANY_DEVICE_HAS_ANY_ASPECT__` was not defined.
43+
44+
In the host-side compilation of a SYCL program, where $[t1, t2, \ldots, tn]$ are
45+
the $n$ targets specified in `-fsycl-targets`, the driver defines the following
46+
macros:
47+
* `__SYCL_ALL_DEVICES_HAVE_`$i$`__` as `1` for all $i$ in
48+
${\bigcap}^n_{k=1} A^{all}_{tk}$.
49+
* `__SYCL_ANY_DEVICE_HAS_ANY_ASPECT__` as `1` if
50+
${\bigcup}^n_{k=1} A^{any}_{tk}$ is the set of all aspects.
51+
* `__SYCL_ANY_DEVICE_HAS_`$j$`__` as `1` for all $j$ in
52+
${\bigcup}^n_{k=1} A^{any}_{tk}$ if `__SYCL_ANY_DEVICE_HAS_ANY_ASPECT__` was not
53+
defined.
54+
55+
Note that the need for the `__SYCL_ANY_DEVICE_HAS_ANY_ASPECT__` macro is
56+
due to the special case where the driver finds no configuration for a target and
57+
must assume that there exists some device that supports any given aspect. Since
58+
the driver has no way of knowing all possible aspects, we use a catch-all macro
59+
to denote this case instead. This is not needed for $A^{all}_t$ for any target
60+
$t$, as the driver will always know all relevant aspects.
61+
62+
## Changes to the device headers
63+
64+
Using the macros defined by the driver, the device headers define the traits
65+
together with specializations for each aspect:
66+
67+
```c++
68+
namespace sycl {
69+
template <aspect Aspect> all_devices_have;
70+
template<> all_devices_have<aspect::host> : std::bool_constant<__SYCL_ALL_DEVICES_HAVE_0__ + 0> {};
71+
template<> all_devices_have<aspect::cpu> : std::bool_constant<__SYCL_ALL_DEVICES_HAVE_1__ + 0> {};
72+
template<> all_devices_have<aspect::gpu> : std::bool_constant<__SYCL_ALL_DEVICES_HAVE_2__ + 0> {};
73+
...
74+
75+
#ifdef __SYCL_ANY_DEVICE_HAS_ANY_ASPECT__
76+
// Special case where any_device_has is trivially true.
77+
template <aspect Aspect> any_device_has : std::true_t {};
78+
#else
79+
template <aspect Aspect> any_device_has;
80+
template<> any_device_has<aspect::host> : std::bool_constant<__SYCL_ANY_DEVICE_HAS_0__ + 0> {};
81+
template<> any_device_has<aspect::cpu> : std::bool_constant<__SYCL_ANY_DEVICE_HAS_1__ + 0> {};
82+
template<> any_device_has<aspect::gpu> : std::bool_constant<__SYCL_ANY_DEVICE_HAS_2__ + 0> {};
83+
...
84+
#endif // __SYCL_ANY_DEVICE_HAS_ANY_ASPECT__
85+
86+
template <aspect Aspect> constexpr bool all_devices_have_v = all_devices_have<Aspect>::value;
87+
template <aspect Aspect> constexpr bool any_device_has_v = any_device_has<Aspect>::value;
88+
} // namespace sycl
89+
```
90+
91+
Note that the driver may not define macros for all aspects, so the `+ 0` is
92+
used to ensure the boolean constant value of the specializations become `false`
93+
when the corresponding macro is undefined.
94+
95+
Since the specializations need to be explicitly specified, there is a high
96+
probability of mistakes when new aspects are added. To avoid such mistakes, a
97+
SYCL unit-test uses the [aspects.def](../../include/sycl/info/aspects.def) file
98+
to generate test cases, ensuring that specializations exist for all aspects:
99+
100+
```c++
101+
#define __SYCL_ASPECT(ASPECT, ASPECT_VAL) \
102+
constexpr bool CheckAnyDeviceHas##ASPECT = any_devices_has_v<aspect::ASPECT>; \
103+
constexpr bool CheckAllDevicesHave##ASPECT = all_devices_have_v<aspect::ASPECT>;
104+
105+
#include <sycl/info/aspects.def>
106+
107+
#undef __SYCL_ASPECT
108+
```
109+
110+
This relies on the fact that unspecialized variants of `any_device_has` and
111+
`all_devices_have` are undefined.
112+
113+
[1]: <https://registry.khronos.org/SYCL/specs/sycl-2020/html/sycl-2020.html#sec:device-aspects>
114+
[2]: <../extensions/proposed/sycl_ext_oneapi_device_if.asciidoc>
115+
[3]: <../extensions/proposed/sycl_ext_oneapi_device_architecture.asciidoc>
116+
[4]: <DeviceIf.md>
117+
[5]: <OptionalDeviceFeatures.md>

0 commit comments

Comments
 (0)