diff --git a/dpctl/__init__.py b/dpctl/__init__.py index 5f57cdf90e..42d61207de 100644 --- a/dpctl/__init__.py +++ b/dpctl/__init__.py @@ -65,7 +65,12 @@ backend_type, device_type, event_status_type, + fp_config, global_mem_cache_type, + local_mem_type, + memory_order, + memory_scope, + partition_property, ) __all__ = [ @@ -118,6 +123,11 @@ "backend_type", "event_status_type", "global_mem_cache_type", + "local_mem_type", + "partition_property", + "fp_config", + "memory_order", + "memory_scope", ] __all__ += [ "get_include", diff --git a/dpctl/_backend.pxd b/dpctl/_backend.pxd index 30710b3779..3fc385ce85 100644 --- a/dpctl/_backend.pxd +++ b/dpctl/_backend.pxd @@ -31,6 +31,7 @@ cdef extern from "syclinterface/dpctl_error_handler_type.h": cdef extern from "syclinterface/dpctl_utils.h": cdef void DPCTLCString_Delete(const char *str) cdef void DPCTLSize_t_Array_Delete(size_t *arr) + cdef void DPCTLInt_Array_Delete(int *arr) cdef extern from "syclinterface/dpctl_sycl_enum_types.h": @@ -128,6 +129,41 @@ cdef extern from "syclinterface/dpctl_sycl_enum_types.h": _MEM_CACHE_TYPE_READ_ONLY "DPCTL_MEM_CACHE_TYPE_READ_ONLY" _MEM_CACHE_TYPE_READ_WRITE "DPCTL_MEM_CACHE_TYPE_READ_WRITE" + ctypedef enum _local_mem_type "DPCTLLocalMemType": + _LOCAL_MEM_TYPE_NONE "DPCTL_LOCAL_MEM_TYPE_NONE" + _LOCAL_MEM_TYPE_LOCAL "DPCTL_LOCAL_MEM_TYPE_LOCAL" + _LOCAL_MEM_TYPE_GLOBAL "DPCTL_LOCAL_MEM_TYPE_GLOBAL" + + ctypedef enum _partition_property_type "DPCTLPartitionPropertyType": + _PARTITION_NO_PARTITION "DPCTL_PARTITION_NO_PARTITION" + _PARTITION_EQUALLY "DPCTL_PARTITION_EQUALLY" + _PARTITION_BY_COUNTS "DPCTL_PARTITION_BY_COUNTS" + _PARTITION_BY_AFFINITY_DOMAIN "DPCTL_PARTITION_BY_AFFINITY_DOMAIN" + + ctypedef enum _fp_config_type "DPCTLFPConfigType": + _FP_DENORM "DPCTL_FP_DENORM" + _FP_INF_NAN "DPCTL_FP_INF_NAN" + _FP_ROUND_TO_NEAREST "DPCTL_FP_ROUND_TO_NEAREST" + _FP_ROUND_TO_ZERO "DPCTL_FP_ROUND_TO_ZERO" + _FP_ROUND_TO_INF "DPCTL_FP_ROUND_TO_INF" + _FP_FMA "DPCTL_FP_FMA" + _FP_CORRECT_ROUND_DIV_SQRT "DPCTL_FP_CORRECTLY_ROUNDED_DIVIDE_SQRT" + _FP_SOFT_FLOAT "DPCTL_FP_SOFT_FLOAT" + + ctypedef enum _memory_order_type "DPCTLMemoryOrderType": + _MEMORY_ORDER_RELAXED "DPCTL_MEMORY_ORDER_RELAXED" + _MEMORY_ORDER_ACQUIRE "DPCTL_MEMORY_ORDER_ACQUIRE" + _MEMORY_ORDER_RELEASE "DPCTL_MEMORY_ORDER_RELEASE" + _MEMORY_ORDER_ACQ_REL "DPCTL_MEMORY_ORDER_ACQ_REL" + _MEMORY_ORDER_SEQ_CST "DPCTL_MEMORY_ORDER_SEQ_CST" + + ctypedef enum _memory_scope_type "DPCTLMemoryScopeType": + _MEMORY_SCOPE_WORK_ITEM "DPCTL_MEMORY_SCOPE_WORK_ITEM" + _MEMORY_SCOPE_SUB_GROUP "DPCTL_MEMORY_SCOPE_SUB_GROUP" + _MEMORY_SCOPE_WORK_GROUP "DPCTL_MEMORY_SCOPE_WORK_GROUP" + _MEMORY_SCOPE_DEVICE "DPCTL_MEMORY_SCOPE_DEVICE" + _MEMORY_SCOPE_SYSTEM "DPCTL_MEMORY_SCOPE_SYSTEM" + cdef extern from "syclinterface/dpctl_sycl_types.h": cdef struct DPCTLOpaqueSyclContext @@ -290,6 +326,46 @@ cdef extern from "syclinterface/dpctl_sycl_device_interface.h": cdef void DPCTLDevice_DisablePeerAccess(const DPCTLSyclDeviceRef DRef, const DPCTLSyclDeviceRef PDRef) + cdef uint32_t DPCTLDevice_GetVendorId(const DPCTLSyclDeviceRef DRef) + cdef uint32_t DPCTLDevice_GetAddressBits(const DPCTLSyclDeviceRef DRef) + cdef size_t DPCTLDevice_GetImageMaxBufferSize( + const DPCTLSyclDeviceRef DRef) + cdef uint32_t DPCTLDevice_GetMaxSamplers(const DPCTLSyclDeviceRef DRef) + cdef size_t DPCTLDevice_GetMaxParameterSize( + const DPCTLSyclDeviceRef DRef) + cdef uint32_t DPCTLDevice_GetMemBaseAddrAlign( + const DPCTLSyclDeviceRef DRef) + cdef bool DPCTLDevice_GetErrorCorrectionSupport( + const DPCTLSyclDeviceRef DRef) + cdef bool DPCTLDevice_IsAvailable(const DPCTLSyclDeviceRef DRef) + cdef const char *DPCTLDevice_GetVersion(const DPCTLSyclDeviceRef DRef) + cdef const char *DPCTLDevice_GetBackendVersion( + const DPCTLSyclDeviceRef DRef) + cdef _local_mem_type DPCTLDevice_GetLocalMemType( + const DPCTLSyclDeviceRef DRef) + cdef _partition_property_type DPCTLDevice_GetPartitionTypeProperty( + const DPCTLSyclDeviceRef DRef) + cdef _partition_affinity_domain_type \ + DPCTLDevice_GetPartitionTypeAffinityDomain( + const DPCTLSyclDeviceRef DRef) + cdef int *DPCTLDevice_GetHalfFPConfig( + const DPCTLSyclDeviceRef DRef, size_t *res_len) + cdef int *DPCTLDevice_GetSingleFPConfig( + const DPCTLSyclDeviceRef DRef, size_t *res_len) + cdef int *DPCTLDevice_GetDoubleFPConfig( + const DPCTLSyclDeviceRef DRef, size_t *res_len) + cdef int *DPCTLDevice_GetAtomicMemoryOrderCapabilities( + const DPCTLSyclDeviceRef DRef, size_t *res_len) + cdef int *DPCTLDevice_GetAtomicFenceOrderCapabilities( + const DPCTLSyclDeviceRef DRef, size_t *res_len) + cdef int *DPCTLDevice_GetAtomicMemoryScopeCapabilities( + const DPCTLSyclDeviceRef DRef, size_t *res_len) + cdef int *DPCTLDevice_GetAtomicFenceScopeCapabilities( + const DPCTLSyclDeviceRef DRef, size_t *res_len) + cdef int *DPCTLDevice_GetPartitionProperties( + const DPCTLSyclDeviceRef DRef, size_t *res_len) + cdef int *DPCTLDevice_GetPartitionAffinityDomains( + const DPCTLSyclDeviceRef DRef, size_t *res_len) cdef extern from "syclinterface/dpctl_sycl_device_manager.h": cdef DPCTLDeviceVectorRef DPCTLDeviceVector_CreateFromArray( diff --git a/dpctl/_sycl_device.pyx b/dpctl/_sycl_device.pyx index 91f2c544f9..140b0a5ab6 100644 --- a/dpctl/_sycl_device.pyx +++ b/dpctl/_sycl_device.pyx @@ -34,32 +34,46 @@ from ._backend cimport ( # noqa: E211 DPCTLDevice_Delete, DPCTLDevice_DisablePeerAccess, DPCTLDevice_EnablePeerAccess, + DPCTLDevice_GetAddressBits, + DPCTLDevice_GetAtomicFenceOrderCapabilities, + DPCTLDevice_GetAtomicFenceScopeCapabilities, + DPCTLDevice_GetAtomicMemoryOrderCapabilities, + DPCTLDevice_GetAtomicMemoryScopeCapabilities, DPCTLDevice_GetBackend, + DPCTLDevice_GetBackendVersion, DPCTLDevice_GetComponentDevices, DPCTLDevice_GetCompositeDevice, DPCTLDevice_GetDeviceType, + DPCTLDevice_GetDoubleFPConfig, DPCTLDevice_GetDriverVersion, + DPCTLDevice_GetErrorCorrectionSupport, DPCTLDevice_GetGlobalMemCacheLineSize, DPCTLDevice_GetGlobalMemCacheSize, DPCTLDevice_GetGlobalMemCacheType, DPCTLDevice_GetGlobalMemSize, + DPCTLDevice_GetHalfFPConfig, DPCTLDevice_GetImage2dMaxHeight, DPCTLDevice_GetImage2dMaxWidth, DPCTLDevice_GetImage3dMaxDepth, DPCTLDevice_GetImage3dMaxHeight, DPCTLDevice_GetImage3dMaxWidth, + DPCTLDevice_GetImageMaxBufferSize, DPCTLDevice_GetLocalMemSize, + DPCTLDevice_GetLocalMemType, DPCTLDevice_GetMaxClockFrequency, DPCTLDevice_GetMaxComputeUnits, DPCTLDevice_GetMaxMemAllocSize, DPCTLDevice_GetMaxNumSubGroups, + DPCTLDevice_GetMaxParameterSize, DPCTLDevice_GetMaxReadImageArgs, + DPCTLDevice_GetMaxSamplers, DPCTLDevice_GetMaxWorkGroupSize, DPCTLDevice_GetMaxWorkItemDims, DPCTLDevice_GetMaxWorkItemSizes1d, DPCTLDevice_GetMaxWorkItemSizes2d, DPCTLDevice_GetMaxWorkItemSizes3d, DPCTLDevice_GetMaxWriteImageArgs, + DPCTLDevice_GetMemBaseAddrAlign, DPCTLDevice_GetName, DPCTLDevice_GetNativeVectorWidthChar, DPCTLDevice_GetNativeVectorWidthDouble, @@ -69,7 +83,11 @@ from ._backend cimport ( # noqa: E211 DPCTLDevice_GetNativeVectorWidthLong, DPCTLDevice_GetNativeVectorWidthShort, DPCTLDevice_GetParentDevice, + DPCTLDevice_GetPartitionAffinityDomains, DPCTLDevice_GetPartitionMaxSubDevices, + DPCTLDevice_GetPartitionProperties, + DPCTLDevice_GetPartitionTypeAffinityDomain, + DPCTLDevice_GetPartitionTypeProperty, DPCTLDevice_GetPlatform, DPCTLDevice_GetPreferredVectorWidthChar, DPCTLDevice_GetPreferredVectorWidthDouble, @@ -79,12 +97,16 @@ from ._backend cimport ( # noqa: E211 DPCTLDevice_GetPreferredVectorWidthLong, DPCTLDevice_GetPreferredVectorWidthShort, DPCTLDevice_GetProfilingTimerResolution, + DPCTLDevice_GetSingleFPConfig, DPCTLDevice_GetSubGroupIndependentForwardProgress, DPCTLDevice_GetSubGroupSizes, DPCTLDevice_GetVendor, + DPCTLDevice_GetVendorId, + DPCTLDevice_GetVersion, DPCTLDevice_HasAspect, DPCTLDevice_Hash, DPCTLDevice_IsAccelerator, + DPCTLDevice_IsAvailable, DPCTLDevice_IsCPU, DPCTLDevice_IsGPU, DPCTLDeviceMgr_GetDeviceInfoStr, @@ -97,6 +119,7 @@ from ._backend cimport ( # noqa: E211 DPCTLDeviceVector_Size, DPCTLDeviceVectorRef, DPCTLFilterSelector_Create, + DPCTLInt_Array_Delete, DPCTLSize_t_Array_Delete, DPCTLSyclDeviceRef, DPCTLSyclDeviceSelectorRef, @@ -105,11 +128,22 @@ from ._backend cimport ( # noqa: E211 _backend_type, _device_type, _global_mem_cache_type, + _local_mem_type, _partition_affinity_domain_type, + _partition_property_type, _peer_access, ) -from .enum_types import backend_type, device_type, global_mem_cache_type +from .enum_types import ( + backend_type, + device_type, + fp_config, + global_mem_cache_type, + local_mem_type, + memory_order, + memory_scope, + partition_property, +) from libc.stdint cimport int64_t, uint32_t, uint64_t from libc.stdlib cimport free, malloc @@ -2110,6 +2144,446 @@ cdef class SyclDevice(_SyclDevice): ) return max_part + @property + def vendor_id(self): + """ Returns the vendor identifier of the device. + + Returns: + int: + The vendor ID as an unsigned 32-bit integer. + """ + return DPCTLDevice_GetVendorId(self._device_ref) + + @property + def address_bits(self): + """ Returns the address space size of the device. + + Returns: + int: + The default compute device address space size specified as + an unsigned integer value in bits. + The result should always be 32 or 64. + """ + return DPCTLDevice_GetAddressBits(self._device_ref) + + @property + def image_max_buffer_size(self): + """ Returns the max number of pixels for a 1D image created from a + buffer. + + Returns: + int: + The maximum number of pixels in a 1D image from buffer. + """ + return DPCTLDevice_GetImageMaxBufferSize(self._device_ref) + + @property + def max_samplers(self): + """ Returns the maximum number of samplers that can be used in a + kernel. + + Returns: + int: + Maximum number of samplers. + """ + return DPCTLDevice_GetMaxSamplers(self._device_ref) + + @property + def max_parameter_size(self): + """ Returns the maximum size in bytes of all arguments that can be + passed to a kernel. + + Returns: + int: + Maximum kernel parameter size in bytes. + """ + return DPCTLDevice_GetMaxParameterSize(self._device_ref) + + @property + def mem_base_addr_align(self): + """ Returns the minimum value to which memory allocations on this + device are aligned in bits. + + Returns: + int: + Minimum alignment in bits for memory allocations. + """ + return DPCTLDevice_GetMemBaseAddrAlign(self._device_ref) + + @property + def error_correction_support(self): + """ Returns ``True`` if the device implements error correction for + all accesses to compute device memories (global, local, etc.). + + Returns: + bool: + Whether ECC memory is supported. + """ + return DPCTLDevice_GetErrorCorrectionSupport(self._device_ref) + + @property + def is_available(self): + """ Returns ``True`` if the device is available. + + Returns: + bool: + Whether the device is currently available. + """ + return DPCTLDevice_IsAvailable(self._device_ref) + + @property + def version(self): + """ Returns a backend-defined device version string. + + Returns: + str: + The device version string. + """ + cdef const char *ver = DPCTLDevice_GetVersion(self._device_ref) + if ver is NULL: + raise RuntimeError("Descriptor 'version' not available") + cdef str ver_str = ver.decode() + DPCTLCString_Delete(ver) + return ver_str + + @property + def backend_version(self): + """ Returns a backend-defined driver version string. + + Returns: + str: + The backend version string. + """ + cdef const char *ver = DPCTLDevice_GetBackendVersion(self._device_ref) + if ver is NULL: + raise RuntimeError("Descriptor 'backend_version' not available") + cdef str ver_str = ver.decode() + DPCTLCString_Delete(ver) + return ver_str + + @property + def local_mem_type(self): + """ Returns the type of local memory supported by the device. + + Returns: + :class:`dpctl.local_mem_type`: + The type of local memory (none, local, or global). + + Raises: + RuntimeError: + If an unrecognized memory type is reported by runtime. + """ + cdef _local_mem_type lmTy = ( + DPCTLDevice_GetLocalMemType(self._device_ref) + ) + if lmTy == _local_mem_type._LOCAL_MEM_TYPE_LOCAL: + return local_mem_type.local + elif lmTy == _local_mem_type._LOCAL_MEM_TYPE_GLOBAL: + return local_mem_type.global_mem + elif lmTy == _local_mem_type._LOCAL_MEM_TYPE_NONE: + return local_mem_type.none + raise RuntimeError("Unrecognized local memory type reported") + + @property + def partition_type_property(self): + """ Returns the partition property of this device if it is a + sub-device, or ``partition_property.no_partition`` if it is not a + sub-device. + + Returns: + :class:`dpctl.partition_property`: + The partition property that was used to create this device. + """ + cdef _partition_property_type ppTy = ( + DPCTLDevice_GetPartitionTypeProperty(self._device_ref) + ) + if ppTy == _partition_property_type._PARTITION_NO_PARTITION: + return partition_property.no_partition + elif ppTy == _partition_property_type._PARTITION_EQUALLY: + return partition_property.partition_equally + elif ppTy == _partition_property_type._PARTITION_BY_COUNTS: + return partition_property.partition_by_counts + elif ppTy == _partition_property_type._PARTITION_BY_AFFINITY_DOMAIN: + return partition_property.partition_by_affinity_domain + return partition_property.no_partition + + @property + def partition_type_affinity_domain(self): + """ Returns the partition affinity domain used to partition the parent + device if this is a sub-device partitioned by affinity domain, or + ``"not_applicable"`` otherwise. + + Returns: + str: + The affinity domain string. + """ + cdef _partition_affinity_domain_type padTy = ( + DPCTLDevice_GetPartitionTypeAffinityDomain(self._device_ref) + ) + if padTy == _partition_affinity_domain_type._not_applicable: + return "not_applicable" + elif padTy == _partition_affinity_domain_type._numa: + return "numa" + elif padTy == _partition_affinity_domain_type._L4_cache: + return "L4_cache" + elif padTy == _partition_affinity_domain_type._L3_cache: + return "L3_cache" + elif padTy == _partition_affinity_domain_type._L2_cache: + return "L2_cache" + elif padTy == _partition_affinity_domain_type._L1_cache: + return "L1_cache" + elif padTy == _partition_affinity_domain_type._next_partitionable: + return "next_partitionable" + return "not_applicable" + + @property + def half_fp_config(self): + """ Returns a tuple of :class:`dpctl.fp_config` enum members + describing half-precision floating-point capabilities of the device. + + Returns: + Tuple[:class:`dpctl.fp_config`]: + Tuple of floating-point configuration flags. + """ + cdef int *arr = NULL + cdef size_t arr_len = 0 + cdef size_t i + cdef list res + + arr = DPCTLDevice_GetHalfFPConfig(self._device_ref, &arr_len) + if arr is not NULL and arr_len > 0: + res = [] + for i in range(arr_len): + res.append(fp_config(arr[i] + 1)) + DPCTLInt_Array_Delete(arr) + return tuple(res) + if arr is not NULL: + DPCTLInt_Array_Delete(arr) + return () + + @property + def single_fp_config(self): + """ Returns a tuple of :class:`dpctl.fp_config` enum members + describing single-precision floating-point capabilities of the device. + + Returns: + Tuple[:class:`dpctl.fp_config`]: + Tuple of floating-point configuration flags. + """ + cdef int *arr = NULL + cdef size_t arr_len = 0 + cdef size_t i + cdef list res + + arr = DPCTLDevice_GetSingleFPConfig(self._device_ref, &arr_len) + if arr is not NULL and arr_len > 0: + res = [] + for i in range(arr_len): + res.append(fp_config(arr[i] + 1)) + DPCTLInt_Array_Delete(arr) + return tuple(res) + if arr is not NULL: + DPCTLInt_Array_Delete(arr) + return () + + @property + def double_fp_config(self): + """ Returns a tuple of :class:`dpctl.fp_config` enum members + describing double-precision floating-point capabilities of the device. + + Returns: + Tuple[:class:`dpctl.fp_config`]: + Tuple of floating-point configuration flags. + """ + cdef int *arr = NULL + cdef size_t arr_len = 0 + cdef size_t i + cdef list res + + arr = DPCTLDevice_GetDoubleFPConfig(self._device_ref, &arr_len) + if arr is not NULL and arr_len > 0: + res = [] + for i in range(arr_len): + res.append(fp_config(arr[i] + 1)) + DPCTLInt_Array_Delete(arr) + return tuple(res) + if arr is not NULL: + DPCTLInt_Array_Delete(arr) + return () + + @property + def atomic_memory_order_capabilities(self): + """ Returns a tuple of :class:`dpctl.memory_order` enum members + describing atomic memory order capabilities of the device. + + Returns: + Tuple[:class:`dpctl.memory_order`]: + Tuple of supported memory orders. + """ + cdef int *arr = NULL + cdef size_t arr_len = 0 + cdef size_t i + cdef list res + + arr = DPCTLDevice_GetAtomicMemoryOrderCapabilities( + self._device_ref, &arr_len + ) + if arr is not NULL and arr_len > 0: + res = [] + for i in range(arr_len): + res.append(memory_order(arr[i] + 1)) + DPCTLInt_Array_Delete(arr) + return tuple(res) + if arr is not NULL: + DPCTLInt_Array_Delete(arr) + return () + + @property + def atomic_fence_order_capabilities(self): + """ Returns a tuple of :class:`dpctl.memory_order` enum members + describing atomic fence order capabilities of the device. + + Returns: + Tuple[:class:`dpctl.memory_order`]: + Tuple of supported fence orders. + """ + cdef int *arr = NULL + cdef size_t arr_len = 0 + cdef size_t i + cdef list res + + arr = DPCTLDevice_GetAtomicFenceOrderCapabilities( + self._device_ref, &arr_len + ) + if arr is not NULL and arr_len > 0: + res = [] + for i in range(arr_len): + res.append(memory_order(arr[i] + 1)) + DPCTLInt_Array_Delete(arr) + return tuple(res) + if arr is not NULL: + DPCTLInt_Array_Delete(arr) + return () + + @property + def atomic_memory_scope_capabilities(self): + """ Returns a tuple of :class:`dpctl.memory_scope` enum members + describing atomic memory scope capabilities of the device. + + Returns: + Tuple[:class:`dpctl.memory_scope`]: + Tuple of supported memory scopes. + """ + cdef int *arr = NULL + cdef size_t arr_len = 0 + cdef size_t i + cdef list res + + arr = DPCTLDevice_GetAtomicMemoryScopeCapabilities( + self._device_ref, &arr_len + ) + if arr is not NULL and arr_len > 0: + res = [] + for i in range(arr_len): + res.append(memory_scope(arr[i] + 1)) + DPCTLInt_Array_Delete(arr) + return tuple(res) + if arr is not NULL: + DPCTLInt_Array_Delete(arr) + return () + + @property + def atomic_fence_scope_capabilities(self): + """ Returns a tuple of :class:`dpctl.memory_scope` enum members + describing atomic fence scope capabilities of the device. + + Returns: + Tuple[:class:`dpctl.memory_scope`]: + Tuple of supported fence scopes. + """ + cdef int *arr = NULL + cdef size_t arr_len = 0 + cdef size_t i + cdef list res + + arr = DPCTLDevice_GetAtomicFenceScopeCapabilities( + self._device_ref, &arr_len + ) + if arr is not NULL and arr_len > 0: + res = [] + for i in range(arr_len): + res.append(memory_scope(arr[i] + 1)) + DPCTLInt_Array_Delete(arr) + return tuple(res) + if arr is not NULL: + DPCTLInt_Array_Delete(arr) + return () + + @property + def partition_properties(self): + """ Returns a tuple of :class:`dpctl.partition_property` enum members + describing supported partition properties of the device. + + Returns: + Tuple[:class:`dpctl.partition_property`]: + Tuple of supported partition properties. + """ + cdef int *arr = NULL + cdef size_t arr_len = 0 + cdef size_t i + cdef list res + + arr = DPCTLDevice_GetPartitionProperties( + self._device_ref, &arr_len + ) + if arr is not NULL and arr_len > 0: + res = [] + for i in range(arr_len): + res.append(partition_property(arr[i] + 1)) + DPCTLInt_Array_Delete(arr) + return tuple(res) + if arr is not NULL: + DPCTLInt_Array_Delete(arr) + return () + + @property + def partition_affinity_domains(self): + """ Returns a tuple of strings describing supported partition + affinity domains of the device. + + Returns: + Tuple[str]: + Tuple of supported affinity domain names. + """ + cdef int *arr = NULL + cdef size_t arr_len = 0 + cdef size_t i + cdef list res + cdef dict _pad_map = { + _partition_affinity_domain_type._not_applicable: + "not_applicable", + _partition_affinity_domain_type._numa: "numa", + _partition_affinity_domain_type._L4_cache: "L4_cache", + _partition_affinity_domain_type._L3_cache: "L3_cache", + _partition_affinity_domain_type._L2_cache: "L2_cache", + _partition_affinity_domain_type._L1_cache: "L1_cache", + _partition_affinity_domain_type._next_partitionable: + "next_partitionable", + } + + arr = DPCTLDevice_GetPartitionAffinityDomains( + self._device_ref, &arr_len + ) + if arr is not NULL and arr_len > 0: + res = [] + for i in range(arr_len): + res.append(_pad_map.get(arr[i], "not_applicable")) + DPCTLInt_Array_Delete(arr) + return tuple(res) + if arr is not NULL: + DPCTLInt_Array_Delete(arr) + return () + cdef cpp_bool equals(self, SyclDevice other): """ Returns ``True`` if the :class:`dpctl.SyclDevice` argument has the same _device_ref as this SyclDevice. diff --git a/dpctl/enum_types.py b/dpctl/enum_types.py index 6872afa42e..f445ebb7f6 100644 --- a/dpctl/enum_types.py +++ b/dpctl/enum_types.py @@ -23,7 +23,17 @@ from enum import Enum, auto -__all__ = ["device_type", "backend_type", "event_status_type"] +__all__ = [ + "device_type", + "backend_type", + "event_status_type", + "global_mem_cache_type", + "local_mem_type", + "partition_property", + "fp_config", + "memory_order", + "memory_scope", +] class device_type(Enum): @@ -134,3 +144,145 @@ class global_mem_cache_type(Enum): none = auto() read_only = auto() read_write = auto() + + +class local_mem_type(Enum): + """ + An :class:`enum.Enum` of local memory types for a device. + + | ``none`` + | ``local`` + | ``global_mem`` + + :Example: + .. code-block:: python + + import dpctl + dev = dpctl.SyclDevice() + dev.local_mem_type + # Possible output: + """ + + none = auto() + local = auto() + global_mem = auto() + + +class partition_property(Enum): + """ + An :class:`enum.Enum` of partition property types. + + | ``no_partition`` + | ``partition_equally`` + | ``partition_by_counts`` + | ``partition_by_affinity_domain`` + + :Example: + .. code-block:: python + + import dpctl + dev = dpctl.SyclDevice() + dev.partition_type_property + # Possible output: + """ + + no_partition = auto() + partition_equally = auto() + partition_by_counts = auto() + partition_by_affinity_domain = auto() + + +class fp_config(Enum): + """ + An :class:`enum.Enum` of floating-point capability flags. + + | ``denorm`` + | ``inf_nan`` + | ``round_to_nearest`` + | ``round_to_zero`` + | ``round_to_inf`` + | ``fma`` + | ``correctly_rounded_divide_sqrt`` + | ``soft_float`` + + :Example: + .. code-block:: python + + import dpctl + dev = dpctl.SyclDevice() + dev.single_fp_config + # Possible output: ( + # , + # , + # ... + # ) + """ + + denorm = auto() + inf_nan = auto() + round_to_nearest = auto() + round_to_zero = auto() + round_to_inf = auto() + fma = auto() + correctly_rounded_divide_sqrt = auto() + soft_float = auto() + + +class memory_order(Enum): + """ + An :class:`enum.Enum` of memory ordering capabilities. + + | ``relaxed`` + | ``acquire`` + | ``release`` + | ``acq_rel`` + | ``seq_cst`` + + :Example: + .. code-block:: python + + import dpctl + dev = dpctl.SyclDevice() + dev.atomic_memory_order_capabilities + # Possible output: ( + # , + # , + # ... + # ) + """ + + relaxed = auto() + acquire = auto() + release = auto() + acq_rel = auto() + seq_cst = auto() + + +class memory_scope(Enum): + """ + An :class:`enum.Enum` of memory scope capabilities. + + | ``work_item`` + | ``sub_group`` + | ``work_group`` + | ``device`` + | ``system`` + + :Example: + .. code-block:: python + + import dpctl + dev = dpctl.SyclDevice() + dev.atomic_memory_scope_capabilities + # Possible output: ( + # , + # , + # ... + # ) + """ + + work_item = auto() + sub_group = auto() + work_group = auto() + device = auto() + system = auto() diff --git a/dpctl/tests/_device_attributes_checks.py b/dpctl/tests/_device_attributes_checks.py index 003eefa721..2639c78035 100644 --- a/dpctl/tests/_device_attributes_checks.py +++ b/dpctl/tests/_device_attributes_checks.py @@ -659,6 +659,146 @@ def check_global_mem_cache_line_size(device): assert gmc_sz +def check_vendor_id(device): + vid = device.vendor_id + assert isinstance(vid, int) + assert vid > 0 + + +def check_address_bits(device): + ab = device.address_bits + assert isinstance(ab, int) + assert ab in (32, 64) + + +def check_image_max_buffer_size(device): + sz = device.image_max_buffer_size + assert isinstance(sz, int) + assert sz >= 0 + + +def check_max_samplers(device): + ms = device.max_samplers + assert isinstance(ms, int) + assert ms >= 0 + + +def check_max_parameter_size(device): + mps = device.max_parameter_size + assert isinstance(mps, int) + assert mps > 0 + + +def check_mem_base_addr_align(device): + align = device.mem_base_addr_align + assert isinstance(align, int) + assert align > 0 + + +def check_error_correction_support(device): + ecs = device.error_correction_support + assert isinstance(ecs, bool) + + +def check_is_available(device): + avail = device.is_available + assert isinstance(avail, bool) + assert avail + + +def check_version(device): + ver = device.version + assert isinstance(ver, str) + assert len(ver) > 0 + + +def check_backend_version(device): + ver = device.backend_version + assert isinstance(ver, str) + + +def check_local_mem_type(device): + lmt = device.local_mem_type + assert type(lmt) is dpctl.local_mem_type + + +def check_partition_type_property(device): + ptp = device.partition_type_property + assert type(ptp) is dpctl.partition_property + + +def check_partition_type_affinity_domain(device): + ptad = device.partition_type_affinity_domain + assert isinstance(ptad, str) + + +def check_half_fp_config(device): + cfg = device.half_fp_config + assert isinstance(cfg, tuple) + for v in cfg: + assert type(v) is dpctl.fp_config + + +def check_single_fp_config(device): + cfg = device.single_fp_config + assert isinstance(cfg, tuple) + for v in cfg: + assert type(v) is dpctl.fp_config + + +def check_double_fp_config(device): + cfg = device.double_fp_config + assert isinstance(cfg, tuple) + for v in cfg: + assert type(v) is dpctl.fp_config + + +def check_atomic_memory_order_capabilities(device): + caps = device.atomic_memory_order_capabilities + assert isinstance(caps, tuple) + assert len(caps) > 0 + for v in caps: + assert type(v) is dpctl.memory_order + + +def check_atomic_fence_order_capabilities(device): + caps = device.atomic_fence_order_capabilities + assert isinstance(caps, tuple) + assert len(caps) > 0 + for v in caps: + assert type(v) is dpctl.memory_order + + +def check_atomic_memory_scope_capabilities(device): + caps = device.atomic_memory_scope_capabilities + assert isinstance(caps, tuple) + assert len(caps) > 0 + for v in caps: + assert type(v) is dpctl.memory_scope + + +def check_atomic_fence_scope_capabilities(device): + caps = device.atomic_fence_scope_capabilities + assert isinstance(caps, tuple) + assert len(caps) > 0 + for v in caps: + assert type(v) is dpctl.memory_scope + + +def check_partition_properties(device): + props = device.partition_properties + assert isinstance(props, tuple) + for v in props: + assert type(v) is dpctl.partition_property + + +def check_partition_affinity_domains(device): + domains = device.partition_affinity_domains + assert isinstance(domains, tuple) + for v in domains: + assert isinstance(v, str) + + list_of_checks = [ check_max_compute_units, check_max_work_item_dims, @@ -742,6 +882,28 @@ def check_global_mem_cache_line_size(device): check_global_mem_cache_line_size, check_max_clock_frequency, check_max_mem_alloc_size, + check_vendor_id, + check_address_bits, + check_image_max_buffer_size, + check_max_samplers, + check_max_parameter_size, + check_mem_base_addr_align, + check_error_correction_support, + check_is_available, + check_version, + check_backend_version, + check_local_mem_type, + check_partition_type_property, + check_partition_type_affinity_domain, + check_half_fp_config, + check_single_fp_config, + check_double_fp_config, + check_atomic_memory_order_capabilities, + check_atomic_fence_order_capabilities, + check_atomic_memory_scope_capabilities, + check_atomic_fence_scope_capabilities, + check_partition_properties, + check_partition_affinity_domains, ] diff --git a/libsyclinterface/include/syclinterface/dpctl_sycl_device_interface.h b/libsyclinterface/include/syclinterface/dpctl_sycl_device_interface.h index c07a0f8f46..bfcf956957 100644 --- a/libsyclinterface/include/syclinterface/dpctl_sycl_device_interface.h +++ b/libsyclinterface/include/syclinterface/dpctl_sycl_device_interface.h @@ -828,4 +828,271 @@ DPCTL_API void DPCTLDevice_DisablePeerAccess(__dpctl_keep const DPCTLSyclDeviceRef DRef, __dpctl_keep const DPCTLSyclDeviceRef PDRef); +/*! + * @brief Wrapper over device.get_info(). + * + * @param DRef Opaque pointer to a ``sycl::device`` + * @return Returns the vendor id of the device. + * @ingroup DeviceInterface + */ +DPCTL_API +uint32_t DPCTLDevice_GetVendorId(__dpctl_keep const DPCTLSyclDeviceRef DRef); + +/*! + * @brief Wrapper over device.get_info(). + * + * @param DRef Opaque pointer to a ``sycl::device`` + * @return Returns the address space size (32 or 64 bits). + * @ingroup DeviceInterface + */ +DPCTL_API +uint32_t DPCTLDevice_GetAddressBits(__dpctl_keep const DPCTLSyclDeviceRef DRef); + +/*! + * @brief Wrapper over device.get_info(). + * + * @param DRef Opaque pointer to a ``sycl::device`` + * @return Returns the max number of pixels for a 1D image from buffer. + * @ingroup DeviceInterface + */ +DPCTL_API +size_t +DPCTLDevice_GetImageMaxBufferSize(__dpctl_keep const DPCTLSyclDeviceRef DRef); + +/*! + * @brief Wrapper over device.get_info(). + * + * @param DRef Opaque pointer to a ``sycl::device`` + * @return Returns the maximum number of samplers that can be used in a + * kernel. + * @ingroup DeviceInterface + */ +DPCTL_API +uint32_t DPCTLDevice_GetMaxSamplers(__dpctl_keep const DPCTLSyclDeviceRef DRef); + +/*! + * @brief Wrapper over device.get_info(). + * + * @param DRef Opaque pointer to a ``sycl::device`` + * @return Returns the max size in bytes of all arguments passed to a kernel. + * @ingroup DeviceInterface + */ +DPCTL_API +size_t +DPCTLDevice_GetMaxParameterSize(__dpctl_keep const DPCTLSyclDeviceRef DRef); + +/*! + * @brief Wrapper over device.get_info(). + * + * @param DRef Opaque pointer to a ``sycl::device`` + * @return Returns the minimum alignment in bits for memory allocations. + * @ingroup DeviceInterface + */ +DPCTL_API +uint32_t +DPCTLDevice_GetMemBaseAddrAlign(__dpctl_keep const DPCTLSyclDeviceRef DRef); + +/*! + * @brief Wrapper over + * device.get_info(). + * + * @param DRef Opaque pointer to a ``sycl::device`` + * @return Returns true if the device supports ECC memory. + * @ingroup DeviceInterface + */ +DPCTL_API +bool DPCTLDevice_GetErrorCorrectionSupport( + __dpctl_keep const DPCTLSyclDeviceRef DRef); + +/*! + * @brief Wrapper over device.get_info(). + * + * @param DRef Opaque pointer to a ``sycl::device`` + * @return Returns true if the device is available. + * @ingroup DeviceInterface + */ +DPCTL_API +bool DPCTLDevice_IsAvailable(__dpctl_keep const DPCTLSyclDeviceRef DRef); + +/*! + * @brief Wrapper over device.get_info(). + * + * @param DRef Opaque pointer to a ``sycl::device`` + * @return Returns a C string with the device version. + * @ingroup DeviceInterface + */ +DPCTL_API +__dpctl_give const char * +DPCTLDevice_GetVersion(__dpctl_keep const DPCTLSyclDeviceRef DRef); + +/*! + * @brief Wrapper over device.get_info(). + * + * @param DRef Opaque pointer to a ``sycl::device`` + * @return Returns a C string with the backend version. + * @ingroup DeviceInterface + */ +DPCTL_API +__dpctl_give const char * +DPCTLDevice_GetBackendVersion(__dpctl_keep const DPCTLSyclDeviceRef DRef); + +/*! + * @brief Wrapper over device.get_info(). + * + * @param DRef Opaque pointer to a ``sycl::device`` + * @return Returns the type of local memory supported. + * @ingroup DeviceInterface + */ +DPCTL_API +DPCTLLocalMemType +DPCTLDevice_GetLocalMemType(__dpctl_keep const DPCTLSyclDeviceRef DRef); + +/*! + * @brief Wrapper over + * device.get_info(). + * + * @param DRef Opaque pointer to a ``sycl::device`` + * @return Returns the partition property used to create this device. + * @ingroup DeviceInterface + */ +DPCTL_API +DPCTLPartitionPropertyType DPCTLDevice_GetPartitionTypeProperty( + __dpctl_keep const DPCTLSyclDeviceRef DRef); + +/*! + * @brief Wrapper over + * device.get_info(). + * + * @param DRef Opaque pointer to a ``sycl::device`` + * @return Returns the affinity domain used to partition the parent device. + * @ingroup DeviceInterface + */ +DPCTL_API +DPCTLPartitionAffinityDomainType DPCTLDevice_GetPartitionTypeAffinityDomain( + __dpctl_keep const DPCTLSyclDeviceRef DRef); + +/*! + * @brief Wrapper over device.get_info(). + * + * @param DRef Opaque pointer to a ``sycl::device`` + * @param res_len Populated with size of the returned array + * @return Returns an array of DPCTLFPConfigType values. Caller must free + * with DPCTLSize_t_Array_Delete. + * @ingroup DeviceInterface + */ +DPCTL_API +__dpctl_keep int * +DPCTLDevice_GetHalfFPConfig(__dpctl_keep const DPCTLSyclDeviceRef DRef, + size_t *res_len); + +/*! + * @brief Wrapper over device.get_info(). + * + * @param DRef Opaque pointer to a ``sycl::device`` + * @param res_len Populated with size of the returned array + * @return Returns an array of DPCTLFPConfigType values. + * @ingroup DeviceInterface + */ +DPCTL_API +__dpctl_keep int * +DPCTLDevice_GetSingleFPConfig(__dpctl_keep const DPCTLSyclDeviceRef DRef, + size_t *res_len); + +/*! + * @brief Wrapper over device.get_info(). + * + * @param DRef Opaque pointer to a ``sycl::device`` + * @param res_len Populated with size of the returned array + * @return Returns an array of DPCTLFPConfigType values. + * @ingroup DeviceInterface + */ +DPCTL_API +__dpctl_keep int * +DPCTLDevice_GetDoubleFPConfig(__dpctl_keep const DPCTLSyclDeviceRef DRef, + size_t *res_len); + +/*! + * @brief Wrapper over + * device.get_info(). + * + * @param DRef Opaque pointer to a ``sycl::device`` + * @param res_len Populated with size of the returned array + * @return Returns an array of DPCTLMemoryOrderType values. + * @ingroup DeviceInterface + */ +DPCTL_API +__dpctl_keep int *DPCTLDevice_GetAtomicMemoryOrderCapabilities( + __dpctl_keep const DPCTLSyclDeviceRef DRef, + size_t *res_len); + +/*! + * @brief Wrapper over + * device.get_info(). + * + * @param DRef Opaque pointer to a ``sycl::device`` + * @param res_len Populated with size of the returned array + * @return Returns an array of DPCTLMemoryOrderType values. + * @ingroup DeviceInterface + */ +DPCTL_API +__dpctl_keep int *DPCTLDevice_GetAtomicFenceOrderCapabilities( + __dpctl_keep const DPCTLSyclDeviceRef DRef, + size_t *res_len); + +/*! + * @brief Wrapper over + * device.get_info(). + * + * @param DRef Opaque pointer to a ``sycl::device`` + * @param res_len Populated with size of the returned array + * @return Returns an array of DPCTLMemoryScopeType values. + * @ingroup DeviceInterface + */ +DPCTL_API +__dpctl_keep int *DPCTLDevice_GetAtomicMemoryScopeCapabilities( + __dpctl_keep const DPCTLSyclDeviceRef DRef, + size_t *res_len); + +/*! + * @brief Wrapper over + * device.get_info(). + * + * @param DRef Opaque pointer to a ``sycl::device`` + * @param res_len Populated with size of the returned array + * @return Returns an array of DPCTLMemoryScopeType values. + * @ingroup DeviceInterface + */ +DPCTL_API +__dpctl_keep int *DPCTLDevice_GetAtomicFenceScopeCapabilities( + __dpctl_keep const DPCTLSyclDeviceRef DRef, + size_t *res_len); + +/*! + * @brief Wrapper over + * device.get_info(). + * + * @param DRef Opaque pointer to a ``sycl::device`` + * @param res_len Populated with size of the returned array + * @return Returns an array of DPCTLPartitionPropertyType values. + * @ingroup DeviceInterface + */ +DPCTL_API +__dpctl_keep int * +DPCTLDevice_GetPartitionProperties(__dpctl_keep const DPCTLSyclDeviceRef DRef, + size_t *res_len); + +/*! + * @brief Wrapper over + * device.get_info(). + * + * @param DRef Opaque pointer to a ``sycl::device`` + * @param res_len Populated with size of the returned array + * @return Returns an array of DPCTLPartitionAffinityDomainType values. + * @ingroup DeviceInterface + */ +DPCTL_API +__dpctl_keep int *DPCTLDevice_GetPartitionAffinityDomains( + __dpctl_keep const DPCTLSyclDeviceRef DRef, + size_t *res_len); + 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 e8c4cba7e9..96f0c70d66 100644 --- a/libsyclinterface/include/syclinterface/dpctl_sycl_enum_types.h +++ b/libsyclinterface/include/syclinterface/dpctl_sycl_enum_types.h @@ -191,4 +191,49 @@ typedef enum DPCTL_MEM_CACHE_TYPE_READ_WRITE } DPCTLGlobalMemCacheType; +typedef enum +{ + DPCTL_LOCAL_MEM_TYPE_NONE, + DPCTL_LOCAL_MEM_TYPE_LOCAL, + DPCTL_LOCAL_MEM_TYPE_GLOBAL +} DPCTLLocalMemType; + +typedef enum +{ + DPCTL_PARTITION_NO_PARTITION, + DPCTL_PARTITION_EQUALLY, + DPCTL_PARTITION_BY_COUNTS, + DPCTL_PARTITION_BY_AFFINITY_DOMAIN +} DPCTLPartitionPropertyType; + +typedef enum +{ + DPCTL_FP_DENORM, + DPCTL_FP_INF_NAN, + DPCTL_FP_ROUND_TO_NEAREST, + DPCTL_FP_ROUND_TO_ZERO, + DPCTL_FP_ROUND_TO_INF, + DPCTL_FP_FMA, + DPCTL_FP_CORRECTLY_ROUNDED_DIVIDE_SQRT, + DPCTL_FP_SOFT_FLOAT +} DPCTLFPConfigType; + +typedef enum +{ + DPCTL_MEMORY_ORDER_RELAXED, + DPCTL_MEMORY_ORDER_ACQUIRE, + DPCTL_MEMORY_ORDER_RELEASE, + DPCTL_MEMORY_ORDER_ACQ_REL, + DPCTL_MEMORY_ORDER_SEQ_CST +} DPCTLMemoryOrderType; + +typedef enum +{ + DPCTL_MEMORY_SCOPE_WORK_ITEM, + DPCTL_MEMORY_SCOPE_SUB_GROUP, + DPCTL_MEMORY_SCOPE_WORK_GROUP, + DPCTL_MEMORY_SCOPE_DEVICE, + DPCTL_MEMORY_SCOPE_SYSTEM +} DPCTLMemoryScopeType; + DPCTL_C_EXTERN_C_END diff --git a/libsyclinterface/include/syclinterface/dpctl_utils.h b/libsyclinterface/include/syclinterface/dpctl_utils.h index d124869062..bdf5709784 100644 --- a/libsyclinterface/include/syclinterface/dpctl_utils.h +++ b/libsyclinterface/include/syclinterface/dpctl_utils.h @@ -47,4 +47,12 @@ void DPCTLCString_Delete(__dpctl_take const char *str); DPCTL_API void DPCTLSize_t_Array_Delete(__dpctl_take size_t *arr); +/*! + * @brief Deletes an array of int elements. + * + * @param arr Array to be deleted. + */ +DPCTL_API +void DPCTLInt_Array_Delete(__dpctl_take int *arr); + DPCTL_C_EXTERN_C_END diff --git a/libsyclinterface/source/dpctl_sycl_device_interface.cpp b/libsyclinterface/source/dpctl_sycl_device_interface.cpp index 65be01a0bb..12ec15e747 100644 --- a/libsyclinterface/source/dpctl_sycl_device_interface.cpp +++ b/libsyclinterface/source/dpctl_sycl_device_interface.cpp @@ -982,3 +982,417 @@ void DPCTLDevice_DisablePeerAccess(__dpctl_keep const DPCTLSyclDeviceRef DRef, } return; } + +uint32_t DPCTLDevice_GetVendorId(__dpctl_keep const DPCTLSyclDeviceRef DRef) +{ + uint32_t vendorId = 0; + auto D = unwrap(DRef); + if (D) { + try { + vendorId = D->get_info(); + } catch (std::exception const &e) { + error_handler(e, __FILE__, __func__, __LINE__); + } + } + return vendorId; +} + +uint32_t DPCTLDevice_GetAddressBits(__dpctl_keep const DPCTLSyclDeviceRef DRef) +{ + uint32_t addressBits = 0; + auto D = unwrap(DRef); + if (D) { + try { + addressBits = D->get_info(); + } catch (std::exception const &e) { + error_handler(e, __FILE__, __func__, __LINE__); + } + } + return addressBits; +} + +size_t +DPCTLDevice_GetImageMaxBufferSize(__dpctl_keep const DPCTLSyclDeviceRef DRef) +{ + size_t result = 0; + auto D = unwrap(DRef); + if (D) { + try { + result = D->get_info(); + } catch (std::exception const &e) { + error_handler(e, __FILE__, __func__, __LINE__); + } + } + return result; +} + +uint32_t DPCTLDevice_GetMaxSamplers(__dpctl_keep const DPCTLSyclDeviceRef DRef) +{ + uint32_t result = 0; + auto D = unwrap(DRef); + if (D) { + try { + result = D->get_info(); + } catch (std::exception const &e) { + error_handler(e, __FILE__, __func__, __LINE__); + } + } + return result; +} + +size_t +DPCTLDevice_GetMaxParameterSize(__dpctl_keep const DPCTLSyclDeviceRef DRef) +{ + size_t result = 0; + auto D = unwrap(DRef); + if (D) { + try { + result = D->get_info(); + } catch (std::exception const &e) { + error_handler(e, __FILE__, __func__, __LINE__); + } + } + return result; +} + +uint32_t +DPCTLDevice_GetMemBaseAddrAlign(__dpctl_keep const DPCTLSyclDeviceRef DRef) +{ + uint32_t result = 0; + auto D = unwrap(DRef); + if (D) { + try { + result = D->get_info(); + } catch (std::exception const &e) { + error_handler(e, __FILE__, __func__, __LINE__); + } + } + return result; +} + +bool DPCTLDevice_GetErrorCorrectionSupport( + __dpctl_keep const DPCTLSyclDeviceRef DRef) +{ + bool result = false; + auto D = unwrap(DRef); + if (D) { + try { + result = D->get_info(); + } catch (std::exception const &e) { + error_handler(e, __FILE__, __func__, __LINE__); + } + } + return result; +} + +bool DPCTLDevice_IsAvailable(__dpctl_keep const DPCTLSyclDeviceRef DRef) +{ + bool result = false; + auto D = unwrap(DRef); + if (D) { + try { + result = D->get_info(); + } catch (std::exception const &e) { + error_handler(e, __FILE__, __func__, __LINE__); + } + } + return result; +} + +__dpctl_give const char * +DPCTLDevice_GetVersion(__dpctl_keep const DPCTLSyclDeviceRef DRef) +{ + const char *cstr_version = nullptr; + auto D = unwrap(DRef); + if (D) { + try { + auto version = D->get_info(); + cstr_version = dpctl::helper::cstring_from_string(version); + } catch (std::exception const &e) { + error_handler(e, __FILE__, __func__, __LINE__); + } + } + return cstr_version; +} + +__dpctl_give const char * +DPCTLDevice_GetBackendVersion(__dpctl_keep const DPCTLSyclDeviceRef DRef) +{ + const char *cstr_version = nullptr; + auto D = unwrap(DRef); + if (D) { + try { + auto version = D->get_info(); + cstr_version = dpctl::helper::cstring_from_string(version); + } catch (std::exception const &e) { + error_handler(e, __FILE__, __func__, __LINE__); + } + } + return cstr_version; +} + +DPCTLLocalMemType +DPCTLDevice_GetLocalMemType(__dpctl_keep const DPCTLSyclDeviceRef DRef) +{ + if (DRef) { + auto D = unwrap(DRef); + try { + auto mem_type = D->get_info(); + switch (mem_type) { + case info::local_mem_type::none: + return DPCTL_LOCAL_MEM_TYPE_NONE; + case info::local_mem_type::local: + return DPCTL_LOCAL_MEM_TYPE_LOCAL; + case info::local_mem_type::global: + return DPCTL_LOCAL_MEM_TYPE_GLOBAL; + } + } catch (std::exception const &e) { + error_handler(e, __FILE__, __func__, __LINE__); + } + } + return DPCTL_LOCAL_MEM_TYPE_NONE; +} + +DPCTLPartitionPropertyType +DPCTLDevice_GetPartitionTypeProperty(__dpctl_keep const DPCTLSyclDeviceRef DRef) +{ + if (DRef) { + auto D = unwrap(DRef); + try { + auto pp = D->get_info(); + switch (pp) { + case info::partition_property::no_partition: + return DPCTL_PARTITION_NO_PARTITION; + case info::partition_property::partition_equally: + return DPCTL_PARTITION_EQUALLY; + case info::partition_property::partition_by_counts: + return DPCTL_PARTITION_BY_COUNTS; + case info::partition_property::partition_by_affinity_domain: + return DPCTL_PARTITION_BY_AFFINITY_DOMAIN; + default: + // TODO: investigate ext_intel_partition_by_cslice extension + break; + } + } catch (std::exception const &e) { + error_handler(e, __FILE__, __func__, __LINE__); + } + } + return DPCTL_PARTITION_NO_PARTITION; +} + +DPCTLPartitionAffinityDomainType DPCTLDevice_GetPartitionTypeAffinityDomain( + __dpctl_keep const DPCTLSyclDeviceRef DRef) +{ + if (DRef) { + auto D = unwrap(DRef); + try { + auto domain = + D->get_info(); + return DPCTL_SyclPartitionAffinityDomainToDPCTLType(domain); + } catch (std::exception const &e) { + error_handler(e, __FILE__, __func__, __LINE__); + } + } + return DPCTLPartitionAffinityDomainType::not_applicable; +} + +namespace +{ + +int dpctl_fp_config_to_int(info::fp_config fc) +{ + switch (fc) { + case info::fp_config::denorm: + return DPCTL_FP_DENORM; + case info::fp_config::inf_nan: + return DPCTL_FP_INF_NAN; + case info::fp_config::round_to_nearest: + return DPCTL_FP_ROUND_TO_NEAREST; + case info::fp_config::round_to_zero: + return DPCTL_FP_ROUND_TO_ZERO; + case info::fp_config::round_to_inf: + return DPCTL_FP_ROUND_TO_INF; + case info::fp_config::fma: + return DPCTL_FP_FMA; + case info::fp_config::correctly_rounded_divide_sqrt: + return DPCTL_FP_CORRECTLY_ROUNDED_DIVIDE_SQRT; + case info::fp_config::soft_float: + return DPCTL_FP_SOFT_FLOAT; + } + return -1; +} + +int dpctl_memory_order_to_int(sycl::memory_order mo) +{ + switch (mo) { + case sycl::memory_order::relaxed: + return DPCTL_MEMORY_ORDER_RELAXED; + case sycl::memory_order::acquire: + return DPCTL_MEMORY_ORDER_ACQUIRE; + case sycl::memory_order::release: + return DPCTL_MEMORY_ORDER_RELEASE; + case sycl::memory_order::acq_rel: + return DPCTL_MEMORY_ORDER_ACQ_REL; + case sycl::memory_order::seq_cst: + return DPCTL_MEMORY_ORDER_SEQ_CST; + default: + return -1; + } +} + +int dpctl_memory_scope_to_int(sycl::memory_scope ms) +{ + switch (ms) { + case sycl::memory_scope::work_item: + return DPCTL_MEMORY_SCOPE_WORK_ITEM; + case sycl::memory_scope::sub_group: + return DPCTL_MEMORY_SCOPE_SUB_GROUP; + case sycl::memory_scope::work_group: + return DPCTL_MEMORY_SCOPE_WORK_GROUP; + case sycl::memory_scope::device: + return DPCTL_MEMORY_SCOPE_DEVICE; + case sycl::memory_scope::system: + return DPCTL_MEMORY_SCOPE_SYSTEM; + } + return -1; +} + +int dpctl_partition_property_to_int(info::partition_property pp) +{ + switch (pp) { + case info::partition_property::no_partition: + return DPCTL_PARTITION_NO_PARTITION; + case info::partition_property::partition_equally: + return DPCTL_PARTITION_EQUALLY; + case info::partition_property::partition_by_counts: + return DPCTL_PARTITION_BY_COUNTS; + case info::partition_property::partition_by_affinity_domain: + return DPCTL_PARTITION_BY_AFFINITY_DOMAIN; + default: + // TODO: investigate ext_intel_partition_by_cslice extension + return -1; + } +} + +int dpctl_partition_affinity_domain_to_int(info::partition_affinity_domain pad) +{ + switch (pad) { + case info::partition_affinity_domain::not_applicable: + return DPCTLPartitionAffinityDomainType::not_applicable; + case info::partition_affinity_domain::numa: + return DPCTLPartitionAffinityDomainType::numa; + case info::partition_affinity_domain::L4_cache: + return DPCTLPartitionAffinityDomainType::L4_cache; + case info::partition_affinity_domain::L3_cache: + return DPCTLPartitionAffinityDomainType::L3_cache; + case info::partition_affinity_domain::L2_cache: + return DPCTLPartitionAffinityDomainType::L2_cache; + case info::partition_affinity_domain::L1_cache: + return DPCTLPartitionAffinityDomainType::L1_cache; + case info::partition_affinity_domain::next_partitionable: + return DPCTLPartitionAffinityDomainType::next_partitionable; + } + return DPCTLPartitionAffinityDomainType::not_applicable; +} + +template +int *get_info_enum_array(__dpctl_keep const DPCTLSyclDeviceRef DRef, + size_t *res_len, + ConvertFn convert) +{ + int *arr = nullptr; + *res_len = 0; + auto D = unwrap(DRef); + if (D) { + try { + auto values = D->get_info(); + *res_len = values.size(); + if (*res_len > 0) { + arr = new int[*res_len]; + for (size_t i = 0; i < *res_len; ++i) { + arr[i] = convert(values[i]); + } + } + } catch (std::exception const &e) { + error_handler(e, __FILE__, __func__, __LINE__); + delete[] arr; + arr = nullptr; + *res_len = 0; + } + } + return arr; +} + +} // end of anonymous namespace + +__dpctl_keep int * +DPCTLDevice_GetHalfFPConfig(__dpctl_keep const DPCTLSyclDeviceRef DRef, + size_t *res_len) +{ + return get_info_enum_array( + DRef, res_len, dpctl_fp_config_to_int); +} + +__dpctl_keep int * +DPCTLDevice_GetSingleFPConfig(__dpctl_keep const DPCTLSyclDeviceRef DRef, + size_t *res_len) +{ + return get_info_enum_array( + DRef, res_len, dpctl_fp_config_to_int); +} + +__dpctl_keep int * +DPCTLDevice_GetDoubleFPConfig(__dpctl_keep const DPCTLSyclDeviceRef DRef, + size_t *res_len) +{ + return get_info_enum_array( + DRef, res_len, dpctl_fp_config_to_int); +} + +__dpctl_keep int *DPCTLDevice_GetAtomicMemoryOrderCapabilities( + __dpctl_keep const DPCTLSyclDeviceRef DRef, + size_t *res_len) +{ + return get_info_enum_array( + DRef, res_len, dpctl_memory_order_to_int); +} + +__dpctl_keep int *DPCTLDevice_GetAtomicFenceOrderCapabilities( + __dpctl_keep const DPCTLSyclDeviceRef DRef, + size_t *res_len) +{ + return get_info_enum_array( + DRef, res_len, dpctl_memory_order_to_int); +} + +__dpctl_keep int *DPCTLDevice_GetAtomicMemoryScopeCapabilities( + __dpctl_keep const DPCTLSyclDeviceRef DRef, + size_t *res_len) +{ + return get_info_enum_array( + DRef, res_len, dpctl_memory_scope_to_int); +} + +__dpctl_keep int *DPCTLDevice_GetAtomicFenceScopeCapabilities( + __dpctl_keep const DPCTLSyclDeviceRef DRef, + size_t *res_len) +{ + return get_info_enum_array( + DRef, res_len, dpctl_memory_scope_to_int); +} + +__dpctl_keep int * +DPCTLDevice_GetPartitionProperties(__dpctl_keep const DPCTLSyclDeviceRef DRef, + size_t *res_len) +{ + return get_info_enum_array( + DRef, res_len, dpctl_partition_property_to_int); +} + +__dpctl_keep int *DPCTLDevice_GetPartitionAffinityDomains( + __dpctl_keep const DPCTLSyclDeviceRef DRef, + size_t *res_len) +{ + return get_info_enum_array( + DRef, res_len, dpctl_partition_affinity_domain_to_int); +} diff --git a/libsyclinterface/source/dpctl_utils.cpp b/libsyclinterface/source/dpctl_utils.cpp index 16c79fc8b0..0d4eb8840b 100644 --- a/libsyclinterface/source/dpctl_utils.cpp +++ b/libsyclinterface/source/dpctl_utils.cpp @@ -29,3 +29,5 @@ void DPCTLCString_Delete(__dpctl_take const char *str) { delete[] str; } void DPCTLSize_t_Array_Delete(__dpctl_take size_t *arr) { delete[] arr; } + +void DPCTLInt_Array_Delete(__dpctl_take int *arr) { delete[] arr; } diff --git a/libsyclinterface/tests/test_sycl_device_interface.cpp b/libsyclinterface/tests/test_sycl_device_interface.cpp index 3aa89b53be..dd7b8ac11c 100644 --- a/libsyclinterface/tests/test_sycl_device_interface.cpp +++ b/libsyclinterface/tests/test_sycl_device_interface.cpp @@ -551,6 +551,136 @@ TEST_P(TestDPCTLSyclDeviceInterface, ChkGetCompositeDevice) } } +TEST_P(TestDPCTLSyclDeviceInterface, ChkGetVendorId) +{ + uint32_t vid = 0; + EXPECT_NO_FATAL_FAILURE(vid = DPCTLDevice_GetVendorId(DRef)); + EXPECT_TRUE(vid > 0); +} + +TEST_P(TestDPCTLSyclDeviceInterface, ChkGetAddressBits) +{ + uint32_t ab = 0; + EXPECT_NO_FATAL_FAILURE(ab = DPCTLDevice_GetAddressBits(DRef)); + EXPECT_TRUE(ab == 32 || ab == 64); +} + +TEST_P(TestDPCTLSyclDeviceInterface, ChkGetMaxSamplers) +{ + uint32_t ms = 0; + EXPECT_NO_FATAL_FAILURE(ms = DPCTLDevice_GetMaxSamplers(DRef)); + EXPECT_TRUE(ms >= 0); +} + +TEST_P(TestDPCTLSyclDeviceInterface, ChkGetMaxParameterSize) +{ + size_t mps = 0; + EXPECT_NO_FATAL_FAILURE(mps = DPCTLDevice_GetMaxParameterSize(DRef)); + EXPECT_TRUE(mps > 0); +} + +TEST_P(TestDPCTLSyclDeviceInterface, ChkGetMemBaseAddrAlign) +{ + uint32_t align = 0; + EXPECT_NO_FATAL_FAILURE(align = DPCTLDevice_GetMemBaseAddrAlign(DRef)); + EXPECT_TRUE(align > 0); +} + +TEST_P(TestDPCTLSyclDeviceInterface, ChkGetErrorCorrectionSupport) +{ + bool ecs = false; + EXPECT_NO_FATAL_FAILURE(ecs = DPCTLDevice_GetErrorCorrectionSupport(DRef)); + (void)ecs; +} + +TEST_P(TestDPCTLSyclDeviceInterface, ChkIsAvailable) +{ + bool avail = false; + EXPECT_NO_FATAL_FAILURE(avail = DPCTLDevice_IsAvailable(DRef)); + EXPECT_TRUE(avail); +} + +TEST_P(TestDPCTLSyclDeviceInterface, ChkGetVersion) +{ + const char *ver = nullptr; + EXPECT_NO_FATAL_FAILURE(ver = DPCTLDevice_GetVersion(DRef)); + EXPECT_TRUE(ver != nullptr); + EXPECT_NO_FATAL_FAILURE(DPCTLCString_Delete(ver)); +} + +TEST_P(TestDPCTLSyclDeviceInterface, ChkGetBackendVersion) +{ + const char *ver = nullptr; + EXPECT_NO_FATAL_FAILURE(ver = DPCTLDevice_GetBackendVersion(DRef)); + EXPECT_TRUE(ver != nullptr); + EXPECT_NO_FATAL_FAILURE(DPCTLCString_Delete(ver)); +} + +TEST_P(TestDPCTLSyclDeviceInterface, ChkGetLocalMemType) +{ + DPCTLLocalMemType lmt; + EXPECT_NO_FATAL_FAILURE(lmt = DPCTLDevice_GetLocalMemType(DRef)); + EXPECT_TRUE(lmt == DPCTL_LOCAL_MEM_TYPE_NONE || + lmt == DPCTL_LOCAL_MEM_TYPE_LOCAL || + lmt == DPCTL_LOCAL_MEM_TYPE_GLOBAL); +} + +TEST_P(TestDPCTLSyclDeviceInterface, ChkGetPartitionTypeProperty) +{ + DPCTLPartitionPropertyType ptp; + EXPECT_NO_FATAL_FAILURE(ptp = DPCTLDevice_GetPartitionTypeProperty(DRef)); + EXPECT_TRUE(ptp == DPCTL_PARTITION_NO_PARTITION || + ptp == DPCTL_PARTITION_EQUALLY || + ptp == DPCTL_PARTITION_BY_COUNTS || + ptp == DPCTL_PARTITION_BY_AFFINITY_DOMAIN); +} + +TEST_P(TestDPCTLSyclDeviceInterface, ChkGetSingleFPConfig) +{ + int *arr = nullptr; + size_t len = 0; + EXPECT_NO_FATAL_FAILURE(arr = DPCTLDevice_GetSingleFPConfig(DRef, &len)); + EXPECT_TRUE(len > 0); + EXPECT_TRUE(arr != nullptr); + if (arr) + delete[] arr; +} + +TEST_P(TestDPCTLSyclDeviceInterface, ChkGetAtomicMemoryOrderCapabilities) +{ + int *arr = nullptr; + size_t len = 0; + EXPECT_NO_FATAL_FAILURE( + arr = DPCTLDevice_GetAtomicMemoryOrderCapabilities(DRef, &len)); + EXPECT_TRUE(len > 0); + EXPECT_TRUE(arr != nullptr); + if (arr) + delete[] arr; +} + +TEST_P(TestDPCTLSyclDeviceInterface, ChkGetAtomicMemoryScopeCapabilities) +{ + int *arr = nullptr; + size_t len = 0; + EXPECT_NO_FATAL_FAILURE( + arr = DPCTLDevice_GetAtomicMemoryScopeCapabilities(DRef, &len)); + EXPECT_TRUE(len > 0); + EXPECT_TRUE(arr != nullptr); + if (arr) + delete[] arr; +} + +TEST_P(TestDPCTLSyclDeviceInterface, ChkGetPartitionProperties) +{ + int *arr = nullptr; + size_t len = 0; + EXPECT_NO_FATAL_FAILURE(arr = + DPCTLDevice_GetPartitionProperties(DRef, &len)); + // may be empty if device doesn't support partitioning + if (arr) + delete[] arr; +} + INSTANTIATE_TEST_SUITE_P(DPCTLDeviceFns, TestDPCTLSyclDeviceInterface, ::testing::Values("opencl",