Skip to content

Commit 4f4adf5

Browse files
Merge pull request #366 from IntelPython/feature/SyclDevice-parent
Feature/sycl device parent
2 parents ffd1042 + f2c900c commit 4f4adf5

10 files changed

+169
-4
lines changed

dpctl-capi/include/dpctl_sycl_device_interface.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -479,3 +479,15 @@ uint32_t DPCTLDevice_GetPreferredVectorWidthDouble(
479479
DPCTL_API
480480
uint32_t DPCTLDevice_GetPreferredVectorWidthHalf(
481481
__dpctl_keep const DPCTLSyclDeviceRef DRef);
482+
483+
/*!
484+
* @brief Wrapper over
485+
* device.get_info<info::device::parent_device>
486+
*
487+
* @param DRef Opaque pointer to a sycl::device
488+
* @return Returns an opaque pointer to the parent device for a sub-device,
489+
* or nullptr otherwise.
490+
*/
491+
DPCTL_API
492+
__dpctl_give DPCTLSyclDeviceRef
493+
DPCTLDevice_GetParentDevice(__dpctl_keep const DPCTLSyclDeviceRef DRef);

dpctl-capi/include/dpctl_sycl_device_manager.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,4 +116,15 @@ size_t DPCTLDeviceMgr_GetNumDevices(int device_identifier);
116116
DPCTL_API
117117
void DPCTLDeviceMgr_PrintDeviceInfo(__dpctl_keep const DPCTLSyclDeviceRef DRef);
118118

119+
/*!
120+
* @brief Gives the index of the given device in the vector returned get_devices
121+
* for the platform associated with DRef for the device type of DRef.
122+
*
123+
* @param DRef A #DPCTLSyclDeviceRef opaque pointer.
124+
* @ingroup DeviceManager
125+
*/
126+
DPCTL_API
127+
int64_t
128+
DPCTLDeviceMgr_GetRelativeId(__dpctl_keep const DPCTLSyclDeviceRef DRef);
129+
119130
DPCTL_C_EXTERN_C_END

dpctl-capi/source/dpctl_sycl_device_interface.cpp

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -549,6 +549,27 @@ uint32_t DPCTLDevice_GetPreferredVectorWidthHalf(
549549
return vector_width_half;
550550
}
551551

552+
__dpctl_give DPCTLSyclDeviceRef
553+
DPCTLDevice_GetParentDevice(__dpctl_keep const DPCTLSyclDeviceRef DRef)
554+
{
555+
auto D = unwrap(DRef);
556+
if (D) {
557+
try {
558+
auto parent_D = D->get_info<info::device::parent_device>();
559+
return wrap(new device(parent_D));
560+
} catch (invalid_object_error const &ioe) {
561+
// not a sub device
562+
return nullptr;
563+
} catch (runtime_error const &re) {
564+
// \todo log error
565+
std::cerr << re.what() << '\n';
566+
return nullptr;
567+
}
568+
}
569+
else
570+
return nullptr;
571+
}
572+
552573
__dpctl_give DPCTLDeviceVectorRef
553574
DPCTLDevice_CreateSubDevicesEqually(__dpctl_keep const DPCTLSyclDeviceRef DRef,
554575
size_t count)

dpctl-capi/source/dpctl_sycl_device_manager.cpp

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -194,3 +194,22 @@ void DPCTLDeviceMgr_PrintDeviceInfo(__dpctl_keep const DPCTLSyclDeviceRef DRef)
194194
std::cout << "Device is not valid (NULL). Cannot print device info.\n";
195195
}
196196
}
197+
198+
int64_t DPCTLDeviceMgr_GetRelativeId(__dpctl_keep const DPCTLSyclDeviceRef DRef)
199+
{
200+
auto Device = unwrap(DRef);
201+
202+
if (Device) {
203+
auto p = Device->get_platform();
204+
auto dt = Device->get_info<sycl::info::device::device_type>();
205+
auto dev_vec = p.get_devices(dt);
206+
int64_t id = 0;
207+
for (auto &d_i : dev_vec) {
208+
if (*Device == d_i)
209+
return id;
210+
++id;
211+
}
212+
return -1;
213+
}
214+
return -1;
215+
}

dpctl-capi/tests/test_sycl_device_interface.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -330,6 +330,13 @@ TEST_P(TestDPCTLSyclDeviceInterface, Chk_GetImage3dMaxDepth)
330330
EXPECT_TRUE(image_3d_max_depth >= min_val);
331331
}
332332

333+
TEST_P(TestDPCTLSyclDeviceInterface, Chk_GetParentDevice)
334+
{
335+
DPCTLSyclDeviceRef pDRef = nullptr;
336+
EXPECT_NO_FATAL_FAILURE(pDRef = DPCTLDevice_GetParentDevice(DRef));
337+
EXPECT_TRUE(pDRef == nullptr);
338+
}
339+
333340
INSTANTIATE_TEST_SUITE_P(DPCTLDevice_Fns,
334341
TestDPCTLSyclDeviceInterface,
335342
::testing::Values("opencl",

dpctl-capi/tests/test_sycl_device_manager.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,13 @@ struct TestDPCTLDeviceManager : public ::testing::TestWithParam<const char *>
5656
}
5757
};
5858

