Skip to content

Commit 6344ead

Browse files
[SYCL] kernel_compiler support of OpenCL queries (#12888)
This PR both includes and realizes the new specification here originally drafted here: #11994 --------- Co-authored-by: Greg Lueck <gregory.m.lueck@intel.com>
1 parent 3bb5f40 commit 6344ead

15 files changed

+672
-72
lines changed

sycl/doc/extensions/experimental/sycl_ext_oneapi_kernel_compiler_opencl.asciidoc

Lines changed: 183 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,11 @@ This extension is written against the SYCL 2020 revision 8 specification.
4141
All references below to the "core SYCL specification" or to section numbers in
4242
the SYCL specification refer to that revision.
4343

44+
This extension references sections of the OpenCL specification version 3.0.14.
45+
References below to the "OpenCL specification" refer to that version.
46+
It also references sections of the OpenCL C specification version 3.0.14.
47+
References below to the "OpenCL C specification" refer to that version.
48+
4449
This extension also depends on the following other SYCL extensions:
4550

4651
* link:../experimental/sycl_ext_oneapi_kernel_compiler.asciidoc[
@@ -114,6 +119,140 @@ As a result, the application must use the overload of
114119
`create_kernel_bundle_from_source` taking `std::string` when creating a kernel
115120
bundle from this language.
116121

122+
=== Queries
123+
124+
==== Version type
125+
126+
This extension adds the following type and constant definitions, which help
127+
identify the version of OpenCL and its extensions.
128+
129+
|====
130+
a|
131+
[frame=all,grid=none]
132+
!====
133+
a!
134+
[source]
135+
----
136+
namespace sycl::ext::oneapi::experimental {
137+
138+
struct cl_version {
139+
unsigned major:10;
140+
unsigned minor:10;
141+
unsigned patch:12;
142+
};
143+
144+
inline constexpr cl_version opencl_c_1_0 = {1,0,0};
145+
inline constexpr cl_version opencl_c_1_1 = {1,1,0};
146+
inline constexpr cl_version opencl_c_1_2 = {1,2,0};
147+
inline constexpr cl_version opencl_c_2_0 = {2,0,0};
148+
inline constexpr cl_version opencl_c_3_0 = {3,0,0};
149+
150+
} // namespace ext::oneapi::experimental
151+
----
152+
!====
153+
154+
The meaning of the `major`, `minor`, and `patch` values are defined by section
155+
3.4.3.1 "Versions" of the OpenCL specification.
156+
157+
The constant values (e.g. `opencl_c_1_0`) are shorthands that identify various
158+
OpenCL C versions.
159+
160+
[_Note:_ The OpenCL C version is not the same as the the OpenCL version because
161+
some minor releases of OpenCL did not change the OpenCL C language.
162+
For example, there is no version of OpenCL C named "2.1" even though there is
163+
an OpenCL version named "2.1".
164+
_{endnote}_]
165+
|====
166+
167+
==== New member functions for the device class
168+
169+
This extension also adds the following member functions to the `device` class,
170+
which allow the application to query which OpenCL features and extensions the
171+
device supports.
172+
173+
|====
174+
a|
175+
[frame=all,grid=none]
176+
!====
177+
a!
178+
[source]
179+
----
180+
class device {
181+
bool ext_oneapi_supports_cl_c_version(
182+
const ext::oneapi::experimental::cl_version &version) const;
183+
};
184+
----
185+
!====
186+
187+
_Returns:_ The value `true` only if the device supports kernel bundles written
188+
in the OpenCL C version identified by `version`.
189+
Returns `false` if the device does not support kernel bundles written in
190+
`source_language::opencl`.
191+
192+
a|
193+
[frame=all,grid=none]
194+
!====
195+
a!
196+
[source]
197+
----
198+
class device {
199+
bool ext_oneapi_supports_cl_c_feature(const std::string &name) const;
200+
};
201+
----
202+
!====
203+
204+
_Returns:_ The value `true` only if the device supports kernel bundles using
205+
the OpenCL C feature whose feature macro is `name`.
206+
The set of possible feature macros are defined in section 6.2.1 "Features" of
207+
the OpenCL C specification.
208+
Returns `false` if the device does not support kernel bundles written in
209+
`source_language::opencl`.
210+
211+
a|
212+
[frame=all,grid=none]
213+
!====
214+
a!
215+
[source]
216+
----
217+
class device {
218+
bool ext_oneapi_supports_cl_extension(const std::string &name,
219+
ext::oneapi::experimental::cl_version *version = nullptr) const;
220+
};
221+
----
222+
!====
223+
224+
_Effects:_ If the device supports kernel bundles using the OpenCL extension
225+
identified by `name` and if `version` is not a null pointer, the supported
226+
version of the extension is written to `version`.
227+
228+
_Returns:_ The value `true` only if the device supports kernel bundles using
229+
the OpenCL extension identified by `name`.
230+
Returns `false` if the device does not support kernel bundles written in
231+
`source_language::opencl`.
232+
233+
a|
234+
[frame=all,grid=none]
235+
!====
236+
a!
237+
[source]
238+
----
239+
class device {
240+
std::string ext_oneapi_cl_profile() const;
241+
};
242+
----
243+
!====
244+
245+
_Returns:_ If the device supports kernel bundles written in
246+
`source_language::opencl`, returns the name of the OpenCL profile that is
247+
supported.
248+
The profile name is the same string that is returned by the query
249+
`CL_DEVICE_PROFILE`, as defined in section 4.2 "Querying Devices" of the OpenCL
250+
specification.
251+
If the device does not support kernel bundles written in
252+
`source_language::opencl`, returns the empty string.
253+
254+
|====
255+
117256
=== Build options
118257

119258
The `build_options` property accepts any of the compiler or linker options
@@ -122,6 +261,13 @@ creating an OpenCL library.
122261
The kernel compiler can be used to create an OpenCL program, but not an OpenCL
123262
library.
124263

264+
The `-cl-std=` option is required when compiling kernels that use OpenCL C 2.0
265+
or OpenCL C 3.0 features.
266+
Otherwise, the implementation defaults to the highest OpenCL C 1.x language
267+
version that each device supports.
268+
See section 5.8.6.5 "Options Controlling the OpenCL C version" of the OpenCL
269+
specification for details.
270+
125271
=== Obtaining a kernel
126272

127273
OpenCL C kernel functions do not support {cpp} features like overloads or
@@ -187,7 +333,9 @@ _{endnote}_]
187333
|===
188334

189335

190-
== Example
336+
== Examples
337+
338+
=== Simple example
191339

192340
The following example shows a simple SYCL program that defines an OpenCL C
193341
kernel as a string and then compiles and launches it.
@@ -243,52 +391,45 @@ int main() {
243391
}
244392
```
245393

394+
=== Querying supported features and extensions
246395

247-
== Issues
248-
249-
* How should we expose the difference between OpenCL C versions?
250-
It seems like there are two aspects to the problem.
251-
Applications need some way to query which versions the backend (or device)
252-
supports.
253-
Applications also need some way to tell the runtime which version the kernel
254-
is written in.
255-
+
256-
--
257-
One option is to define separate enumerators in `source_language` for each
258-
version like this:
396+
This example demonstrates how to query the version of OpenCL C that is
397+
supported, how to query the supported features, and how to query the
398+
supported extensions.
259399

260400
```
261-
enum class source_language : /*unspecified*/ {
262-
opencl_1_0,
263-
opencl_1_1,
264-
opencl_2_0,
265-
opencl_3_0,
266-
};
401+
#include <iostream>
402+
#include <sycl/sycl.hpp>
403+
namespace syclex = sycl::ext::oneapi::experimental;
404+
405+
int main() {
406+
sycl::queue q;
407+
sycl::device d = q.get_device();
408+
409+
if (d.ext_oneapi_can_compile(syclex::source_language::opencl))
410+
std::cout << "Device supports online compilation of OpenCL C kernels\n";
411+
412+
if (d.ext_oneapi_supports_cl_c_version(syclex::opencl_c_3_0))
413+
std::cout << "Device supports online compilation with OpenCL C 3.0\n";
414+
415+
if (d.ext_oneapi_supports_cl_c_feature("__opencl_c_fp64"))
416+
std::cout << "Device supports online compilation with 64-bit FP in OpenCL C\n";
417+
418+
syclex::cl_version version;
419+
if (d.ext_oneapi_supports_cl_extension("cl_intel_bfloat16_conversions", &version)) {
420+
std::cout << "Device supports online compilation of OpenCL C with bfloat16 "
421+
"conversions (version: " << version.major << "." << version.minor << "." <<
422+
version.patch << ")\n";
423+
}
424+
425+
if (d.ext_oneapi_cl_profile() == "FULL_PROFILE")
426+
std::cout << "Device supports online compilation with the OpenCL full profile\n";
427+
428+
}
267429
```
268430

269-
Applications could then query the supported versions via
270-
`is_source_kernel_bundle_supported`, and applications would identify the
271-
version of their kernel string via the `lang` parameter to
272-
`create_kernel_bundle_from_source`.
273-
274-
Alternatively, this extension could define just a single language enumerator
275-
(`opencl`), but also provide as separate query to get the supported OpenCL C
276-
versions.
277-
When building a kernel bundle, applications would be required to pass "-cl-std"
278-
via the `build_options` property in order to identify the OpenCL C version of
279-
their source string.
280-
--
281-
282-
* How can an application determine the OpenCL C optional features that are
283-
supported and the extensions that are supported?
284-
One option is to require the application to use OpenCL APIs for these
285-
queries.
286-
This seems better than duplicating these queries into this extension.
287-
However, this assumes the application is running with an OpenCL backend.
288-
Do we want to support the use of OpenCL C kernels also with the Level Zero
289-
backend?
290-
Currently, the online_compiler does support this case (but it provides no way
291-
to query about optional features or extensions).
431+
432+
== Issues
292433

293434
* Do we need to document some restrictions on the OpenCL C
294435
https://registry.khronos.org/OpenCL/specs/3.0-unified/html/OpenCL_C.html#work-item-functions[

sycl/include/sycl/device.hpp

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
#include <sycl/device_selector.hpp>
2424
#include <sycl/ext/oneapi/experimental/device_architecture.hpp>
2525
#include <sycl/info/info_desc.hpp>
26+
#include <sycl/kernel_bundle_enums.hpp>
2627
#include <sycl/platform.hpp>
2728

2829
#include <cstddef>
@@ -293,6 +294,57 @@ class __SYCL_EXPORT device : public detail::OwnerLessBase<device> {
293294
bool
294295
ext_oneapi_architecture_is(ext::oneapi::experimental::arch_category category);
295296

297+
/// kernel_compiler extension
298+
299+
/// Indicates if the device can compile a kernel for the given language.
300+
///
301+
/// \param Language is one of the values from the
302+
/// kernel_bundle::source_language enumeration described in the
303+
/// sycl_ext_oneapi_kernel_compiler specification
304+
///
305+
/// \return true only if the device supports kernel bundles written in the
306+
/// source language `lang`.
307+
bool
308+
ext_oneapi_can_compile(ext::oneapi::experimental::source_language Language);
309+
310+
/// Indicates if the device supports a given feature when compiling the OpenCL
311+
/// C language
312+
///
313+
/// \param Feature
314+
///
315+
/// \return true if supported
316+
bool ext_oneapi_supports_cl_c_feature(const std::string &Feature);
317+
318+
/// Indicates if the device supports kernel bundles written in a particular
319+
/// OpenCL C version
320+
///
321+
/// \param Version
322+
///
323+
/// \return true only if the device supports kernel bundles written in the
324+
/// version identified by `Version`.
325+
bool ext_oneapi_supports_cl_c_version(
326+
const ext::oneapi::experimental::cl_version &Version) const;
327+
328+
/// If the device supports kernel bundles using the OpenCL extension
329+
/// identified by `name` and if `version` is not a null pointer, the supported
330+
/// version of the extension is written to `version`.
331+
///
332+
/// \return true only if the device supports kernel bundles using the OpenCL
333+
/// extension identified by `name`.
334+
bool ext_oneapi_supports_cl_extension(
335+
const std::string &name,
336+
ext::oneapi::experimental::cl_version *version = nullptr) const;
337+
338+
/// Retrieve the OpenCl Device Profile
339+
///
340+
/// \return If the device supports kernel bundles written in
341+
/// `source_language::opencl`, returns the name of the OpenCL profile that is
342+
/// supported. The profile name is the same string that is returned by the
343+
/// query `CL_DEVICE_PROFILE`, as defined in section 4.2 "Querying Devices" of
344+
/// the OpenCL specification. If the device does not support kernel bundles
345+
/// written in `source_language::opencl`, returns the empty string.
346+
std::string ext_oneapi_cl_profile() const;
347+
296348
// TODO: Remove this diagnostics when __SYCL_WARN_IMAGE_ASPECT is removed.
297349
#if defined(__clang__)
298350
#pragma clang diagnostic pop

sycl/include/sycl/kernel_bundle_enums.hpp

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,19 @@ namespace ext::oneapi::experimental {
2222

2323
enum class source_language : int { opencl = 0, spirv = 1 /* sycl, cuda */ };
2424

25+
// opencl versions
26+
struct cl_version {
27+
unsigned major : 10;
28+
unsigned minor : 10;
29+
unsigned patch : 12;
30+
};
31+
32+
inline constexpr cl_version opencl_c_1_0 = {1, 0, 0};
33+
inline constexpr cl_version opencl_c_1_1 = {1, 1, 0};
34+
inline constexpr cl_version opencl_c_1_2 = {1, 2, 0};
35+
inline constexpr cl_version opencl_c_2_0 = {2, 0, 0};
36+
inline constexpr cl_version opencl_c_3_0 = {3, 0, 0};
37+
2538
} // namespace ext::oneapi::experimental
2639

2740
} // namespace _V1

sycl/source/detail/device_impl.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -707,6 +707,15 @@ bool device_impl::isGetDeviceAndHostTimerSupported() {
707707
return Result != PI_ERROR_INVALID_OPERATION;
708708
}
709709

710+
bool device_impl::extOneapiCanCompile(
711+
ext::oneapi::experimental::source_language Language) {
712+
try {
713+
return is_source_kernel_bundle_supported(getBackend(), Language);
714+
} catch (sycl::exception &) {
715+
return false;
716+
}
717+
}
718+
710719
} // namespace detail
711720
} // namespace _V1
712721
} // namespace sycl

sycl/source/detail/device_impl.hpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -251,6 +251,8 @@ class device_impl {
251251
return false;
252252
}
253253

254+
bool extOneapiCanCompile(ext::oneapi::experimental::source_language Language);
255+
254256
/// Gets the current device timestamp
255257
/// @throw sycl::feature_not_supported if feature is not supported on device
256258
uint64_t getCurrentDeviceTime();

0 commit comments

Comments
 (0)