Skip to content

Fix/refactor sycl device #321

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Mar 13, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 9 additions & 10 deletions dpctl/_sycl_device.pxd
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,15 @@ cdef class _SyclDevice:
cdef size_t *_max_work_item_sizes
cdef size_t _max_work_group_size
cdef uint32_t _max_num_sub_groups


cdef class SyclDevice(_SyclDevice):
@staticmethod
cdef SyclDevice _create(DPCTLSyclDeviceRef dref)
@staticmethod
cdef void _init_helper(SyclDevice device, DPCTLSyclDeviceRef DRef)
cdef int _init_from__SyclDevice(self, _SyclDevice other)
cdef int _init_from_selector(self, DPCTLSyclDeviceSelectorRef DSRef)
cdef DPCTLSyclDeviceRef get_device_ref(self)
cpdef get_backend(self)
cpdef get_device_name(self)
Expand All @@ -59,13 +68,3 @@ cdef class _SyclDevice:
cpdef is_cpu(self)
cpdef is_gpu(self)
cpdef is_host(self)


cdef class SyclDevice(_SyclDevice):
@staticmethod
cdef SyclDevice _create(DPCTLSyclDeviceRef dref)
@staticmethod
cdef void _init_helper(SyclDevice device, DPCTLSyclDeviceRef DRef)
cdef void _init_from__SyclDevice(self, _SyclDevice other)
cdef int _init_from_selector(self, DPCTLSyclDeviceSelectorRef DSRef)

