Skip to content

Commit c31be27

Browse files
dpctl.SyclDevice.get_filter_string method added
dpctl.SyclDevice.filter_string property gives fully specified filter selector, which includes backend, device_type and relative id. get_filter_string(include_backend, include_device_type) allows one to construct filter strings which would omit either backend or device_type or both, guaranteeing that dpctl.SyclDevice(obtained_selector_string) will give back the same device. ``` In [1]: import dpctl In [2]: default_dev = dpctl.SyclDevice() In [3]: default_dev.get_filter_string(include_backend=False) Out[3]: 'gpu:1' In [4]: default_dev.get_filter_string(include_device_type=False) Out[4]: 'level_zero:0' In [5]: default_dev.get_filter_string(include_device_type=False, include_backend=False) Out[5]: '4' ```
1 parent 9954fa7 commit c31be27

File tree

4 files changed

+175
-4
lines changed

4 files changed

+175
-4
lines changed

dpctl/_backend.pxd

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -208,6 +208,9 @@ cdef extern from "dpctl_sycl_device_manager.h":
208208
DPCTLDeviceVectorRef DVRef,
209209
size_t index)
210210
cdef DPCTLDeviceVectorRef DPCTLDeviceMgr_GetDevices(int device_identifier)
211+
cdef int DPCTLDeviceMgr_GetPositionInDevices(
212+
const DPCTLSyclDeviceRef DRef,
213+
int device_identifier)
211214
cdef size_t DPCTLDeviceMgr_GetNumDevices(int device_identifier)
212215
cdef void DPCTLDeviceMgr_PrintDeviceInfo(const DPCTLSyclDeviceRef DRef)
213216
cdef DPCTLSyclContextRef DPCTLDeviceMgr_GetCachedContext(

dpctl/_sycl_device.pxd

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,3 +51,7 @@ cdef public class SyclDevice(_SyclDevice) [object PySyclDeviceObject, type PySyc
5151
cdef list create_sub_devices_by_counts(self, object counts)
5252
cdef list create_sub_devices_by_affinity(self, _partition_affinity_domain_type domain)
5353
cdef cpp_bool equals(self, SyclDevice q)
54+
cdef int get_device_type_ordinal(self)
55+
cdef int get_overall_ordinal(self)
56+
cdef int get_backend_ordinal(self)
57+
cdef int get_backend_and_device_type_ordinal(self)

dpctl/_sycl_device.pyx

Lines changed: 150 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,8 @@ from ._backend cimport ( # noqa: E211
6161
DPCTLDevice_IsCPU,
6262
DPCTLDevice_IsGPU,
6363
DPCTLDevice_IsHost,
64+
DPCTLDeviceMgr_GetDevices,
65+
DPCTLDeviceMgr_GetPositionInDevices,
6466
DPCTLDeviceMgr_GetRelativeId,
6567
DPCTLDeviceMgr_PrintDeviceInfo,
6668
DPCTLDeviceSelector_Delete,
@@ -825,8 +827,23 @@ cdef class SyclDevice(_SyclDevice):
825827

826828
@property
827829
def filter_string(self):
828-
""" For a parent device, returns a ``tuple (backend, device_kind,
829-
relative_id)``. Raises an exception for sub-devices.
830+
"""
831+
For a parent device, returns a fully specified filter selector
832+
string``backend:device_type:relative_id`` selecting the device.
833+
834+
Raises an exception for sub-devices.
835+
836+
:Example:
837+
.. code-block:: python
838+
839+
import dpctl
840+
841+
# Create a SyclDevice with an explicit filter string,
842+
# in this case the first level_zero gpu device.
843+
level_zero_gpu = dpctl.SyclDevice("level_zero:gpu:0")
844+
# filter_string property should be "level_zero:gpu:0"
845+
dev = dpctl.SyclDevice(level_zero_gpu.filter_string)
846+
assert level_zero_gpu == dev
830847
"""
831848
cdef DPCTLSyclDeviceRef pDRef = NULL
832849
cdef DPCTLSyclBackendType BTy
@@ -846,3 +863,134 @@ cdef class SyclDevice(_SyclDevice):
846863
# this a sub-device, free it, and raise an exception
847864
DPCTLDevice_Delete(pDRef)
848865
raise TypeError("This SyclDevice is not a root device")
866+
867+
cdef int get_backend_and_device_type_ordinal(self):
868+
"""
869+
If this device is a root ``sycl::device`` returns the ordinal
870+
position of this device in the vector
871+
``sycl::device::get_devices(device_type_of_this_device)``
872+
filtered to contain only devices with the same backend as this
873+
device.
874+
875+
Returns -1 if the device is a sub-device, or the device could not
876+
be found in the vector.
877+
"""
878+
cdef int64_t relId = DPCTLDeviceMgr_GetRelativeId(self._device_ref)
879+
return relId
880+
881+
cdef int get_device_type_ordinal(self):
882+
"""
883+
If this device is a root ``sycl::device`` returns the ordinal
884+
position of this device in the vector
885+
``sycl::device::get_devices(device_type_of_this_device)``
886+
887+
Returns -1 if the device is a sub-device, or the device could not
888+
be found in the vector.
889+
"""
890+
cdef DPCTLSyclDeviceType DTy
891+
cdef int64_t relId = -1
892+
893+
DTy = DPCTLDevice_GetDeviceType(self._device_ref)
894+
relId = DPCTLDeviceMgr_GetPositionInDevices(
895+
self._device_ref, _backend_type._ALL_BACKENDS | DTy)
896+
return relId
897+
898+
cdef int get_backend_ordinal(self):
899+
"""
900+
If this device is a root ``sycl::device`` returns the ordinal
901+
position of this device in the vector ``sycl::device::get_devices()``
902+
filtered to contain only devices with the same backend as this
903+
device.
904+
905+
Returns -1 if the device is a sub-device, or the device could not
906+
be found in the vector.
907+
"""
908+
cdef DPCTLSyclBackendType BTy
909+
cdef int64_t relId = -1
910+
911+
BTy = DPCTLDevice_GetBackend(self._device_ref)
912+
relId = DPCTLDeviceMgr_GetPositionInDevices(
913+
self._device_ref, BTy | _device_type._ALL_DEVICES)
914+
return relId
915+
916+
cdef int get_overall_ordinal(self):
917+
"""
918+
If this device is a root ``sycl::device`` returns the ordinal
919+
position of this device in the vector ``sycl::device::get_devices()``
920+
filtered to contain only devices with the same backend as this
921+
device.
922+
923+
Returns -1 if the device is a sub-device, or the device could not
924+
be found in the vector.
925+
"""
926+
cdef int64_t relId = -1
927+
928+
relId = DPCTLDeviceMgr_GetPositionInDevices(
929+
self._device_ref,
930+
(_backend_type._ALL_BACKENDS | _device_type._ALL_DEVICES)
931+
)
932+
return relId
933+
934+
def get_filter_string(self, include_backend=True, include_device_type=True):
935+
"""
936+
For a parent device returns a filter selector string
937+
that includes backend or device type based on the value
938+
of the given keyword arguments.
939+
940+
Raises a TypeError if this devices is a sub-device, or
941+
a ValueError if no match was found in the vector returned
942+
by ``sycl::device::get_devices()``.
943+
944+
:Example:
945+
.. code-block:: python
946+
947+
import dpctl
948+
949+
# Create a GPU SyclDevice
950+
gpu_dev = dpctl.SyclDevice("gpu:0")
951+
# filter string should be "gpu:0"
952+
fs = gpu_dev.get_filter_string(use_backend=False)
953+
dev = dpctl.SyclDevice(fs)
954+
assert gpu _dev == dev
955+
"""
956+
cdef int relId = -1
957+
cdef DPCTLSyclDeviceRef pDRef = NULL
958+
cdef DPCTLSyclDeviceType DTy
959+
cdef DPCTLSyclBackendType BTy
960+
961+
if include_backend:
962+
if include_device_type:
963+
relId = self.get_backend_and_device_type_ordinal()
964+
else:
965+
relId = self.get_backend_ordinal()
966+
else:
967+
if include_device_type:
968+
relId = self.get_device_type_ordinal()
969+
else:
970+
relId = self.get_overall_ordinal()
971+
972+
if relId < 0:
973+
pDRef = DPCTLDevice_GetParentDevice(self._device_ref)
974+
if (pDRef is NULL):
975+
raise ValueError
976+
else:
977+
# this a sub-device, free it, and raise an exception
978+
DPCTLDevice_Delete(pDRef)
979+
raise TypeError("This SyclDevice is not a root device")
980+
else:
981+
if include_backend:
982+
BTy = DPCTLDevice_GetBackend(self._device_ref)
983+
be_str = _backend_type_to_filter_string_part(BTy)
984+
if include_device_type:
985+
DTy = DPCTLDevice_GetDeviceType(self._device_ref)
986+
dt_str = _device_type_to_filter_string_part(DTy)
987+
return ":".join((be_str, dt_str, str(relId)))
988+
else:
989+
return ":".join((be_str, str(relId)))
990+
else:
991+
if include_device_type:
992+
DTy = DPCTLDevice_GetDeviceType(self._device_ref)
993+
dt_str = _device_type_to_filter_string_part(DTy)
994+
return ":".join((dt_str, str(relId)))
995+
else:
996+
return str(relId)

dpctl/tests/test_sycl_device.py

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -591,13 +591,29 @@ def test_filter_string(valid_filter):
591591
)
592592

593593

594-
def test_filter_string2():
594+
def test_filter_string_property():
595595
"""
596596
Test that filter_string reconstructs the same device.
597597
"""
598598
devices = dpctl.get_devices()
599599
for d in devices:
600-
if d.default_selector_score > 0:
600+
if d.default_selector_score >= 0:
601601
dev_id = d.filter_string
602602
d_r = dpctl.SyclDevice(dev_id)
603603
assert d == d_r
604+
605+
606+
def test_filter_string_method():
607+
"""
608+
Test that filter_string reconstructs the same device.
609+
"""
610+
devices = dpctl.get_devices()
611+
for d in devices:
612+
for be in [True, False]:
613+
for dt in [True, False]:
614+
if d.default_selector_score >= 0:
615+
dev_id = d.get_filter_string(
616+
include_backend=be, include_device_type=dt
617+
)
618+
d_r = dpctl.SyclDevice(dev_id)
619+
assert d == d_r, "Failed "

0 commit comments

Comments
 (0)