@@ -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)
0 commit comments