This extension introduces a Level Zero backend for Data Parallel C++ (DPC++), which is built on top of Level Zero runtime enabled with the oneAPI Level Zero Specification. The supported targets are Intel GPUs, starting with Gen9.
The Level Zero backend is added to the cl::sycl::backend enumeration with:
enum class backend { // ... level_zero, // ... };
The sections below explain the different ways the Level Zero backend can be selected.
Through an Environment Variable
The SYCL_DEVICE_FILTER environment variable limits the DPC++ runtime to use only a subset of the system's devices. By using level_zero for the backend in SYCL_DEVICE_FILTER, you can select the use of Level Zero as a DPC++ backend. For more information, see the Environment Variables.
Through a Programming API
The Filter Selector extension is described in SYCL* Proposals: Filter Selector. Similar to how the SYCL_DEVICE_FILTER applies filtering to the entire process, this device selector can be used to programmatically select the Level Zero backend.
If the environment variable or filtering device selector is NOT used, the implementation chooses the Level Zero backend for GPU devices that are supported by the installed Level Zero runtime. The serving backend for a DPC++ platform can be queried with the get_backend() member function of the cl::sycl::platform command.
The sections below describe the various interoperabilities that are possible between DPC++ and Level Zero. The application must include the following headers to use any of the inter-operation APIs described in this section. These headers must be included in the order shown:
#include "level_zero/ze_api.h" #include "sycl/backend/level_zero.hpp"
Mapping of DPC++ Objects to Level Zero Handles
These DPC++ objects encapsulate the corresponding Level Zero handles:
DPC++ Object |
Level Zero Handle |
---|---|
Platform |
ze_driver_handle_t |
Device |
ze_device_handle_t |
Context |
ze_context_handle_t |
Queue |
ze_command_queue_handle_t |
Program |
ze_module_handle_t |
Obtaining Built-in Level Zero Handles from DPC++ Objects
The get_native<cl::sycl::backend::level_zero>() member function is how you can use a raw native Level Zero handle to obtain a specific DPC++ object. The function is supported for the DPC++platform, device, context, queue, event and program classes. You can use a free-function defined in the cl::sycl namespace instead of the member function with:
template <backend BackendName, class SyclObjectT> auto get_native(const SyclObjectT &Obj) -> typename interop<BackendName, SyclObjectT>::type;
Construct a DPC++ Object from a Level Zero Handle
The following free functions, defined in the cl::sycl::level_zero namespace, allow an application to create a DPC++ object that encapsulates a corresponding Level Zero object:
Level Zero Interoperability Function | Description |
---|---|
make<platform>(ze_driver_handle_t); | Constructs a DPC++ platform instance with ze_driver_handle_t. |
make<device>(const platform &, ze_device_handle_t); | Constructs a DPC++ device instance with ze_device_handle_t. The platform argument gives a DPC++ platform, which encapsulates a Level Zero driver that supports the passed Level Zero device. |
make<context>(const vector_class<device> &, ze_context_handle_t); | Constructs a DPC++ context instance with ze_context_handle_t. The context is created against the devices that are passed in. You must give at least one device and all the devices must be from the same DPC++ platform (from the same Level Zero driver). |
make<queue>(const context &, ze_command_queue_handle_t); | Constructs a DPC++ queue instance with ze_command_queue_handle_t. The context argument must be a valid DPC++ context that encapsulates a Level Zero context. The queue is attached to the first device in the passed DPC++ context. |
make<program>(const context &, ze_module_handle_t); | Constructs a DPC++ program instance with ze_module_handle_t. The context argument must be a valid DPC++ that encapsulates a Level Zero context. The Level Zero module must be fully linked (example: it does not require further linking through zeModuleDynamicLink) and then the DPC++ program is created in the linked state. |
Level Zero Handle Ownership and Thread-safety
The Level Zero runtime does not do reference-counting of its objects, so it is crucial to adhere to these practices of how Level Zero handles are managed: