Skip to content

Commit 07eaae3

Browse files
etotmenioleksandr-pavlyk
authored andcommitted
dpctl/ Python API change to add support for subdevices from #326
1 parent 943300a commit 07eaae3

File tree

4 files changed

+234
-2
lines changed

4 files changed

+234
-2
lines changed

dpctl/_backend.pxd

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,18 @@ cdef extern from "dpctl_sycl_enum_types.h":
104104
ctypedef _aspect_type DPCTLSyclAspectType
105105

106106

107+
cdef enum _partition_affinity_domain_type 'DPCTLPartitionAffinityDomainType':
108+
_not_applicable 'not_applicable',
109+
_numa 'numa',
110+
_L4_cache 'L4_cache',
111+
_L3_cache 'L3_cache',
112+
_L2_cache 'L2_cache',
113+
_L1_cache 'L1_cache',
114+
_next_partitionable 'next_partitionable',
115+
116+
ctypedef _partition_affinity_domain_type DPCTLPartitionAffinityDomainType
117+
118+
107119
cdef extern from "dpctl_sycl_types.h":
108120
cdef struct DPCTLOpaqueSyclContext
109121
cdef struct DPCTLOpaqueSyclDevice
@@ -126,6 +138,11 @@ cdef extern from "dpctl_sycl_types.h":
126138
ctypedef DPCTLOpaqueSyclUSM *DPCTLSyclUSMRef
127139

128140

141+
cdef extern from "dpctl_sycl_device_manager.h":
142+
cdef struct DPCTLDeviceVector
143+
ctypedef DPCTLDeviceVector *DPCTLDeviceVectorRef
144+
145+
129146
cdef extern from "dpctl_sycl_device_interface.h":
130147
cdef bool DPCTLDevice_AreEq(const DPCTLSyclDeviceRef DRef1,
131148
const DPCTLSyclDeviceRef DRef2)
@@ -163,11 +180,16 @@ cdef extern from "dpctl_sycl_device_interface.h":
163180
cdef uint32_t DPCTLDevice_GetPreferredVectorWidthHalf(const DPCTLSyclDeviceRef DRef)
164181
cpdef bool DPCTLDevice_HasAspect(
165182
const DPCTLSyclDeviceRef DRef, DPCTLSyclAspectType AT)
183+
cdef DPCTLDeviceVectorRef DPCTLDevice_CreateSubDevicesEqually(
184+
const DPCTLSyclDeviceRef DRef, size_t count)
185+
cdef DPCTLDeviceVectorRef DPCTLDevice_CreateSubDevicesByCounts(
186+
const DPCTLSyclDeviceRef DRef, size_t *counts, size_t ncounts)
187+
cdef DPCTLDeviceVectorRef DPCTLDevice_CreateSubDevicesByAffinity(
188+
const DPCTLSyclDeviceRef DRef,
189+
DPCTLPartitionAffinityDomainType PartitionAffinityDomainTy)
166190

167191

168192
cdef extern from "dpctl_sycl_device_manager.h":
169-
cdef struct DPCTLDeviceVector
170-
ctypedef DPCTLDeviceVector *DPCTLDeviceVectorRef
171193
cdef DPCTLDeviceVectorRef DPCTLDeviceVector_CreateFromArray(
172194
size_t nelems,
173195
DPCTLSyclDeviceRef *elems)

dpctl/_sycl_device.pxd

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
from ._backend cimport (
2424
DPCTLSyclDeviceRef,
2525
DPCTLSyclDeviceSelectorRef,
26+
_partition_affinity_domain_type
2627
)
2728

2829

@@ -44,3 +45,7 @@ cdef class SyclDevice(_SyclDevice):
4445
cdef int _init_from__SyclDevice(self, _SyclDevice other)
4546
cdef int _init_from_selector(self, DPCTLSyclDeviceSelectorRef DSRef)
4647
cdef DPCTLSyclDeviceRef get_device_ref(self)
48+
cdef _raise_sub_devices_creation_error(self, fname, errcode)
49+
cdef list create_sub_devices_equally(self, size_t count)
50+
cdef list create_sub_devices_by_counts(self, list counts)
51+
cdef list create_sub_devices_by_affinity(self, _partition_affinity_domain_type domain)