59+
TEST_P(TestDPCTLDeviceManager, Chk_GetRelativeId)
60+
{
61+
int64_t rel_id = -1;
62+
EXPECT_NO_FATAL_FAILURE(rel_id = DPCTLDeviceMgr_GetRelativeId(DRef));
63+
EXPECT_FALSE(rel_id == -1);
64+
}
65+
5966
TEST_P(TestDPCTLDeviceManager, Chk_PrintDeviceInfo)
6067
{
6168
EXPECT_NO_FATAL_FAILURE(DPCTLDeviceMgr_PrintDeviceInfo(DRef));

dpctl-capi/tests/test_sycl_device_subdevices.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,14 @@ TEST_P(TestDPCTLSyclDeviceInterface, Chk_CreateSubDevicesEqually)
8181
EXPECT_NO_FATAL_FAILURE(
8282
DVRef = DPCTLDevice_CreateSubDevicesEqually(DRef, count));
8383
if (DVRef) {
84+
DPCTLSyclDeviceRef pDRef = nullptr;
85+
DPCTLSyclDeviceRef sDRef = nullptr;
8486
EXPECT_TRUE(DPCTLDeviceVector_Size(DVRef) > 0);
87+
EXPECT_NO_FATAL_FAILURE(sDRef = DPCTLDeviceVector_GetAt(DVRef, 0));
88+
EXPECT_NO_FATAL_FAILURE(pDRef = DPCTLDevice_GetParentDevice(sDRef));
89+
EXPECT_NO_FATAL_FAILURE(DPCTLDevice_Delete(sDRef));
90+
EXPECT_TRUE(DPCTLDevice_AreEq(DRef, pDRef));
91+
EXPECT_NO_FATAL_FAILURE(DPCTLDevice_Delete(pDRef));
8592
EXPECT_NO_FATAL_FAILURE(DPCTLDeviceVector_Delete(DVRef));
8693
}
8794
}

dpctl/_backend.pxd

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ types defined by dpctl's C API.
2222
"""
2323

2424
from libcpp cimport bool
25-
from libc.stdint cimport uint32_t
25+
from libc.stdint cimport uint32_t, int64_t
2626

2727

2828
cdef extern from "dpctl_error_handler_type.h":
@@ -192,6 +192,7 @@ cdef extern from "dpctl_sycl_device_interface.h":
192192
cdef DPCTLDeviceVectorRef DPCTLDevice_CreateSubDevicesByAffinity(
193193
const DPCTLSyclDeviceRef DRef,
194194
DPCTLPartitionAffinityDomainType PartitionAffinityDomainTy)
195+
cdef DPCTLSyclDeviceRef DPCTLDevice_GetParentDevice(const DPCTLSyclDeviceRef DRef)
195196

196197

197198
cdef extern from "dpctl_sycl_device_manager.h":
@@ -209,6 +210,7 @@ cdef extern from "dpctl_sycl_device_manager.h":
209210
cdef void DPCTLDeviceMgr_PrintDeviceInfo(const DPCTLSyclDeviceRef DRef)
210211
cdef DPCTLSyclContextRef DPCTLDeviceMgr_GetCachedContext(
211212
const DPCTLSyclDeviceRef DRef)
213+
cdef int64_t DPCTLDeviceMgr_GetRelativeId(const DPCTLSyclDeviceRef DRef)
212214

213215

214216
cdef extern from "dpctl_sycl_device_selector_interface.h":

dpctl/_sycl_device.pxd

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,10 +25,11 @@ from ._backend cimport (
2525
DPCTLSyclDeviceSelectorRef,
2626
_partition_affinity_domain_type
2727
)
28+
from libcpp cimport bool as cpp_bool
2829

2930

3031
cdef class _SyclDevice:
31-
''' Wrapper class for a Sycl Device
32+
''' Wrapper data owner class for a Sycl Device
3233
'''
3334
cdef DPCTLSyclDeviceRef _device_ref
3435
cdef const char *_vendor_name
@@ -48,3 +49,4 @@ cdef class SyclDevice(_SyclDevice):
4849
cdef list create_sub_devices_equally(self, size_t count)
4950
cdef list create_sub_devices_by_counts(self, object counts)
5051
cdef list create_sub_devices_by_affinity(self, _partition_affinity_domain_type domain)
52+
cpdef cpp_bool equals(self, SyclDevice q)

dpctl/_sycl_device.pyx

Lines changed: 79 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ from ._backend cimport (
3434
DPCTLDeviceVector_Delete,
3535
DPCTLDeviceVector_GetAt,
3636
DPCTLDeviceVector_Size,
37+
DPCTLDevice_AreEq,
3738
DPCTLDevice_GetBackend,
3839
DPCTLDevice_GetDeviceType,
3940
DPCTLDevice_GetDriverInfo,
@@ -49,6 +50,7 @@ from ._backend cimport (
4950
DPCTLDevice_IsGPU,
5051
DPCTLDevice_IsHost,
5152
DPCTLDeviceMgr_PrintDeviceInfo,
53+
DPCTLDeviceMgr_GetRelativeId,
5254
DPCTLFilterSelector_Create,
5355
DPCTLDeviceSelector_Delete,
5456
DPCTLDeviceSelector_Score,
@@ -74,9 +76,10 @@ from ._backend cimport (
7476
DPCTLDevice_CreateSubDevicesEqually,
7577
DPCTLDevice_CreateSubDevicesByCounts,
7678
DPCTLDevice_CreateSubDevicesByAffinity,
79+
DPCTLDevice_GetParentDevice,
7780
)
7881
from . import backend_type, device_type
79-
from libc.stdint cimport uint32_t
82+
from libc.stdint cimport uint32_t, int64_t
8083
from libc.stdlib cimport malloc, free
8184
import warnings
8285
import collections
@@ -96,7 +99,7 @@ cdef class SubDeviceCreationError(Exception):
9699

97100

98101
cdef class _SyclDevice:
99-
""" A helper metaclass to abstract a cl::sycl::device instance.
102+
""" A helper data-owner class to abstract a cl::sycl::device instance.
100103
"""
101104

