22
22
23
23
from __future__ import print_function
24
24
import logging
25
- from ._backend cimport (
25
+ from ._backend cimport(
26
26
DPCTLSyclContextRef,
27
27
DPCTLSyclDeviceRef,
28
28
DPCTLContext_Create,
@@ -69,20 +69,93 @@ cdef class _SyclContext:
69
69
70
70
71
71
cdef class SyclContext(_SyclContext):
72
- """ Python class representing cl::sycl::context.
72
+ """
73
+ Python class representing ``cl::sycl::context``. There are multiple
74
+ ways to create a :class:`dpctl.SyclContext` object:
75
+
76
+ - Invoking the constructor with no arguments creates a context using
77
+ the default selector.
78
+
79
+ :Example:
80
+ .. code-block:: python
81
+
82
+ import dpctl
83
+
84
+ # Create a default SyclContext
85
+ ctx = dpctl.SyclContext()
86
+ print(ctx.get_devices())
87
+
88
+ - Invoking the constuctor with a specific filter string that creates a
89
+ context for the device corresponding to the filter string.
90
+
91
+ :Example:
92
+ .. code-block:: python
93
+
94
+ import dpctl
95
+
96
+ # Create a default SyclContext
97
+ ctx = dpctl.SyclContext("gpu")
98
+ d = ctx.get_devices()[0]
99
+ assert(d.is_gpu)
100
+
101
+ - Invoking the constuctor with a :class:`dpctl.SyclDevice` object
102
+ creates a context for that device.
103
+
104
+ :Example:
105
+ .. code-block:: python
106
+
107
+ import dpctl
108
+
109
+ # Create a level zero gpu device
110
+ d = dpctl.SyclDevice("level_zero:gpu")
111
+ ctx = dpctl.SyclContext(d)
112
+ d = ctx.get_devices()[0]
113
+ assert(d.is_gpu)
114
+
115
+ - Invoking the constuctor with a list of :class:`dpctl.SyclDevice`
116
+ objects creates a common context for all the devices. This
117
+ constructor call is especially useful when creation a context for
118
+ multiple sub-devices.
119
+
120
+ :Example:
121
+ .. code-block:: python
122
+
123
+ import dpctl
124
+
125
+ # Create a CPU device using the opencl driver
126
+ cpu_d = dpctl.SyclDevice("opencl:cpu")
127
+ # Partition the CPU device into sub-devices, each with two cores.
128
+ sub_devices = create_sub_devices(partition=2)
129
+ # Create a context common to all the sub-devices.
130
+ ctx = dpctl.SyclContext(sub_devices)
131
+ assert(len(ctx.get_devices) == len(sub_devices))
132
+
133
+ - Invoking the constuctor with a named ``PyCapsule`` with the name
134
+ **SyclContextRef** that carries a pointer to a ``sycl::context``
135
+ object.
136
+
137
+ Args:
138
+ arg (optional): Defaults to None.
139
+ The argument can be a :class:`dpctl.SyclDevice` instance,
140
+ a :obj:`list` of :class:`dpctl.SyclDevice` objects, or a named
141
+ ``PyCapsule`` called **SyclContextRef**.
142
+
143
+ Raises:
144
+ MemoryError: If the constructor could not allocate necessary
145
+ temporary memory.
146
+ ValueError: If the :class:`dpctl.SyclContext` object creation failed.
147
+ TypeError: If the list of :class:`dpctl.SyclDevice` objects was empty,
148
+ or the input capsule contained a null pointer or could not
149
+ be renamed.
73
150
74
- SyclContext() - create a context for a default device
75
- SyclContext(filter_selector_string) - create a context for specified device
76
- SyclContext(SyclDevice_instance) - create a context for the given device
77
- SyclContext((dev1, dev2, ...)) - create a context for given set of device instances
78
151
"""
79
-
152
+
80
153
@staticmethod
81
154
cdef void _init_helper(_SyclContext context, DPCTLSyclContextRef CRef):
82
155
context._ctxt_ref = CRef
83
-
156
+
84
157
@staticmethod
85
- cdef SyclContext _create (DPCTLSyclContextRef ctxt):
158
+ cdef SyclContext _create(DPCTLSyclContextRef ctxt):
86
159
"""
87
160
Calls DPCTLContext_Delete(ctxt).
88
161
@@ -155,15 +228,18 @@ cdef class SyclContext(_SyclContext):
155
228
156
229
cdef int _init_context_from_capsule(self , object cap):
157
230
"""
158
- For named PyCapsule with name SyclContextRef, which carries pointer to
159
- sycl::context object, interpreted as DPCTLSyclContextRef, creates corresponding
160
- SyclContext.
231
+ For named ``PyCapsule`` with name **SyclContextRef**, which carries
232
+ pointer to ``sycl::context`` object, interpreted as
233
+ ``DPCTLSyclContextRef``, creates corresponding
234
+ :class:`dpctl.SyclContext`.
161
235
"""
162
236
cdef DPCTLSyclContextRef CRef = NULL
163
237
cdef DPCTLSyclContextRef CRef_copy = NULL
164
238
cdef int ret = 0
165
239
if pycapsule.PyCapsule_IsValid(cap, " SyclContextRef" ):
166
- CRef = < DPCTLSyclContextRef> pycapsule.PyCapsule_GetPointer(cap, " SyclContextRef" )
240
+ CRef = < DPCTLSyclContextRef> pycapsule.PyCapsule_GetPointer(
241
+ cap, " SyclContextRef"
242
+ )
167
243
if (CRef is NULL ):
168
244
return - 6
169
245
ret = pycapsule.PyCapsule_SetName(cap, " used_SyclContextRef" )
@@ -188,7 +264,9 @@ cdef class SyclContext(_SyclContext):
188
264
ret = self ._init_context_from_one_device(< SyclDevice> arg, 0 )
189
265
elif pycapsule.PyCapsule_IsValid(arg, " SyclContextRef" ):
190
266
status = self ._init_context_from_capsule(arg)
191
- elif isinstance (arg, (list , tuple )) and all ([isinstance (argi, SyclDevice) for argi in arg]):
267
+ elif isinstance (
268
+ arg, (list , tuple )) and all ([isinstance (argi, SyclDevice) for argi in arg]
269
+ ):
192
270
ret = self ._init_context_from_devices(arg, 0 )
193
271
else :
194
272
dev = SyclDevice(arg)
@@ -197,41 +275,74 @@ cdef class SyclContext(_SyclContext):
197
275
if (ret == - 1 ):
198
276
raise ValueError (" Context failed to be created." )
199
277
elif (ret == - 2 ):
200
- raise TypeError (" List of devices to create context from must be non-empty." )
278
+ raise TypeError (
279
+ " List of devices to create context from must be non-empty."
280
+ )
201
281
elif (ret == - 3 ):
202
- raise MemoryError (" Could not allocate necessary temporary memory." )
282
+ raise MemoryError (
283
+ " Could not allocate necessary temporary memory."
284
+ )
203
285
elif (ret == - 4 ) or (ret == - 7 ):
204
- raise ValueError (" Internal Error: Could not create a copy of a sycl device." )
286
+ raise ValueError (
287
+ " Internal Error: Could not create a copy of a sycl device."
288
+ )
205
289
elif (ret == - 5 ):
206
- raise ValueError (" Internal Error: Creation of DeviceVector failed." )
290
+ raise ValueError (
291
+ " Internal Error: Creation of DeviceVector failed."
292
+ )
207
293
elif (ret == - 6 ):
208
- raise TypeError (" Input capsule {} contains a null pointer or could not be renamed" .format(arg))
209
- raise ValueError (" Unrecognized error code ({}) encountered." .format(ret))
294
+ raise TypeError (
295
+ " Input capsule {} contains a null pointer or could not be"
296
+ " renamed" .format(arg)
297
+ )
298
+ raise ValueError (
299
+ " Unrecognized error code ({}) encountered." .format(ret)
300
+ )
301
+
302
+ cpdef bool equals(self , SyclContext ctxt):
303
+ """
304
+ Returns true if the :class:`dpctl.SyclContext` argument has the
305
+ same underlying ``DPCTLSyclContextRef`` object as this
306
+ :class:`dpctl.SyclContext` instance.
210
307
211
- cpdef bool equals (self , SyclContext ctxt):
212
- """ Returns true if the SyclContext argument has the same _context_ref
213
- as this SyclContext.
308
+ Returns:
309
+ :obj:`bool`: ``True`` if the two :class:`dpctl.SyclContext` objects
310
+ point to the same ``DPCTLSyclContextRef`` object, otherwise
311
+ ``False``.
214
312
"""
215
313
return DPCTLContext_AreEq(self ._ctxt_ref, ctxt.get_context_ref())
216
314
217
- cdef DPCTLSyclContextRef get_context_ref (self ):
315
+ cdef DPCTLSyclContextRef get_context_ref(self ):
218
316
return self ._ctxt_ref
219
317
220
318
def addressof_ref (self ):
221
319
"""
222
- Returns the address of the DPCTLSyclContextRef pointer as a size_t.
320
+ Returns the address of the ``DPCTLSyclContextRef`` pointer as a
321
+ ``size_t``.
223
322
224
323
Returns:
225
- The address of the DPCTLSyclContextRef object used to create this
226
- SyclContext cast to a size_t.
324
+ :obj:`int`: The address of the ``DPCTLSyclContextRef`` object
325
+ used to create this :class:`dpctl.SyclContext` cast to a
326
+ ``size_t``.
227
327
"""
228
328
return int (< size_t> self ._ctx_ref)
229
329
230
- def get_devices (self ):
330
+ def get_devices (self ):
231
331
"""
232
- Returns the list of SyclDevice objects associated with SyclContext instance.
332
+ Returns the list of :class:`dpctl.SyclDevice` objects associated with
333
+ :class:`dpctl.SyclContext` instance.
334
+
335
+ Returns:
336
+ :obj:`list`: A :obj:`list` of :class:`dpctl.SyclDevice` objects
337
+ that belong to this context.
338
+
339
+ Raises:
340
+ ValueError: If the ``DPCTLContext_GetDevices`` call returned
341
+ ``NULL`` instead of a ``DPCTLDeviceVectorRef`` object.
233
342
"""
234
- cdef DPCTLDeviceVectorRef DVRef = DPCTLContext_GetDevices(self .get_context_ref())
343
+ cdef DPCTLDeviceVectorRef DVRef = DPCTLContext_GetDevices(
344
+ self .get_context_ref()
345
+ )
235
346
cdef size_t num_devs
236
347
cdef size_t i
237
348
cdef DPCTLSyclDeviceRef DRef
@@ -244,34 +355,86 @@ cdef class SyclContext(_SyclContext):
244
355
devices.append(SyclDevice._create(DRef))
245
356
DPCTLDeviceVector_Delete(DVRef)
246
357
return devices
247
-
358
+
248
359
@property
249
- def device_count (self ):
360
+ def device_count (self ):
250
361
"""
251
- The number of sycl devices associated with SyclContext instance.
362
+ The number of sycl devices associated with the
363
+ :class:`dpctl.SyclContext` instance.
364
+
365
+ Returns:
366
+ :obj:`int`: Number of devices associated with the context.
367
+
368
+ Raises:
369
+ ValueError: If ``DPCTLContext_DeviceCount`` led to a
370
+ failure.
252
371
"""
253
372
cdef size_t num_devs = DPCTLContext_DeviceCount(self .get_context_ref())
254
373
if num_devs:
255
374
return num_devs
256
375
else :
257
- raise ValueError (" An error was encountered quering the number of devices "
258
- " associated with this context" )
376
+ raise ValueError (
377
+ " An error was encountered quering the number of devices "
378
+ " associated with this context"
379
+ )
259
380
260
381
@property
261
382
def __name__ (self ):
262
383
return " SyclContext"
263
384
264
385
def __repr__ (self ):
386
+ """
387
+ Returns the name of the class and number of devices in the context.
388
+
389
+ :Example:
390
+ .. code-block:: python
391
+
392
+ import dpctl
393
+
394
+ # Create a default SyclContext
395
+ ctx = dpctl.SyclContext()
396
+ print(ctx) # E.g : <dpctl.SyclContext at 0x7f154d8ab070>
397
+
398
+ cpu_d = dpctl.SyclDevice("opencl:cpu")
399
+ sub_devices = create_sub_devices(partition=2)
400
+ ctx2 = dpctl.SyclContext(sub_devices)
401
+ print(ctx2) # E.g : <dpctl.SyclContext for 4 devices at 0x7f154d8ab070>
402
+
403
+ Returns:
404
+ :obj:`str`: A string representation of the
405
+ :class:`dpctl.SyclContext` object.
406
+
407
+ """
265
408
cdef size_t n = self .device_count
266
409
if n == 1 :
267
410
return (" <dpctl." + self .__name__ + " at {}>" .format(hex (id (self ))))
268
411
else :
269
- return (" <dpctl." + self .__name__ + " for {} devices at {}>" .format(n, hex (id (self ))))
412
+ return (" <dpctl." + self .__name__ + " for {} devices at {}>"
413
+ .format(n, hex (id (self ))))
270
414
271
415
def _get_capsule (self ):
416
+ """
417
+ Returns a copy of the underlying ``sycl::context`` pointer as a void
418
+ pointer inside a named ``PyCapsule`` that has the name
419
+ **SyclContextRef**. The ownership of the pointer inside the capsule is
420
+ passed to the caller, and pointer is deleted when the capsule goes out
421
+ of scope.
422
+
423
+ Returns:
424
+ :class:`pycapsule`: A capsule object storing a copy of the
425
+ ``sycl::context`` pointer belonging to thus
426
+ :class:`dpctl.SyclContext` instance.
427
+
428
+ Raises:
429
+ ValueError: If the ``DPCTLContext_Copy`` fails to copy the
430
+ ``sycl::context`` pointer.
431
+ """
272
432
cdef DPCTLSyclContextRef CRef = NULL
273
433
CRef = DPCTLContext_Copy(self ._ctxt_ref)
274
434
if (CRef is NULL ):
275
435
raise ValueError (" SyclContext copy failed." )
276
- return pycapsule.PyCapsule_New(< void * > CRef, " SyclContextRef" , & _context_capsule_deleter)
277
-
436
+ return pycapsule.PyCapsule_New(
437
+ < void * > CRef,
438
+ " SyclContextRef" ,
439
+ & _context_capsule_deleter
440
+ )
0 commit comments