dpctl/_sycl_device.pyx

Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,11 +24,16 @@ from ._backend cimport (
2424
_aspect_type,
2525
_backend_type,
2626
_device_type,
27+
_partition_affinity_domain_type,
2728
DPCTLCString_Delete,
2829
DPCTLDefaultSelector_Create,
2930
DPCTLDevice_Copy,
3031
DPCTLDevice_CreateFromSelector,
3132
DPCTLDevice_Delete,
33+
DPCTLDeviceVectorRef,
34+
DPCTLDeviceVector_Delete,
35+
DPCTLDeviceVector_GetAt,
36+
DPCTLDeviceVector_Size,
3237
DPCTLDevice_GetBackend,
3338
DPCTLDevice_GetDeviceType,
3439
DPCTLDevice_GetDriverInfo,
@@ -61,16 +66,29 @@ from ._backend cimport (
6166
DPCTLDevice_GetPreferredVectorWidthFloat,
6267
DPCTLDevice_GetPreferredVectorWidthDouble,
6368
DPCTLDevice_GetPreferredVectorWidthHalf,
69+
DPCTLDevice_CreateSubDevicesEqually,
70+
DPCTLDevice_CreateSubDevicesByCounts,
71+
DPCTLDevice_CreateSubDevicesByAffinity,
6472
)
6573
from . import backend_type, device_type
6674
from libc.stdint cimport uint32_t
6775
import warnings
76+
from libc.stdlib cimport malloc, free
6877

6978
__all__ = [
7079
"SyclDevice",
7180
]
7281

7382

83+
cdef class SubDeviceCreationError(Exception):
84+
"""
85+
A SubDeviceCreationError exception is raised when
86+
sub-devices were not created.
87+
88+
"""
89+
pass
90+
91+
7492
cdef class _SyclDevice:
7593
""" A helper metaclass to abstract a cl::sycl::device instance.
7694
"""
@@ -83,6 +101,19 @@ cdef class _SyclDevice:
83101
DPCTLSize_t_Array_Delete(self._max_work_item_sizes)
84102

85103

104+
cdef list _get_devices(DPCTLDeviceVectorRef DVRef):
105+
cdef list devices = []
106+
cdef size_t nelems = 0
107+
if DVRef:
108+
nelems = DPCTLDeviceVector_Size(DVRef)
109+
for i in range(0, nelems):
110+
DRef = DPCTLDeviceVector_GetAt(DVRef, i)
111+
D = SyclDevice._create(DRef)
112+
devices.append(D)
113+
114+
return devices
115+
116+
86117
cdef class SyclDevice(_SyclDevice):
87118
""" Python equivalent for cl::sycl::device class.
88119
@@ -167,6 +198,87 @@ cdef class SyclDevice(_SyclDevice):
167198
SyclDevice._init_helper(self, DRef)
168199
return 0
169200

201+
cdef _raise_sub_devices_creation_error(self, fname, errcode):
202+
e = SubDeviceCreationError("Sub-devices were not created.")
203+
e.fname = fname
204+
e.code = errcode
205+
raise e
206+
207+
cdef list create_sub_devices_equally(self, size_t count):
208+
""" Returns a vector of sub devices partitioned from this SYCL device
209+
based on the count parameter. The returned
210+
vector contains as many sub devices as can be created such that each sub
211+
device contains count compute units. If the device’s total number of compute
212+
units is not evenly divided by count, then the remaining compute units are
213+
not included in any of the sub devices.
214+
"""
215+
cdef DPCTLDeviceVectorRef DVRef = NULL
216+
DVRef = DPCTLDevice_CreateSubDevicesEqually(self._device_ref, count)
217+
if DVRef is NULL:
218+
self._raise_sub_devices_creation_error("DPCTLSubDeviceCreationError", -1)
219+
cdef list devices = _get_devices(DVRef)
220+
DPCTLDeviceVector_Delete(DVRef)
221+
return devices
222+
223+
cdef list create_sub_devices_by_counts(self, list counts):
224+
""" Returns a vector of sub devices
225+
partitioned from this SYCL device based on the counts parameter. For each
226+
non-zero value M in the counts vector, a sub device with M compute units
227+
is created.
228+
"""
229+
cdef size_t ncounts = len(counts)
230+
cdef size_t *counts_buff = <size_t *> malloc(ncounts * sizeof(size_t))
231+
cdef DPCTLDeviceVectorRef DVRef = NULL
232+
cdef int i
233+
for i in range(ncounts):
234+
counts_buff[i] = counts[i]
235+
DVRef = DPCTLDevice_CreateSubDevicesByCounts(self._device_ref, counts_buff, ncounts)
236+
if DVRef is NULL:
237+
self._raise_sub_devices_creation_error("DPCTLSubDeviceCreationError", -1)
238+
cdef list devices = _get_devices(DVRef)
239+
free(counts_buff)
240+
DPCTLDeviceVector_Delete(DVRef)
241+
return devices
242+
243+
cdef list create_sub_devices_by_affinity(self, _partition_affinity_domain_type domain):
244+
""" Returns a vector of sub devices
245+
partitioned from this SYCL device by affinity domain based on the domain
246+
parameter.
247+
"""
248+
cdef DPCTLDeviceVectorRef DVRef = NULL
249+
DVRef = DPCTLDevice_CreateSubDevicesByAffinity(self._device_ref, domain)
250+
if DVRef is NULL:
251+
self._raise_sub_devices_creation_error("DPCTLSubDeviceCreationError", -1)
252+
cdef list devices = _get_devices(DVRef)
253+
DPCTLDeviceVector_Delete(DVRef)
254+
return devices
255+
256+
def create_sub_devices(self, partition):
257+
if isinstance(partition, int) and partition > 0:
258+
return self.create_sub_devices_equally(partition)
259+
elif isinstance(partition, list) and all([i > 0 for i in partition]):
260+
return self.create_sub_devices_by_counts(partition)
261+
elif isinstance(partition, str):
262+
if partition == "not_applicable":
263+
domain_type = _partition_affinity_domain_type._not_applicable
264+
elif partition == "numa":
265+
domain_type = _partition_affinity_domain_type._numa
266+
elif partition == "L4_cache":
267+
domain_type = _partition_affinity_domain_type._L4_cache
268+
elif partition == "L3_cache":
269+
domain_type = _partition_affinity_domain_type._L3_cache
270+
elif partition == "L2_cache":
271+
domain_type = _partition_affinity_domain_type._L2_cache
272+
elif partition == "L1_cache":
273+
domain_type = _partition_affinity_domain_type._L1_cache
274+
elif partition == "next_partitionable":
275+
domain_type = _partition_affinity_domain_type._next_partitionable
276+
else:
277+
raise Exception('Unsupported type of domain')
278+
return self.create_sub_devices_by_affinity(domain_type)
279+
else:
280+
raise Exception('Unsupported type of sub-device argument')
281+
170282
def __cinit__(self, arg=None):
171283
cdef DPCTLSyclDeviceSelectorRef DSRef = NULL
172284
cdef const char *filter_c_str = NULL

dpctl/tests/test_sycl_device.py

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919

2020
import dpctl
2121
import pytest
22+
from dpctl._sycl_device import SubDeviceCreationError
2223

2324
list_of_standard_selectors = [
2425
dpctl.select_accelerator_device,
@@ -296,6 +297,89 @@ def check_get_preferred_vector_width_half(device):
296297
pytest.fail("preferred_vector_width_half call failed")
297298

298299

300+
def check_create_sub_devices_equally(device):
301+
try:
302+
n = int(device.max_compute_units / 2)
303+
device.create_sub_devices(n)
304+
except SubDeviceCreationError:
305+
pytest.skip("create_sub_devices can't create sub-devices on this device")
306+
except Exception:
307+
pytest.fail("create_sub_devices failed")
308+
309+
310+
def check_create_sub_devices_by_counts(device):
311+
try:
312+
n = device.max_compute_units / 2
313+
device.create_sub_devices([n, n])
314+
except SubDeviceCreationError:
315+
pytest.skip("create_sub_devices can't create sub-devices on this device")
316+
except Exception:
317+
pytest.fail("create_sub_devices failed")
318+
319+
320+
def check_create_sub_devices_by_affinity_not_applicable(device):
321+
try:
322+
device.create_sub_devices("not_applicable")
323+
except SubDeviceCreationError:
324+
pytest.skip("create_sub_devices can't create sub-devices on this device")
325+
except Exception:
326+
pytest.fail("create_sub_devices failed")
327+
328+
329+
def check_create_sub_devices_by_affinity_numa(device):
330+
try:
331+
device.create_sub_devices("numa")
332+
except SubDeviceCreationError:
333+
pytest.skip("create_sub_devices can't create sub-devices on this device")
334+
except Exception:
335+
pytest.fail("create_sub_devices failed")
336+
337+
338+
def check_create_sub_devices_by_affinity_L4_cache(device):
339+
try:
340+
device.create_sub_devices("L4_cache")
341+
except SubDeviceCreationError:
342+
pytest.skip("create_sub_devices can't create sub-devices on this device")
343+
except Exception:
344+
pytest.fail("create_sub_devices failed")
345+
346+
347+
def check_create_sub_devices_by_affinity_L3_cache(device):
348+
try:
349+
device.create_sub_devices("L3_cache")
350+
except SubDeviceCreationError:
351+
pytest.skip("create_sub_devices can't create sub-devices on this device")
352+
except Exception:
353+
pytest.fail("create_sub_devices failed")
354+
355+
356+
def check_create_sub_devices_by_affinity_L2_cache(device):
357+
try:
358+
device.create_sub_devices("L2_cache")
359+
except SubDeviceCreationError:
360+
pytest.skip("create_sub_devices can't create sub-devices on this device")
361+
except Exception:
362+
pytest.fail("create_sub_devices failed")
363+
364+
365+
def check_create_sub_devices_by_affinity_L1_cache(device):
366+
try:
367+
device.create_sub_devices("L1_cache")
368+
except SubDeviceCreationError:
369+
pytest.skip("create_sub_devices can't create sub-devices on this device")
370+
except Exception:
371+
pytest.fail("create_sub_devices failed")
372+
373+
374+
def check_create_sub_devices_by_affinity_next_partitionable(device):
375+
try:
376+
device.create_sub_devices("next_partitionable")
377+
except SubDeviceCreationError:
378+
pytest.skip("create_sub_devices can't create sub-devices on this device")
379+
except Exception:
380+
pytest.fail("create_sub_devices failed")
381+
382+
299383
def check_print_device_info(device):
300384
try:
301385
device.print_device_info()
@@ -339,6 +423,15 @@ def check_print_device_info(device):
339423
check_has_aspect_usm_shared_allocations,
340424
check_has_aspect_usm_restricted_shared_allocations,
341425
check_has_aspect_usm_system_allocator,
426+
check_create_sub_devices_equally,
427+
check_create_sub_devices_by_counts,
428+
check_create_sub_devices_by_affinity_not_applicable,
429+
check_create_sub_devices_by_affinity_numa,
430+
check_create_sub_devices_by_affinity_L4_cache,
431+
check_create_sub_devices_by_affinity_L3_cache,
432+
check_create_sub_devices_by_affinity_L2_cache,
433+
check_create_sub_devices_by_affinity_L1_cache,
434+
check_create_sub_devices_by_affinity_next_partitionable,
342435
check_print_device_info,
343436
]
344437

0 commit comments

Comments
 (0)