Skip to content

Commit 8481251

Browse files
create_sub_device review changes
1. Moved code for sub-devices to the end of class definition It was placed in the middle of initialization code block, separating `__cinit__` from `_init_*` routines it uses. 2. create_sub_devices requires use of keyword argument parition. Usage is d.create_sub_devices(partition=4) 3. Plugged possible memory leak in create_sub_devices_by_counts which memory allocated for array would not be freed if sub-devices vector was returned NULL 4. Changed signature of create_sub_device_by_counts from accepting object of type list, to accepting any object, which is checked to be Sized (len(obj) is expected to work), and Iterable, i.s. iteration of elements works 5. Changes to accept all integral types, such as np.int32, not just python int. 6. Got rid of _raise_create_sub_devices_exception function, and replaced it with explicit raise CreateSubDevicesError(message) 7. updated tests to use partition= keyword
1 parent 07eaae3 commit 8481251

File tree

3 files changed

+101
-93
lines changed

3 files changed

+101
-93
lines changed

dpctl/_sycl_device.pxd

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,6 @@ cdef class SyclDevice(_SyclDevice):
4545
cdef int _init_from__SyclDevice(self, _SyclDevice other)
4646
cdef int _init_from_selector(self, DPCTLSyclDeviceSelectorRef DSRef)
4747
cdef DPCTLSyclDeviceRef get_device_ref(self)
48-
cdef _raise_sub_devices_creation_error(self, fname, errcode)
4948
cdef list create_sub_devices_equally(self, size_t count)
50-
cdef list create_sub_devices_by_counts(self, list counts)
49+
cdef list create_sub_devices_by_counts(self, object counts)
5150
cdef list create_sub_devices_by_affinity(self, _partition_affinity_domain_type domain)

dpctl/_sycl_device.pyx

Lines changed: 91 additions & 82 deletions
Original file line numberDiff line numberDiff line change
@@ -72,8 +72,9 @@ from ._backend cimport (
7272
)
7373
from . import backend_type, device_type
7474
from libc.stdint cimport uint32_t
75-
import warnings
7675
from libc.stdlib cimport malloc, free
76+
import warnings
77+
import collections
7778

