Skip to content

Commit ec34869

Browse files
[SYCL][Docs] Add design document for device aspect traits (#8182)
This commit adds a design document for the `any_device_has` and `all_devices_have` SYCL 2020 traits. --------- Signed-off-by: Larsen, Steffen <steffen.larsen@intel.com>
1 parent b0bfdfa commit ec34869

File tree

3 files changed

+141
-0
lines changed

3 files changed

+141
-0
lines changed
Lines changed: 130 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,130 @@
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`.
11+
12+
The design of these traits is inspired by the implementation of the
13+
[sycl\_ext\_oneapi\_device\_if][2] and
14+
[sycl\_ext\_oneapi\_device\_architecture][3] extensions as described in
15+
[DeviceIf.md][4]. Additionally, it leverages part of the design for optional
16+
kernel features, as described in [OptionalDeviceFeatures.md][5].
17+
18+
## Changes to the compiler driver
19+
20+
Using the `-fsycl-targets` options introduced in [DeviceIf.md][4] and the
21+
configuration file introduced in [OptionalDeviceFeatures.md][5], the compiler
22+
driver finds the set of all aspects supported by each specified target. Note
23+
that in this section we refer to aspects as their integral representation as
24+
specified in the device headers rather than by the names specified in the
25+
[SYCL 2020 specification][1].
26+
27+
For each target $t$ in `-fsycl-targets`, let $A^{any}_t$ be the set of aspects
28+
supported by any device supporting $t$ and let $A^{all}_t$ be the set of aspects
29+
supported by all devices supporting $t$. These sets are defined as follows:
30+
* If $t$ has an entry in the configuration file, $A^{all}_t$ is the same as the
31+
`aspects` list in that entry.
32+
* If $t$ does not have an entry in the configuration file, $A^{all}_t$ is empty.
33+
* If $t$ has an entry in the configuration file and the entry has a value
34+
`may_support_other_aspects` set to `false`, $A^{any}_t$ is the same as the
35+
`aspects` list in that entry.
36+
* If $t$ does not have an entry the configuration file or the entry has a value
37+
`may_support_other_aspects` set to `true`, $A^{any}_t$ is the set of all
38+
aspects.
39+
40+
For example, the target `intel_gpu_dg1` is supported by a specific device (DG1)
41+
and as such would have an entry in the configuration file with `aspects` being
42+
the set of aspects that device supports. Likewise it would have
43+
`may_support_other_aspects` set to `false` as there will be no other devices
44+
supporting this target, meaning there will never be any devices supporting
45+
the target and supporting anything not in `aspects`. In contrast, the target
46+
`nvidia_gpu_sm_80` is supported by CUDA devices with `sm_80` architecture or
47+
newer, so its entry in the configuration file would have
48+
`may_support_other_aspects` set to `true` to indicate that there could be future
49+
devices that support aspects not in `aspects`, while it is known that all
50+
current and future devices must support the aspects in `aspects`. Lastly, the
51+
default JIT SPIR-V target (`spir64`) should not have an entry in the
52+
configuration file as it cannot guarantee anything about the devices supporting
53+
the target.
54+
55+
When compiling a SYCL program, where $[t1, t2, \ldots, tn]$ are the $n$ targets
56+
specified in `-fsycl-targets` including any targets implicitly added by the
57+
driver, the driver defines the following macros in both host and device
58+
compilation invocations:
59+
* `__SYCL_ALL_DEVICES_HAVE_`$i$`__` as `1` for all $i$ in
60+
${\bigcap}^n_{k=1} A^{all}_{tk}$.
61+
* `__SYCL_ANY_DEVICE_HAS_ANY_ASPECT__` as `1` if
62+
${\bigcup}^n_{k=1} A^{any}_{tk}$ is the set of all aspects.
63+
* `__SYCL_ANY_DEVICE_HAS_`$j$`__` as `1` for all $j$ in
64+
${\bigcup}^n_{k=1} A^{any}_{tk}$ if `__SYCL_ANY_DEVICE_HAS_ANY_ASPECT__` was not
65+
defined.
66+
67+
Note that the need for the `__SYCL_ANY_DEVICE_HAS_ANY_ASPECT__` macro is
68+
due to the special case where the driver finds no configuration for a target and
69+
must assume that there exists some device that supports any given aspect. Since
70+
the driver has no way of knowing all possible aspects, we use a catch-all macro
71+
to denote this case instead. This is not needed for $A^{all}_t$ for any target
72+
$t$, as it will always be a finite set of aspects.
73+
74+
## Changes to the device headers
75+
76+
Using the macros defined by the driver, the device headers define the traits
77+
together with specializations for each aspect:
78+
79+
```c++
80+
namespace sycl {
81+
template <aspect Aspect> all_devices_have;
82+
template<> all_devices_have<aspect::host> : std::bool_constant<__SYCL_ALL_DEVICES_HAVE_0__> {};
83+
template<> all_devices_have<aspect::cpu> : std::bool_constant<__SYCL_ALL_DEVICES_HAVE_1__> {};
84+
template<> all_devices_have<aspect::gpu> : std::bool_constant<__SYCL_ALL_DEVICES_HAVE_2__> {};
85+
...
86+
87+
#ifdef __SYCL_ANY_DEVICE_HAS_ANY_ASPECT__
88+
// Special case where any_device_has is trivially true.
89+
template <aspect Aspect> any_device_has : std::true_t {};
90+
#else
91+
template <aspect Aspect> any_device_has;
92+
template<> any_device_has<aspect::host> : std::bool_constant<__SYCL_ANY_DEVICE_HAS_0__> {};
93+
template<> any_device_has<aspect::cpu> : std::bool_constant<__SYCL_ANY_DEVICE_HAS_1__> {};
94+
template<> any_device_has<aspect::gpu> : std::bool_constant<__SYCL_ANY_DEVICE_HAS_2__> {};
95+
...
96+
#endif // __SYCL_ANY_DEVICE_HAS_ANY_ASPECT__
97+
98+
template <aspect Aspect> constexpr bool all_devices_have_v = all_devices_have<Aspect>::value;
99+
template <aspect Aspect> constexpr bool any_device_has_v = any_device_has<Aspect>::value;
100+
} // namespace sycl
101+
```
102+
103+
Note that the driver may not define macros for all aspects as it only knows the
104+
specified subset from the configuration file. As such the device headers will
105+
have to define any undefined `__SYCL_ANY_DEVICE_HAS_`$i$`__` and
106+
`__SYCL_ALL_DEVICES_HAVE_`$i$`__` as `0` for all aspect values $i$.
107+
108+
Since the specializations need to be explicitly specified, there is a high
109+
probability of mistakes when new aspects are added. To avoid such mistakes, a
110+
SYCL unit-test uses the [aspects.def](../../include/sycl/info/aspects.def) file
111+
to generate test cases, ensuring that specializations exist for all aspects:
112+
113+
```c++
114+
#define __SYCL_ASPECT(ASPECT, ASPECT_VAL) \
115+
constexpr bool CheckAnyDeviceHas##ASPECT = any_devices_has_v<aspect::ASPECT>; \
116+
constexpr bool CheckAllDevicesHave##ASPECT = all_devices_have_v<aspect::ASPECT>;
117+
118+
#include <sycl/info/aspects.def>
119+
120+
#undef __SYCL_ASPECT
121+
```
122+
123+
This relies on the fact that unspecialized variants of `any_device_has` and
124+
`all_devices_have` are undefined.
125+
126+
[1]: <https://registry.khronos.org/SYCL/specs/sycl-2020/html/sycl-2020.html#sec:device-aspects>
127+
[2]: <../extensions/proposed/sycl_ext_oneapi_device_if.asciidoc>
128+
[3]: <../extensions/proposed/sycl_ext_oneapi_device_architecture.asciidoc>
129+
[4]: <DeviceIf.md>
130+
[5]: <OptionalDeviceFeatures.md>

sycl/doc/design/OptionalDeviceFeatures.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -905,15 +905,23 @@ the supported aspects and sub-group sizes. For example:
905905
```
906906
intel_gpu_12_0_0:
907907
aspects: [1, 2, 3]
908+
may_support_other_aspects: false
908909
sub-group-sizes: [8, 16]
909910
intel_gpu_icl:
910911
aspects: [2, 3]
912+
may_support_other_aspects: false
911913
sub-group-sizes: [8, 16]
912914
x86_64_avx512:
913915
aspects: [1, 2, 3, 9, 11]
916+
may_support_other_aspects: false
914917
sub-group-sizes: [8, 32]
915918
```
916919

920+
The device entries have an optional `may_support_other_aspects` sub-key
921+
specifying if a given target may be supported by devices that support aspects
922+
not in the `aspects` list. This is used by the [DeviceAspectTraitDesign.md][10]
923+
design.
924+
917925
The values of the aspects in this configuration file can be the numerical
918926
values from the `enum class aspect` enumeration or the enum identifier itself.
919927

@@ -926,6 +934,8 @@ to select an alternate configuration file.
926934
**TODO**:
927935
* Define location of the default device configuration file.
928936

937+
[10]: <DeviceAspectTraitDesign.md>
938+
929939
#### New features in clang compilation driver and tools
930940

931941
NOTE: the term *device binary image* used to refer to a device

sycl/doc/index.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ Design Documents for the oneAPI DPC++ Compiler
4747
design/ESIMDDesignNotes
4848
design/DeviceIf
4949
design/NonRelocatableDeviceCode
50+
design/DeviceAspectTraitDesign
5051
New OpenCL Extensions <https://github.com/intel/llvm/tree/sycl/sycl/doc/design/opencl-extensions>
5152
New SPIR-V Extensions <https://github.com/intel/llvm/tree/sycl/sycl/doc/design/spirv-extensions>
5253

0 commit comments

Comments
 (0)