diff --git a/dpctl/_backend.pxd b/dpctl/_backend.pxd index ec0c428247..e0c92b6ea8 100644 --- a/dpctl/_backend.pxd +++ b/dpctl/_backend.pxd @@ -97,6 +97,8 @@ cdef extern from "syclinterface/dpctl_sycl_enum_types.h": _usm_atomic_shared_allocations 'usm_atomic_shared_allocations', _host_debuggable 'host_debuggable', _emulated 'emulated', + _is_component 'is_component', + _is_composite 'is_composite', ctypedef enum _partition_affinity_domain_type 'DPCTLPartitionAffinityDomainType': _not_applicable 'not_applicable', @@ -216,6 +218,8 @@ cdef extern from "syclinterface/dpctl_sycl_device_interface.h": cdef uint32_t DPCTLDevice_GetPartitionMaxSubDevices(const DPCTLSyclDeviceRef DRef) cdef uint32_t DPCTLDevice_GetMaxClockFrequency(const DPCTLSyclDeviceRef DRef) cdef uint64_t DPCTLDevice_GetMaxMemAllocSize(const DPCTLSyclDeviceRef DRef) + cdef DPCTLSyclDeviceRef DPCTLDevice_GetCompositeDevice(const DPCTLSyclDeviceRef DRef) + cdef DPCTLDeviceVectorRef DPCTLDevice_GetComponentDevices(const DPCTLSyclDeviceRef DRef) cdef extern from "syclinterface/dpctl_sycl_device_manager.h": diff --git a/dpctl/_sycl_device.pyx b/dpctl/_sycl_device.pyx index f8d59a56b0..53772102b6 100644 --- a/dpctl/_sycl_device.pyx +++ b/dpctl/_sycl_device.pyx @@ -32,6 +32,8 @@ from ._backend cimport ( # noqa: E211 DPCTLDevice_CreateSubDevicesEqually, DPCTLDevice_Delete, DPCTLDevice_GetBackend, + DPCTLDevice_GetComponentDevices, + DPCTLDevice_GetCompositeDevice, DPCTLDevice_GetDeviceType, DPCTLDevice_GetDriverVersion, DPCTLDevice_GetGlobalMemCacheLineSize, @@ -795,6 +797,32 @@ cdef class SyclDevice(_SyclDevice): cdef _aspect_type AT = _aspect_type._emulated return DPCTLDevice_HasAspect(self._device_ref, AT) + @property + def is_component(self): + """ Returns ``True`` if this device is a component device, ``False`` + otherwise. A device with this aspect will have a composite device + from which it is descended. + + Returns: + bool: + Indicates if device is a component device. + """ + cdef _aspect_type AT = _aspect_type._is_component + return DPCTLDevice_HasAspect(self._device_ref, AT) + + + @property + def is_composite(self): + """ Returns ``True`` if this device is a composite device, ``False`` + otherwise. A device with this aspect contains component devices. + + Returns: + bool: + Indicates if device is a composite device. + """ + cdef _aspect_type AT = _aspect_type._is_composite + return DPCTLDevice_HasAspect(self._device_ref, AT) + @property def image_2d_max_width(self): """ Returns the maximum width of a 2D image or 1D image in pixels. @@ -1728,6 +1756,41 @@ cdef class SyclDevice(_SyclDevice): return None return SyclDevice._create(pDRef) + @property + def composite_device(self): + """ The composite device for a component device, or None for a non-component device. + + Returns: + dpctl.SyclDevice: + The composite :class:`dpctl.SyclDevice` instance for a + component device, or ``None`` for a non-component device. + """ + cdef DPCTLSyclDeviceRef cDRef = NULL + cDRef = DPCTLDevice_GetCompositeDevice(self._device_ref) + if (cDRef is NULL): + return None + return SyclDevice._create(cDRef) + + def component_devices(self): + """ Returns a list of component devices contained in this SYCL device. + + The returned list will be empty if this SYCL device is not a composite + device, i.e., if `is_composite` is ``False``. + + Returns: + List[:class:`dpctl.SyclDevice`]: + List of component devices. + + Raises: + dpctl.SyclSubdeviceCreationError: + if sub-devices can not be created. + """ + cdef DPCTLDeviceVectorRef cDVRef = NULL + cDVRef = DPCTLDevice_GetComponentDevices(self._device_ref) + if cDVRef is NULL: + raise ValueError("Internal error: NULL device vector encountered") + return _get_devices(cDVRef) + @property def profiling_timer_resolution(self): """ Profiling timer resolution. diff --git a/libsyclinterface/helper/source/dpctl_utils_helper.cpp b/libsyclinterface/helper/source/dpctl_utils_helper.cpp index fe3bbd86cb..ca4254d60c 100644 --- a/libsyclinterface/helper/source/dpctl_utils_helper.cpp +++ b/libsyclinterface/helper/source/dpctl_utils_helper.cpp @@ -335,6 +335,10 @@ aspect DPCTL_DPCTLAspectTypeToSyclAspect(DPCTLSyclAspectType AspectTy) return aspect::host_debuggable; case DPCTLSyclAspectType::emulated: return aspect::emulated; + case DPCTLSyclAspectType::is_component: + return aspect::ext_oneapi_is_component; + case DPCTLSyclAspectType::is_composite: + return aspect::ext_oneapi_is_composite; default: throw std::runtime_error("Unsupported aspect type"); } @@ -381,6 +385,10 @@ DPCTLSyclAspectType DPCTL_SyclAspectToDPCTLAspectType(aspect Aspect) return DPCTLSyclAspectType::host_debuggable; case aspect::emulated: return DPCTLSyclAspectType::emulated; + case aspect::ext_oneapi_is_composite: + return DPCTLSyclAspectType::is_composite; + case aspect::ext_oneapi_is_component: + return DPCTLSyclAspectType::is_component; default: throw std::runtime_error("Unsupported aspect type"); } diff --git a/libsyclinterface/include/syclinterface/dpctl_sycl_device_interface.h b/libsyclinterface/include/syclinterface/dpctl_sycl_device_interface.h index 5f940600ec..6fddb2967f 100644 --- a/libsyclinterface/include/syclinterface/dpctl_sycl_device_interface.h +++ b/libsyclinterface/include/syclinterface/dpctl_sycl_device_interface.h @@ -766,4 +766,30 @@ __dpctl_keep size_t * DPCTLDevice_GetSubGroupSizes(__dpctl_keep const DPCTLSyclDeviceRef DRef, size_t *res_len); +/*! + * @brief Wrapper over + * device.get_info + * + * @param DRef Opaque pointer to a sycl::device + * @return Returns an opaque pointer to the composite device for a + * component device, or nullptr if the device is not a component device. + */ +DPCTL_API +__dpctl_give DPCTLSyclDeviceRef +DPCTLDevice_GetCompositeDevice(__dpctl_keep const DPCTLSyclDeviceRef DRef); + +/*! + * @brief Returns a vector of component devices that are contained by the + * provided composite device. If the device is not a composite device, + * returns an empty vector. + * + * @param DRef Opaque pointer to a ``sycl::device`` + * @return A #DPCTLDeviceVectorRef containing component + * #DPCTLSyclDeviceRef objects + * @ingroup DeviceInterface + */ +DPCTL_API +__dpctl_give DPCTLDeviceVectorRef +DPCTLDevice_GetComponentDevices(__dpctl_keep const DPCTLSyclDeviceRef DRef); + DPCTL_C_EXTERN_C_END diff --git a/libsyclinterface/include/syclinterface/dpctl_sycl_enum_types.h b/libsyclinterface/include/syclinterface/dpctl_sycl_enum_types.h index 6c7f05e195..9d60b08809 100644 --- a/libsyclinterface/include/syclinterface/dpctl_sycl_enum_types.h +++ b/libsyclinterface/include/syclinterface/dpctl_sycl_enum_types.h @@ -129,7 +129,9 @@ typedef enum usm_atomic_host_allocations, usm_atomic_shared_allocations, host_debuggable, - emulated + emulated, + is_component, + is_composite } DPCTLSyclAspectType; /*! diff --git a/libsyclinterface/source/dpctl_sycl_device_interface.cpp b/libsyclinterface/source/dpctl_sycl_device_interface.cpp index 2f0fb63b3b..d72dd5ed46 100644 --- a/libsyclinterface/source/dpctl_sycl_device_interface.cpp +++ b/libsyclinterface/source/dpctl_sycl_device_interface.cpp @@ -849,3 +849,56 @@ DPCTLDevice_GetSubGroupSizes(__dpctl_keep const DPCTLSyclDeviceRef DRef, } return sizes; } + +__dpctl_give DPCTLDeviceVectorRef +DPCTLDevice_GetComponentDevices(__dpctl_keep const DPCTLSyclDeviceRef DRef) +{ + using vecTy = std::vector; + vecTy *ComponentDevicesVectorPtr = nullptr; + if (DRef) { + auto D = unwrap(DRef); + try { + auto componentDevices = + D->get_info(); + ComponentDevicesVectorPtr = new vecTy(); + for (const auto &cd : componentDevices) { + ComponentDevicesVectorPtr->emplace_back( + wrap(new device(cd))); + } + } catch (std::exception const &e) { + delete ComponentDevicesVectorPtr; + error_handler(e, __FILE__, __func__, __LINE__); + return nullptr; + } + } + return wrap(ComponentDevicesVectorPtr); +} + +__dpctl_give DPCTLSyclDeviceRef +DPCTLDevice_GetCompositeDevice(__dpctl_keep const DPCTLSyclDeviceRef DRef) +{ + auto D = unwrap(DRef); + if (D) { + bool is_component = false; + try { + is_component = D->has(sycl::aspect::ext_oneapi_is_component); + } catch (std::exception const &e) { + error_handler(e, __FILE__, __func__, __LINE__); + return nullptr; + } + if (!is_component) + return nullptr; + try { + const auto &compositeDevice = + D->get_info(); + return wrap(new device(compositeDevice)); + } catch (std::exception const &e) { + error_handler(e, __FILE__, __func__, __LINE__); + return nullptr; + } + } + else + return nullptr; +}