Skip to content
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
20 changes: 20 additions & 0 deletions dpctl-capi/include/dpctl_sycl_device_manager.h
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,26 @@ DPCTL_API
__dpctl_give DPCTLDeviceVectorRef
DPCTLDeviceMgr_GetDevices(int device_identifier);

/*!
* @brief Returns an index on the given device in the vector returned by
* #DPCTLDeviceMgr_GetDevices if found, -1 otherwise.
*
* The device_identifier can be a combination of #DPCTLSyclBackendType and
* #DPCTLSyclDeviceType bit flags. The function returns all devices that
* match the specified bit flags.
*
* @param DRef A #DPCTLSyclDeviceRef opaque pointer.
* @param device_identifier A bitflag that can be any combination of
* #DPCTLSyclBackendType and #DPCTLSyclDeviceType
* enum values.
* @return If found, returns the position of the given device in the
* vector that would be returned by #DPCTLDeviceMgr_GetDevices if called
* with the same device_identifier argument.
*/
DPCTL_API
int DPCTLDeviceMgr_GetPositionInDevices(__dpctl_keep DPCTLSyclDeviceRef DRef,
int device_identifier);

/*!
* @brief If the DPCTLSyclDeviceRef argument is a root device, then this
* function returns a cached default SYCL context for that device.
Expand Down
29 changes: 29 additions & 0 deletions dpctl-capi/source/dpctl_sycl_device_manager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,35 @@ DPCTLDeviceMgr_GetDevices(int device_identifier)
return wrap(Devices);
}

int DPCTLDeviceMgr_GetPositionInDevices(__dpctl_keep DPCTLSyclDeviceRef DRef,
int device_identifier)
{
constexpr int not_found = -1;
if (!DRef) {
return not_found;
}

const auto &root_devices = device::get_devices();
default_selector mRanker;
int index = not_found;
auto reference_device = *(unwrap(DRef));

for (const auto &root_device : root_devices) {
if (mRanker(root_device) < 0)
continue;
auto Bty(DPCTL_SyclBackendToDPCTLBackendType(
root_device.get_platform().get_backend()));
auto Dty(DPCTL_SyclDeviceTypeToDPCTLDeviceType(
root_device.get_info<info::device::device_type>()));
if ((device_identifier & Bty) && (device_identifier & Dty)) {
++index;
if (root_device == reference_device)
return index;
}
}
return not_found;
}

/*!
* Returns the number of available devices for a specific backend and device
* type combination.
Expand Down
11 changes: 8 additions & 3 deletions dpctl-capi/tests/test_sycl_device_manager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -146,12 +146,12 @@ struct TestDPCTLGetDevicesOrdering : public ::testing::TestWithParam<int>
{
DPCTLDeviceVectorRef DV = nullptr;
size_t nDevices = 0;
int device_type_mask;

TestDPCTLGetDevicesOrdering()
{
const int device_type_mask =
(GetParam() & DPCTLSyclDeviceType::DPCTL_ALL) |
DPCTLSyclBackendType::DPCTL_ALL_BACKENDS;
device_type_mask = (GetParam() & DPCTLSyclDeviceType::DPCTL_ALL) |
DPCTLSyclBackendType::DPCTL_ALL_BACKENDS;
EXPECT_NO_FATAL_FAILURE(
DV = DPCTLDeviceMgr_GetDevices(device_type_mask));
EXPECT_TRUE(DV != nullptr);
Expand Down Expand Up @@ -179,6 +179,7 @@ TEST_P(TestDPCTLGetDevicesOrdering, ChkConsistencyWithFilterSelector)
std::string fs_device_type, fs;
DPCTLSyclDeviceRef DRef = nullptr, D0Ref = nullptr;
DPCTLSyclDeviceSelectorRef DSRef = nullptr;
int j = -1;
EXPECT_NO_FATAL_FAILURE(DRef = DPCTLDeviceVector_GetAt(DV, i));
EXPECT_NO_FATAL_FAILURE(Dty = DPCTLDevice_GetDeviceType(DRef));
EXPECT_NO_FATAL_FAILURE(
Expand All @@ -189,6 +190,10 @@ TEST_P(TestDPCTLGetDevicesOrdering, ChkConsistencyWithFilterSelector)
EXPECT_NO_FATAL_FAILURE(D0Ref = DPCTLDevice_CreateFromSelector(DSRef));
EXPECT_NO_FATAL_FAILURE(DPCTLDeviceSelector_Delete(DSRef));
EXPECT_TRUE(DPCTLDevice_AreEq(DRef, D0Ref));
EXPECT_NO_FATAL_FAILURE(
j = DPCTLDeviceMgr_GetPositionInDevices(DRef, device_type_mask));
EXPECT_TRUE(j >= 0);
EXPECT_TRUE(i == static_cast<decltype(i)>(j));
EXPECT_NO_FATAL_FAILURE(DPCTLDevice_Delete(D0Ref));
EXPECT_NO_FATAL_FAILURE(DPCTLDevice_Delete(DRef));
}
Expand Down
3 changes: 3 additions & 0 deletions dpctl/_backend.pxd
Original file line number Diff line number Diff line change
Expand Up @@ -208,6 +208,9 @@ cdef extern from "dpctl_sycl_device_manager.h":
DPCTLDeviceVectorRef DVRef,
size_t index)
cdef DPCTLDeviceVectorRef DPCTLDeviceMgr_GetDevices(int device_identifier)
cdef int DPCTLDeviceMgr_GetPositionInDevices(
const DPCTLSyclDeviceRef DRef,
int device_identifier)
cdef size_t DPCTLDeviceMgr_GetNumDevices(int device_identifier)
cdef void DPCTLDeviceMgr_PrintDeviceInfo(const DPCTLSyclDeviceRef DRef)
cdef DPCTLSyclContextRef DPCTLDeviceMgr_GetCachedContext(
Expand Down
4 changes: 4 additions & 0 deletions dpctl/_sycl_device.pxd
Original file line number Diff line number Diff line change
Expand Up @@ -51,3 +51,7 @@ cdef public class SyclDevice(_SyclDevice) [object PySyclDeviceObject, type PySyc
cdef list create_sub_devices_by_counts(self, object counts)
cdef list create_sub_devices_by_affinity(self, _partition_affinity_domain_type domain)
cdef cpp_bool equals(self, SyclDevice q)
cdef int get_device_type_ordinal(self)
cdef int get_overall_ordinal(self)
cdef int get_backend_ordinal(self)
cdef int get_backend_and_device_type_ordinal(self)
152 changes: 150 additions & 2 deletions dpctl/_sycl_device.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,8 @@ from ._backend cimport ( # noqa: E211
DPCTLDevice_IsCPU,
DPCTLDevice_IsGPU,
DPCTLDevice_IsHost,
DPCTLDeviceMgr_GetDevices,
DPCTLDeviceMgr_GetPositionInDevices,
DPCTLDeviceMgr_GetRelativeId,
DPCTLDeviceMgr_PrintDeviceInfo,
DPCTLDeviceSelector_Delete,
Expand Down Expand Up @@ -825,8 +827,23 @@ cdef class SyclDevice(_SyclDevice):

@property
def filter_string(self):
""" For a parent device, returns a ``tuple (backend, device_kind,
relative_id)``. Raises an exception for sub-devices.
"""
For a parent device, returns a fully specified filter selector
string``backend:device_type:relative_id`` selecting the device.

Raises an exception for sub-devices.

: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")
# filter_string property should be "level_zero:gpu:0"
dev = dpctl.SyclDevice(level_zero_gpu.filter_string)
assert level_zero_gpu == dev
"""
cdef DPCTLSyclDeviceRef pDRef = NULL
cdef DPCTLSyclBackendType BTy
Expand All @@ -846,3 +863,134 @@ cdef class SyclDevice(_SyclDevice):
# this a sub-device, free it, and raise an exception
DPCTLDevice_Delete(pDRef)
raise TypeError("This SyclDevice is not a root device")

cdef int get_backend_and_device_type_ordinal(self):
"""
If this device is a root ``sycl::device`` returns the ordinal
position of this device in the vector
``sycl::device::get_devices(device_type_of_this_device)``
filtered to contain only devices with the same backend as this
device.

Returns -1 if the device is a sub-device, or the device could not
be found in the vector.
"""
cdef int64_t relId = DPCTLDeviceMgr_GetRelativeId(self._device_ref)
return relId

cdef int get_device_type_ordinal(self):
"""
If this device is a root ``sycl::device`` returns the ordinal
position of this device in the vector
``sycl::device::get_devices(device_type_of_this_device)``

Returns -1 if the device is a sub-device, or the device could not
be found in the vector.
"""
cdef DPCTLSyclDeviceType DTy
cdef int64_t relId = -1

DTy = DPCTLDevice_GetDeviceType(self._device_ref)
relId = DPCTLDeviceMgr_GetPositionInDevices(
self._device_ref, _backend_type._ALL_BACKENDS | DTy)
return relId

cdef int get_backend_ordinal(self):
"""
If this device is a root ``sycl::device`` returns the ordinal
position of this device in the vector ``sycl::device::get_devices()``
filtered to contain only devices with the same backend as this
device.

Returns -1 if the device is a sub-device, or the device could not
be found in the vector.
"""
cdef DPCTLSyclBackendType BTy
cdef int64_t relId = -1

BTy = DPCTLDevice_GetBackend(self._device_ref)
relId = DPCTLDeviceMgr_GetPositionInDevices(
self._device_ref, BTy | _device_type._ALL_DEVICES)
return relId

cdef int get_overall_ordinal(self):
"""
If this device is a root ``sycl::device`` returns the ordinal
position of this device in the vector ``sycl::device::get_devices()``
filtered to contain only devices with the same backend as this
device.

Returns -1 if the device is a sub-device, or the device could not
be found in the vector.
"""
cdef int64_t relId = -1

relId = DPCTLDeviceMgr_GetPositionInDevices(
self._device_ref,
(_backend_type._ALL_BACKENDS | _device_type._ALL_DEVICES)
)
return relId

def get_filter_string(self, include_backend=True, include_device_type=True):
"""
For a parent device returns a filter selector string
that includes backend or device type based on the value
of the given keyword arguments.

Raises a TypeError if this devices is a sub-device, or
a ValueError if no match was found in the vector returned
by ``sycl::device::get_devices()``.

:Example:
.. code-block:: python

import dpctl

# Create a GPU SyclDevice
gpu_dev = dpctl.SyclDevice("gpu:0")
# filter string should be "gpu:0"
fs = gpu_dev.get_filter_string(use_backend=False)
dev = dpctl.SyclDevice(fs)
assert gpu _dev == dev
"""
cdef int relId = -1
cdef DPCTLSyclDeviceRef pDRef = NULL
cdef DPCTLSyclDeviceType DTy
cdef DPCTLSyclBackendType BTy

if include_backend:
if include_device_type:
relId = self.get_backend_and_device_type_ordinal()
else:
relId = self.get_backend_ordinal()
else:
if include_device_type:
relId = self.get_device_type_ordinal()
else:
relId = self.get_overall_ordinal()

if relId < 0:
pDRef = DPCTLDevice_GetParentDevice(self._device_ref)
if (pDRef is NULL):
raise ValueError
else:
# this a sub-device, free it, and raise an exception
DPCTLDevice_Delete(pDRef)
raise TypeError("This SyclDevice is not a root device")
else:
if include_backend:
BTy = DPCTLDevice_GetBackend(self._device_ref)
be_str = _backend_type_to_filter_string_part(BTy)
if include_device_type:
DTy = DPCTLDevice_GetDeviceType(self._device_ref)
dt_str = _device_type_to_filter_string_part(DTy)
return ":".join((be_str, dt_str, str(relId)))
else:
return ":".join((be_str, str(relId)))
else:
if include_device_type:
DTy = DPCTLDevice_GetDeviceType(self._device_ref)
dt_str = _device_type_to_filter_string_part(DTy)
return ":".join((dt_str, str(relId)))
else:
return str(relId)
20 changes: 18 additions & 2 deletions dpctl/tests/test_sycl_device.py
Original file line number Diff line number Diff line change
Expand Up @@ -591,13 +591,29 @@ def test_filter_string(valid_filter):
)


def test_filter_string2():
def test_filter_string_property():
"""
Test that filter_string reconstructs the same device.
"""
devices = dpctl.get_devices()
for d in devices:
if d.default_selector_score > 0:
if d.default_selector_score >= 0:
dev_id = d.filter_string
d_r = dpctl.SyclDevice(dev_id)
assert d == d_r


def test_filter_string_method():
"""
Test that filter_string reconstructs the same device.
"""
devices = dpctl.get_devices()
for d in devices:
for be in [True, False]:
for dt in [True, False]:
if d.default_selector_score >= 0:
dev_id = d.get_filter_string(
include_backend=be, include_device_type=dt
)
d_r = dpctl.SyclDevice(dev_id)
assert d == d_r, "Failed "