102105
def __dealloc__(self):
@@ -124,6 +127,34 @@ cdef list _get_devices(DPCTLDeviceVectorRef DVRef):
124127
return devices
125128

126129

130+
cdef str _backend_type_to_filter_string_part(DPCTLSyclBackendType BTy):
131+
if BTy == _backend_type._CUDA:
132+
return "cuda"
133+
elif BTy == _backend_type._HOST:
134+
return "host"
135+
elif BTy == _backend_type._LEVEL_ZERO:
136+
return "level_zero"
137+
elif BTy == _backend_type._OPENCL:
138+
return "opencl"
139+
else:
140+
return "unknown"
141+
142+
143+
cdef str _device_type_to_filter_string_part(DPCTLSyclDeviceType DTy):
144+
if DTy == _device_type._ACCELERATOR:
145+
return "accelerator"
146+
elif DTy == _device_type._AUTOMATIC:
147+
return "automatic"
148+
elif DTy == _device_type._CPU:
149+
return "cpu"
150+
elif DTy == _device_type._GPU:
151+
return "gpu"
152+
elif DTy == _device_type._HOST_DEVICE:
153+
return "host"
154+
else:
155+
return "unknown"
156+
157+
127158
cdef class SyclDevice(_SyclDevice):
128159
""" Python equivalent for cl::sycl::device class.
129160
@@ -714,3 +745,49 @@ cdef class SyclDevice(_SyclDevice):
714745
return self.create_sub_devices_equally(partition)
715746
except Exception as e:
716747
raise TypeError("Unsupported type of sub-device argument")
748+
749+
@property
750+
def parent_device(self):
751+
""" Parent device for a sub-device, or None for a root device.
752+
"""
753+
cdef DPCTLSyclDeviceRef pDRef = NULL
754+
pDRef = DPCTLDevice_GetParentDevice(self._device_ref)
755+
if (pDRef is NULL):
756+
return None
757+
return SyclDevice._create(pDRef)
758+
759+
cpdef cpp_bool equals(self, SyclDevice other):
760+
""" Returns true if the SyclDevice argument has the same _device_ref
761+
as this SyclDevice.
762+
"""
763+
return DPCTLDevice_AreEq(self._device_ref, other.get_device_ref())
764+
765+
def __eq__(self, other):
766+
if isinstance(other, SyclDevice):
767+
return self.equals(<SyclDevice> other)
768+
else:
769+
return False
770+
771+
@property
772+
def filter_string(self):
773+
""" For a parent device returns a tuple (backend, device_kind, relative_id).
774+
Raises an exception for sub-devices.
775+
"""
776+
cdef DPCTLSyclDeviceRef pDRef = NULL
777+
cdef DPCTLSyclBackendType BTy
778+
cdef DPCTLSyclDeviceType DTy
779+
cdef int64_t relId = -1
780+
pDRef = DPCTLDevice_GetParentDevice(self._device_ref)
781+
if (pDRef is NULL):
782+
BTy = DPCTLDevice_GetBackend(self._device_ref)
783+
DTy = DPCTLDevice_GetDeviceType(self._device_ref)
784+
relId = DPCTLDeviceMgr_GetRelativeId(self._device_ref)
785+
if (relId == -1):
786+
raise TypeError("This SyclDevice is not a root device")
787+
br_str = _backend_type_to_filter_string_part(BTy)
788+
dt_str = _device_type_to_filter_string_part(DTy)
789+
return ":".join((br_str, dt_str, str(relId)))
790+
else:
791+
# this a sub-device, free it, and raise an exception
792+
DPCTLDevice_Delete(pDRef)
793+
raise TypeError("This SyclDevice is not a root device")

0 commit comments

Comments
 (0)