7879
__all__ = [
7980
"SyclDevice",
@@ -102,6 +103,9 @@ cdef class _SyclDevice:
102103

103104

104105
cdef list _get_devices(DPCTLDeviceVectorRef DVRef):
106+
"""
107+
Deletes DVRef. Pass a copy in case an original reference is needed.
108+
"""
105109
cdef list devices = []
106110
cdef size_t nelems = 0
107111
if DVRef:
@@ -110,6 +114,7 @@ cdef list _get_devices(DPCTLDeviceVectorRef DVRef):
110114
DRef = DPCTLDeviceVector_GetAt(DVRef, i)
111115
D = SyclDevice._create(DRef)
112116
devices.append(D)
117+
DPCTLDeviceVector_Delete(DVRef)
113118

114119
return devices
115120

@@ -198,87 +203,6 @@ cdef class SyclDevice(_SyclDevice):
198203
SyclDevice._init_helper(self, DRef)
199204
return 0
200205

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-
282206
def __cinit__(self, arg=None):
283207
cdef DPCTLSyclDeviceSelectorRef DSRef = NULL
284208
cdef const char *filter_c_str = NULL
@@ -665,3 +589,88 @@ cdef class SyclDevice(_SyclDevice):
665589
return ("<dpctl." + self.__name__ + " [" +
666590
str(self.backend) + ", " + str(self.device_type) +", " +
667591
" " + self.device_name + "] at {}>".format(hex(id(self))) )
592+
593+
cdef list create_sub_devices_equally(self, size_t count):
594+
""" Returns a vector of sub devices partitioned from this SYCL device
595+
based on the count parameter. The returned
596+
vector contains as many sub devices as can be created such that each sub
597+
device contains count compute units. If the device’s total number of compute
598+
units is not evenly divided by count, then the remaining compute units are
599+
not included in any of the sub devices.
600+
"""
601+
cdef DPCTLDeviceVectorRef DVRef = NULL
602+
DVRef = DPCTLDevice_CreateSubDevicesEqually(self._device_ref, count)
603+
if DVRef is NULL:
604+
raise SubDeviceCreationError("Sub-devices were not created.")
605+
return _get_devices(DVRef)
606+
607+
cdef list create_sub_devices_by_counts(self, object counts):
608+
""" Returns a vector of sub devices
609+
partitioned from this SYCL device based on the counts parameter. For each
610+
non-zero value M in the counts vector, a sub device with M compute units
611+
is created.
612+
"""
613+
cdef int ncounts = len(counts)
614+
cdef size_t *counts_buff = NULL
615+
cdef DPCTLDeviceVectorRef DVRef = NULL
616+
cdef int i
617+
618+
if (ncounts == 0):
619+
raise TypeError("Non-empty object representing list of counts is expected.")
620+
counts_buff = <size_t *> malloc((<size_t> ncounts) * sizeof(size_t))
621+
if (counts_buff is NULL):
622+
raise MemoryError("Allocation of counts array of size {} failed.".format(ncounts))
623+
for i in range(ncounts):
624+
counts_buff[i] = counts[i]
625+
DVRef = DPCTLDevice_CreateSubDevicesByCounts(self._device_ref, counts_buff, ncounts)
626+
free(counts_buff)
627+
if DVRef is NULL:
628+
raise SubDeviceCreationError("Sub-devices were not created.")
629+
return _get_devices(DVRef)
630+
631+
cdef list create_sub_devices_by_affinity(self, _partition_affinity_domain_type domain):
632+
""" Returns a vector of sub devices
633+
partitioned from this SYCL device by affinity domain based on the domain
634+
parameter.
635+
"""
636+
cdef DPCTLDeviceVectorRef DVRef = NULL
637+
DVRef = DPCTLDevice_CreateSubDevicesByAffinity(self._device_ref, domain)
638+
if DVRef is NULL:
639+
raise SubDeviceCreationError("Sub-devices were not created.")
640+
return _get_devices(DVRef)
641+
642+
def create_sub_devices(self, **kwargs):
643+
if not kwargs.has_key('partition'):
644+
raise TypeError("create_sub_devices(partition=parition_spec) is expected.")
645+
partition = kwargs.pop('partition')
646+
if (kwargs):
647+
raise TypeError("create_sub_devices(partition=parition_spec) is expected.")
648+
if isinstance(partition, int) and partition > 0:
649+
return self.create_sub_devices_equally(partition)
650+
elif isinstance(partition, str):
651+
if partition == "not_applicable":
652+
domain_type = _partition_affinity_domain_type._not_applicable
653+
elif partition == "numa":
654+
domain_type = _partition_affinity_domain_type._numa
655+
elif partition == "L4_cache":
656+
domain_type = _partition_affinity_domain_type._L4_cache
657+
elif partition == "L3_cache":
658+
domain_type = _partition_affinity_domain_type._L3_cache
659+
elif partition == "L2_cache":
660+
domain_type = _partition_affinity_domain_type._L2_cache
661+
elif partition == "L1_cache":
662+
domain_type = _partition_affinity_domain_type._L1_cache
663+
elif partition == "next_partitionable":
664+
domain_type = _partition_affinity_domain_type._next_partitionable
665+
else:
666+
raise TypeError("Partition affinity domain {} is not understood.".format(partition))
667+
return self.create_sub_devices_by_affinity(domain_type)
668+
elif (isinstance(partition, collections.abc.Sized) and
669+
isinstance(partition, collections.abc.Iterable)):
670+
return self.create_sub_devices_by_counts(partition)
671+
else:
672+
try:
673+
partition = int(partition)
674+
return self.create_sub_devices_equally(partition)
675+
except Exception as e:
676+
raise TypeError("Unsupported type of sub-device argument")

dpctl/tests/test_sycl_device.py

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -300,7 +300,7 @@ def check_get_preferred_vector_width_half(device):
300300
def check_create_sub_devices_equally(device):
301301
try:
302302
n = int(device.max_compute_units / 2)
303-
device.create_sub_devices(n)
303+
device.create_sub_devices(partition=n)
304304
except SubDeviceCreationError:
305305
pytest.skip("create_sub_devices can't create sub-devices on this device")
306306
except Exception:
@@ -310,7 +310,7 @@ def check_create_sub_devices_equally(device):
310310
def check_create_sub_devices_by_counts(device):
311311
try:
312312
n = device.max_compute_units / 2
313-
device.create_sub_devices([n, n])
313+
device.create_sub_devices(partition=(n, n))
314314
except SubDeviceCreationError:
315315
pytest.skip("create_sub_devices can't create sub-devices on this device")
316316
except Exception:
@@ -319,7 +319,7 @@ def check_create_sub_devices_by_counts(device):
319319

320320
def check_create_sub_devices_by_affinity_not_applicable(device):
321321
try:
322-
device.create_sub_devices("not_applicable")
322+
device.create_sub_devices(partition="not_applicable")
323323
except SubDeviceCreationError:
324324
pytest.skip("create_sub_devices can't create sub-devices on this device")
325325
except Exception:
@@ -328,7 +328,7 @@ def check_create_sub_devices_by_affinity_not_applicable(device):
328328

329329
def check_create_sub_devices_by_affinity_numa(device):
330330
try:
331-
device.create_sub_devices("numa")
331+
device.create_sub_devices(partition="numa")
332332
except SubDeviceCreationError:
333333
pytest.skip("create_sub_devices can't create sub-devices on this device")
334334
except Exception:
@@ -337,7 +337,7 @@ def check_create_sub_devices_by_affinity_numa(device):
337337

338338
def check_create_sub_devices_by_affinity_L4_cache(device):
339339
try:
340-
device.create_sub_devices("L4_cache")
340+
device.create_sub_devices(partition="L4_cache")
341341
except SubDeviceCreationError:
342342
pytest.skip("create_sub_devices can't create sub-devices on this device")
343343
except Exception:
@@ -346,7 +346,7 @@ def check_create_sub_devices_by_affinity_L4_cache(device):
346346

347347
def check_create_sub_devices_by_affinity_L3_cache(device):
348348
try:
349-
device.create_sub_devices("L3_cache")
349+
device.create_sub_devices(partition="L3_cache")
350350
except SubDeviceCreationError:
351351
pytest.skip("create_sub_devices can't create sub-devices on this device")
352352
except Exception:
@@ -355,7 +355,7 @@ def check_create_sub_devices_by_affinity_L3_cache(device):
355355

356356
def check_create_sub_devices_by_affinity_L2_cache(device):
357357
try:
358-
device.create_sub_devices("L2_cache")
358+
device.create_sub_devices(partition="L2_cache")
359359
except SubDeviceCreationError:
360360
pytest.skip("create_sub_devices can't create sub-devices on this device")
361361
except Exception:
@@ -364,7 +364,7 @@ def check_create_sub_devices_by_affinity_L2_cache(device):
364364

365365
def check_create_sub_devices_by_affinity_L1_cache(device):
366366
try:
367-
device.create_sub_devices("L1_cache")
367+
device.create_sub_devices(partition="L1_cache")
368368
except SubDeviceCreationError:
369369
pytest.skip("create_sub_devices can't create sub-devices on this device")
370370
except Exception:
@@ -373,7 +373,7 @@ def check_create_sub_devices_by_affinity_L1_cache(device):
373373

374374
def check_create_sub_devices_by_affinity_next_partitionable(device):
375375
try:
376-
device.create_sub_devices("next_partitionable")
376+
device.create_sub_devices(partition="next_partitionable")
377377
except SubDeviceCreationError:
378378
pytest.skip("create_sub_devices can't create sub-devices on this device")
379379
except Exception:

0 commit comments

Comments
 (0)