269 changes: 137 additions & 132 deletions dpctl/_sycl_device.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,8 @@ from ._backend cimport (
_aspect_type,
_backend_type,
_device_type,
DPCTLDefaultSelector_Create,
DPCTLCString_Delete,
DPCTLDefaultSelector_Create,
DPCTLDevice_Copy,
DPCTLDevice_CreateFromSelector,
DPCTLDevice_Delete,
Expand Down Expand Up @@ -72,6 +72,139 @@ cdef class _SyclDevice:
DPCTLCString_Delete(self._driver_version)
DPCTLSize_t_Array_Delete(self._max_work_item_sizes)


cdef class SyclDevice(_SyclDevice):
""" Python equivalent for cl::sycl::device class.

There are two ways of creating a SyclDevice instance:

- by directly passing in a filter string to the class constructor. The
filter string needs to conform to the the `DPC++ filter selector SYCL
extension <https://bit.ly/37kqANT>`_.

:Example:
.. code-block:: python

import dpctl

# Create a SyclDevice with an explicit filter string, in
# this case the first level_zero gpu device.
level_zero_gpu = dpctl.SyclDevice("level_zero:gpu:0"):
level_zero_gpu.dump_device_info()

- by calling one of the device selector helper functions:

:func:`dpctl.select_accelerator_device()`,
:func:`dpctl.select_cpu_device()`,
:func:`dpctl.select_default_device()`,
:func:`dpctl.select_gpu_device()`,
:func:`dpctl.select_host_device()`.


:Example:
.. code-block:: python

import dpctl

# Create a SyclDevice of type GPU based on whatever is returned
# by the SYCL `gpu_selector` device selector class.
gpu = dpctl.select_gpu_device():
gpu.dump_device_info()

"""
@staticmethod
cdef void _init_helper(SyclDevice device, DPCTLSyclDeviceRef DRef):
device._device_ref = DRef
device._device_name = DPCTLDevice_GetName(DRef)
device._driver_version = DPCTLDevice_GetDriverInfo(DRef)
device._vendor_name = DPCTLDevice_GetVendorName(DRef)
device._accelerator_device = DPCTLDevice_IsAccelerator(DRef)
device._cpu_device = DPCTLDevice_IsCPU(DRef)
device._gpu_device = DPCTLDevice_IsGPU(DRef)
device._host_device = DPCTLDevice_IsHost(DRef)
device._max_compute_units = DPCTLDevice_GetMaxComputeUnits(DRef)
if (device._host_device):
device._max_num_sub_groups = 0
else:
device._max_num_sub_groups = DPCTLDevice_GetMaxNumSubGroups(DRef)
device._max_work_group_size = DPCTLDevice_GetMaxWorkGroupSize(DRef)
device._max_work_item_dims = DPCTLDevice_GetMaxWorkItemDims(DRef)
device._max_work_item_sizes = DPCTLDevice_GetMaxWorkItemSizes(DRef)

@staticmethod
cdef SyclDevice _create(DPCTLSyclDeviceRef dref):
cdef SyclDevice ret = <SyclDevice>_SyclDevice.__new__(_SyclDevice)
# Initialize the attributes of the SyclDevice object
SyclDevice._init_helper(ret, dref)
return SyclDevice(ret)

cdef int _init_from__SyclDevice(self, _SyclDevice other):
self._device_ref = DPCTLDevice_Copy(other._device_ref)
if (self._device_ref is NULL):
return -1
self._device_name = DPCTLDevice_GetName(self._device_ref)
self._driver_version = DPCTLDevice_GetDriverInfo(self._device_ref)
self._max_compute_units = other._max_compute_units
self._max_num_sub_groups = other._max_num_sub_groups
self._max_work_group_size = other._max_work_group_size
self._max_work_item_dims = other._max_work_item_dims
self._max_work_item_sizes = (
DPCTLDevice_GetMaxWorkItemSizes(self._device_ref)
)
self._vendor_name = DPCTLDevice_GetVendorName(self._device_ref)
self._accelerator_device = other._accelerator_device
self._cpu_device = other._cpu_device
self._gpu_device = other._gpu_device
self._host_device = other._host_device

cdef int _init_from_selector(self, DPCTLSyclDeviceSelectorRef DSRef):
# Initialize the attributes of the SyclDevice object
cdef DPCTLSyclDeviceRef DRef = DPCTLDevice_CreateFromSelector(DSRef)
if DRef is NULL:
return -1
else:
SyclDevice._init_helper(self, DRef)
return 0

def __cinit__(self, arg=None):
cdef DPCTLSyclDeviceSelectorRef DSRef = NULL
cdef DPCTLSyclDeviceRef DRef = NULL
cdef const char *filter_c_str = NULL
cdef int ret = 0

if type(arg) is unicode:
string = bytes(<unicode>arg, "utf-8")
filter_c_str = string
DSRef = DPCTLFilterSelector_Create(filter_c_str)
ret = self._init_from_selector(DSRef)
if ret == -1:
raise ValueError("Could not create a Device with the selector")
# Free up the device selector
DPCTLDeviceSelector_Delete(DSRef)
elif isinstance(arg, unicode):
string = bytes(<unicode>unicode(arg), "utf-8")
filter_c_str = string
DSRef = DPCTLFilterSelector_Create(filter_c_str)
ret = self._init_from_selector(DSRef)
if ret == -1:
raise ValueError("Could not create a Device with the selector")
# Free up the device selector
DPCTLDeviceSelector_Delete(DSRef)
elif isinstance(arg, _SyclDevice):
ret = self._init_from__SyclDevice(arg)
if ret == -1:
raise ValueError("Could not create a Device from _SyclDevice instance")
elif arg is None:
DSRef = DPCTLDefaultSelector_Create()
ret = self._init_from_selector(DSRef)
if ret == -1:
raise ValueError("Could not create a Device from default selector")
else:
raise ValueError(
"Invalid argument. Argument should be a str object specifying "
"a SYCL filter selector string."
)

def dump_device_info(self):
""" Print information about the SYCL device.
"""
Expand Down Expand Up @@ -240,136 +373,6 @@ cdef class _SyclDevice:
"""
return int(<size_t>self._device_ref)

@property
def __name__(self):
return "SyclDevice"

def __repr__(self):
return "<dpctl." + self.__name__ + " at {}>".format(hex(id(self)))


cdef class SyclDevice(_SyclDevice):
""" Python equivalent for cl::sycl::device class.

There are two ways of creating a SyclDevice instance:

- by directly passing in a filter string to the class constructor. The
filter string needs to conform to the the `DPC++ filter selector SYCL
extension <https://bit.ly/37kqANT>`_.

:Example:
.. code-block:: python

import dpctl

# Create a SyclDevice with an explicit filter string, in
# this case the first level_zero gpu device.
level_zero_gpu = dpctl.SyclDevice("level_zero:gpu:0"):
level_zero_gpu.dump_device_info()

- by calling one of the device selector helper functions:

:func:`dpctl.select_accelerator_device()`,
:func:`dpctl.select_cpu_device()`,
:func:`dpctl.select_default_device()`,
:func:`dpctl.select_gpu_device()`,
:func:`dpctl.select_host_device()`.


:Example:
.. code-block:: python

import dpctl

# Create a SyclDevice of type GPU based on whatever is returned
# by the SYCL `gpu_selector` device selector class.
gpu = dpctl.select_gpu_device():
gpu.dump_device_info()

"""
@staticmethod
cdef void _init_helper(SyclDevice device, DPCTLSyclDeviceRef DRef):
device._device_ref = DRef
device._device_name = DPCTLDevice_GetName(DRef)
device._driver_version = DPCTLDevice_GetDriverInfo(DRef)
device._max_compute_units = DPCTLDevice_GetMaxComputeUnits(DRef)
device._max_num_sub_groups = DPCTLDevice_GetMaxNumSubGroups(DRef)
device._max_work_group_size = DPCTLDevice_GetMaxWorkGroupSize(DRef)
device._max_work_item_dims = DPCTLDevice_GetMaxWorkItemDims(DRef)
device._max_work_item_sizes = DPCTLDevice_GetMaxWorkItemSizes(DRef)
device._vendor_name = DPCTLDevice_GetVendorName(DRef)
device._accelerator_device = DPCTLDevice_IsAccelerator(DRef)
device._cpu_device = DPCTLDevice_IsCPU(DRef)
device._gpu_device = DPCTLDevice_IsGPU(DRef)
device._host_device = DPCTLDevice_IsHost(DRef)

@staticmethod
cdef SyclDevice _create(DPCTLSyclDeviceRef dref):
cdef SyclDevice ret = <SyclDevice>_SyclDevice.__new__(_SyclDevice)
# Initialize the attributes of the SyclDevice object
SyclDevice._init_helper(ret, dref)
return SyclDevice(ret)

cdef void _init_from__SyclDevice(self, _SyclDevice other):
self._device_ref = DPCTLDevice_Copy(other._device_ref)
self._device_name = DPCTLDevice_GetName(self._device_ref)
self._driver_version = DPCTLDevice_GetDriverInfo(self._device_ref)
self._max_compute_units = other._max_compute_units
self._max_num_sub_groups = other._max_num_sub_groups
self._max_work_group_size = other._max_work_group_size
self._max_work_item_dims = other._max_work_item_dims
self._max_work_item_sizes = (
DPCTLDevice_GetMaxWorkItemSizes(self._device_ref)
)
self._vendor_name = DPCTLDevice_GetVendorName(self._device_ref)
self._accelerator_device = other._accelerator_device
self._cpu_device = other._cpu_device
self._gpu_device = other._gpu_device
self._host_device = other._host_device

cdef int _init_from_selector(self, DPCTLSyclDeviceSelectorRef DSRef):
# Initialize the attributes of the SyclDevice object
DRef = DPCTLDevice_CreateFromSelector(DSRef)
if DRef is NULL:
return -1
else:
SyclDevice._init_helper(self, DRef)
return 0

def __cinit__(self, arg=None):
cdef DPCTLSyclDeviceSelectorRef DSRef = NULL
cdef DPCTLSyclDeviceRef DRef = NULL
cdef const char *filter_c_str = NULL
cdef int ret = 0

if type(arg) is unicode:
string = bytes(<unicode>arg, "utf-8")
filter_c_str = string
DSRef = DPCTLFilterSelector_Create(filter_c_str)
ret = self._init_from_selector(DSRef)
if ret == -1:
raise ValueError("Could not create a Device with the selector")
# Free up the device selector
DPCTLDeviceSelector_Delete(DSRef)
elif isinstance(arg, unicode):
string = bytes(unicode(arg), "utf-8")
filter_c_str = <unicode>string
DSRef = DPCTLFilterSelector_Create(filter_c_str)
if ret == -1:
raise ValueError("Could not create a Device with the selector")
# Free up the device selector
DPCTLDeviceSelector_Delete(DSRef)
elif isinstance(arg, _SyclDevice):
self._init_from__SyclDevice(arg)
elif arg is None:
DSRef = DPCTLDefaultSelector_Create()
self._init_from_selector(DSRef)
else:
raise ValueError(
"Invalid argument. Argument should be a str object specifying "
"a SYCL filter selector string."
)

@property
def has_aspect_host(self):
cdef _aspect_type AT = _aspect_type._host
Expand Down Expand Up @@ -465,4 +468,6 @@ cdef class SyclDevice(_SyclDevice):
return "SyclDevice"

def __repr__(self):
return "<dpctl." + self.__name__ + " at {}>".format(hex(id(self)))
return ("<dpctl." + self.__name__ + " [" +
str(self.get_backend()) + ", " + str(self.get_device_type()) +", " +
" " + self.get_device_name() + "] at {}>".format(hex(id(self))) )