@@ -24,11 +24,16 @@ from ._backend cimport (
24
24
_aspect_type,
25
25
_backend_type,
26
26
_device_type,
27
+ _partition_affinity_domain_type,
27
28
DPCTLCString_Delete,
28
29
DPCTLDefaultSelector_Create,
29
30
DPCTLDevice_Copy,
30
31
DPCTLDevice_CreateFromSelector,
31
32
DPCTLDevice_Delete,
33
+ DPCTLDeviceVectorRef,
34
+ DPCTLDeviceVector_Delete,
35
+ DPCTLDeviceVector_GetAt,
36
+ DPCTLDeviceVector_Size,
32
37
DPCTLDevice_GetBackend,
33
38
DPCTLDevice_GetDeviceType,
34
39
DPCTLDevice_GetDriverInfo,
@@ -61,16 +66,29 @@ from ._backend cimport (
61
66
DPCTLDevice_GetPreferredVectorWidthFloat,
62
67
DPCTLDevice_GetPreferredVectorWidthDouble,
63
68
DPCTLDevice_GetPreferredVectorWidthHalf,
69
+ DPCTLDevice_CreateSubDevicesEqually,
70
+ DPCTLDevice_CreateSubDevicesByCounts,
71
+ DPCTLDevice_CreateSubDevicesByAffinity,
64
72
)
65
73
from . import backend_type, device_type
66
74
from libc.stdint cimport uint32_t
67
75
import warnings
76
+ from libc.stdlib cimport malloc, free
68
77
69
78
__all__ = [
70
79
" SyclDevice" ,
71
80
]
72
81
73
82
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
+
74
92
cdef class _SyclDevice:
75
93
""" A helper metaclass to abstract a cl::sycl::device instance.
76
94
"""
@@ -83,6 +101,19 @@ cdef class _SyclDevice:
83
101
DPCTLSize_t_Array_Delete(self ._max_work_item_sizes)
84
102
85
103
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
+
86
117
cdef class SyclDevice(_SyclDevice):
87
118
""" Python equivalent for cl::sycl::device class.
88
119
@@ -167,6 +198,87 @@ cdef class SyclDevice(_SyclDevice):
167
198
SyclDevice._init_helper(self , DRef)
168
199
return 0
169
200
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
+
170
282
def __cinit__ (self , arg = None ):
171
283
cdef DPCTLSyclDeviceSelectorRef DSRef = NULL
172
284
cdef const char * filter_c_str = NULL
0 commit comments