Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 4 additions & 3 deletions dpctl/_sycl_context.pxd
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,9 @@ cdef class SyclContext(_SyclContext):
cdef SyclContext _create (DPCTLSyclContextRef CRef)
@staticmethod
cdef void _init_helper(_SyclContext self, DPCTLSyclContextRef CRef)
cdef int _init_from__SyclContext(self, _SyclContext other)
cdef int _init_from_one_device(self, SyclDevice device, int props)
cdef int _init_from_devices(self, object devices, int props)
cdef int _init_context_from__SyclContext(self, _SyclContext other)
cdef int _init_context_from_one_device(self, SyclDevice device, int props)
cdef int _init_context_from_devices(self, object devices, int props)
cdef int _init_context_from_capsule(self, object caps)
cpdef bool equals (self, SyclContext ctxt)
cdef DPCTLSyclContextRef get_context_ref (self)
69 changes: 58 additions & 11 deletions dpctl/_sycl_context.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -45,13 +45,21 @@ from ._backend cimport (
from ._sycl_queue cimport default_async_error_handler
from ._sycl_device cimport SyclDevice
from cpython.mem cimport PyMem_Malloc, PyMem_Free
from cpython cimport pycapsule

__all__ = [
"SyclContext",
]

_logger = logging.getLogger(__name__)

cdef void _context_capsule_deleter(object o):
cdef DPCTLSyclContextRef CRef = NULL
if pycapsule.PyCapsule_IsValid(o, "SyclContextRef"):
CRef = <DPCTLSyclContextRef> pycapsule.PyCapsule_GetPointer(o, "SyclContextRef")
DPCTLContext_Delete(CRef)


cdef class _SyclContext:
""" Data owner for SyclContext
"""
Expand Down Expand Up @@ -79,13 +87,13 @@ cdef class SyclContext(_SyclContext):
SyclContext._init_helper(ret, ctxt)
return SyclContext(ret)

cdef int _init_from__SyclContext(self, _SyclContext other):
cdef int _init_context_from__SyclContext(self, _SyclContext other):
self._ctxt_ref = DPCTLContext_Copy(other._ctxt_ref)
if (self._ctxt_ref is NULL):
return -1
return 0

cdef int _init_from_one_device(self, SyclDevice device, int props):
cdef int _init_context_from_one_device(self, SyclDevice device, int props):
cdef DPCTLSyclDeviceRef DRef = device.get_device_ref()
cdef DPCTLSyclContextRef CRef = NULL
cdef error_handler_callback * eh_callback = (
Expand All @@ -100,7 +108,7 @@ cdef class SyclContext(_SyclContext):
SyclContext._init_helper(<_SyclContext> self, CRef)
return 0

cdef int _init_from_devices(self, object devices, int props):
cdef int _init_context_from_devices(self, object devices, int props):
cdef int num_devices = len(devices)
cdef int i = 0
cdef int j = 0
Expand Down Expand Up @@ -140,6 +148,33 @@ cdef class SyclContext(_SyclContext):
SyclContext._init_helper(<_SyclContext> self, CRef)
return 0

cdef int _init_context_from_capsule(self, object cap):
"""
For named PyCapsule with name SyclContextRef, which carries pointer to
sycl::context object, interpreted as DPCTLSyclContextRef, creates corresponding
SyclContext.
"""
cdef DPCTLSyclContextRef CRef = NULL
cdef DPCTLSyclContextRef CRef_copy = NULL
cdef int ret = 0
if pycapsule.PyCapsule_IsValid(cap, "SyclContextRef"):
CRef = <DPCTLSyclContextRef> pycapsule.PyCapsule_GetPointer(cap, "SyclContextRef")
if (CRef is NULL):
return -6
ret = pycapsule.PyCapsule_SetName(cap, "used_SyclContextRef")
if (ret):
Comment thread
oleksandr-pavlyk marked this conversation as resolved.
return -6
CRef_copy = DPCTLContext_Copy(CRef)
if (CRef_copy is NULL):
return -7
self._ctxt_ref = CRef_copy
return 0
Comment thread
oleksandr-pavlyk marked this conversation as resolved.
else:
# __cinit__ checks that capsule is valid, so one can be here only
# if call to `_init_context_from_capsule` was made outside of __cinit__
# and the capsule was not checked to be valid
return -128

def __cinit__(self, arg=None):
""" SyclContext() - create a context for a default device
SyclContext(filter_selector_string) - create a context for specified device
Expand All @@ -148,25 +183,29 @@ cdef class SyclContext(_SyclContext):
"""
cdef int ret = 0
if isinstance(arg, _SyclContext):
ret = self._init_from__SyclContext(<_SyclContext> arg)
ret = self._init_context_from__SyclContext(<_SyclContext> arg)
elif isinstance(arg, SyclDevice):
ret = self._init_from_one_device(<SyclDevice> arg, 0)
ret = self._init_context_from_one_device(<SyclDevice> arg, 0)
elif pycapsule.PyCapsule_IsValid(arg, "SyclContextRef"):
status = self._init_context_from_capsule(arg)
elif isinstance(arg, (list, tuple)) and all([isinstance(argi, SyclDevice) for argi in arg]):
ret = self._init_from_devices(arg, 0)
ret = self._init_conext_from_devices(arg, 0)
else:
dev = SyclDevice(arg)
ret = self._init_from_one_device(<SyclDevice> dev, 0)
ret = self._init_context_from_one_device(<SyclDevice> dev, 0)
if (ret < 0):
if (ret == -1):
raise ValueError("Context failed to be created.")
if (ret == -2):
elif (ret == -2):
raise TypeError("List of devices to create context from must be non-empty.")
if (ret == -3):
elif (ret == -3):
raise MemoryError("Could not allocate necessary temporary memory.")
if (ret == -4):
elif (ret == -4) or (ret == -7):
raise ValueError("Internal Error: Could not create a copy of a sycl device.")
if (ret == -5):
elif (ret == -5):
raise ValueError("Internal Error: Creation of DeviceVector failed.")
elif (ret == -6):
raise TypeError("Input capsule {} contains a null pointer or could not be renamed".format(arg))
raise ValueError("Unrecognized error code ({}) encountered.".format(ret))

cpdef bool equals (self, SyclContext ctxt):
Expand Down Expand Up @@ -228,3 +267,11 @@ cdef class SyclContext(_SyclContext):
return ("<dpctl." + self.__name__ + " at {}>".format(hex(id(self))))
else:
return ("<dpctl." + self.__name__ + " for {} devices at {}>".format(n, hex(id(self))))

def _get_capsule(self):
cdef DPCTLSyclContextRef CRef = NULL
CRef = DPCTLContext_Copy(self._ctxt_ref)
if (CRef is NULL):
raise ValueError("SyclContext copy failed.")
return pycapsule.PyCapsule_New(<void *>CRef, "SyclContextRef", &_context_capsule_deleter)

1 change: 1 addition & 0 deletions dpctl/_sycl_queue.pxd
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ cdef class SyclQueue (_SyclQueue):
cdef int _init_queue_from_context_and_device(
self, SyclContext, SyclDevice, int
)
cdef int _init_queue_from_capsule(self, object)
cdef _raise_queue_submit_error(self, fname, errcode)
cdef _raise_invalid_range_error(self, fname, ndims, errcode)
cdef int _populate_args(
Expand Down
69 changes: 65 additions & 4 deletions dpctl/_sycl_queue.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ from .memory._memory cimport _Memory
from . import backend_type
import ctypes
from libc.stdlib cimport malloc, free
from cpython cimport pycapsule
import logging


Expand Down Expand Up @@ -136,8 +137,15 @@ cdef int _parse_queue_properties(object prop) except *:
return res


cdef void _queue_capsule_deleter(object o):
cdef DPCTLSyclQueueRef QRef = NULL
if pycapsule.PyCapsule_IsValid(o, "SyclQueueRef"):
QRef = <DPCTLSyclQueueRef> pycapsule.PyCapsule_GetPointer(o, "SyclQueueRef")
DPCTLQueue_Delete(QRef)


cdef class _SyclQueue:
""" Internal helper metaclass to abstract `cl::sycl::queue` instance.
""" Barebone data owner class used by SyclQueue.
"""
def __dealloc__(self):
if (self._queue_ref):
Expand All @@ -146,7 +154,7 @@ cdef class _SyclQueue:
# self._device is a Python object


cdef class SyclQueue:
cdef class SyclQueue(_SyclQueue):
""" Python wrapper class for cl::sycl::queue.
"""
def __cinit__(self, *args, **kwargs):
Expand Down Expand Up @@ -191,6 +199,8 @@ cdef class SyclQueue:
filter_c_str, props)
elif isinstance(arg, SyclDevice):
status = self._init_queue_from_device(<SyclDevice>arg, props)
elif pycapsule.PyCapsule_IsValid(arg, "SyclQueueRef"):
status = self._init_queue_from_capsule(arg)
else:
raise TypeError(
"Positional argument {} is not a filter string or a "
Expand Down Expand Up @@ -219,11 +229,11 @@ cdef class SyclQueue:
"Device filter selector string '{}' is not understood."
.format(arg)
)
elif status == -2:
elif status == -2 or status == -8:
raise SyclQueueCreationError(
"SYCL Device '{}' could not be created.".format(arg)
)
elif status == -3:
elif status == -3 or status == -7:
raise SyclQueueCreationError(
"SYCL Context could not be created from '{}'.".format(arg)
)
Expand All @@ -233,6 +243,10 @@ cdef class SyclQueue:
raise SyclQueueCreationError(
"SYCL Queue failed to be created from '{}'.".format(arg)
)
elif status == -5:
raise TypeError("Input capsule {} contains a null pointer or could not be renamed".format(arg))
elif status == -6:
raise "SYCL Queue failed to be created from '{}'.".format(arg)

cdef int _init_queue_from__SyclQueue(self, _SyclQueue other):
""" Copy data container _SyclQueue fields over.
Expand Down Expand Up @@ -361,6 +375,46 @@ cdef class SyclQueue:
self._queue_ref = QRef
return 0 # normal return

cdef int _init_queue_from_capsule(self, object cap):
"""
For named PyCapsule with name SyclQueueRef, which carries pointer to
sycl::queue object, interpreted as DPCTLSyclQueueRef, creates corresponding
SyclQueue.
"""
cdef DPCTLSyclContextRef CRef = NULL
cdef DPCTLSyclDeviceRef DRef = NULL
cdef DPCTLSyclQueueRef QRef = NULL
cdef DPCTLSyclQueueRef QRef_copy = NULL
cdef int ret = 0
if pycapsule.PyCapsule_IsValid(cap, "SyclQueueRef"):
QRef = <DPCTLSyclQueueRef> pycapsule.PyCapsule_GetPointer(cap, "SyclQueueRef")
if (QRef is NULL):
return -5
ret = pycapsule.PyCapsule_SetName(cap, "used_SyclQueueRef")
if (ret):
return -5
QRef_copy = DPCTLQueue_Copy(QRef)
if (QRef_copy is NULL):
return -6
CRef = DPCTLQueue_GetContext(QRef_copy)
if (CRef is NULL):
DPCTLQueue_Delete(QRef_copy)
return -7
DRef = DPCTLQueue_GetDevice(QRef_copy)
if (DRef is NULL):
DPCTLContext_Delete(CRef)
DPCTLQueue_Delete(QRef_copy)
return -8
self._context = SyclContext._create(CRef)
self._device = SyclDevice._create(DRef)
self._queue_ref = QRef_copy
return 0
else:
# __cinit__ checks that capsule is valid, so one can be here only
# if call to `_init_queue_from_capsule` was made outside of __cinit__
# and the capsule was not checked to be valid
return -128

@staticmethod
cdef SyclQueue _create(DPCTLSyclQueueRef qref):
"""
Expand Down Expand Up @@ -685,3 +739,10 @@ cdef class SyclQueue:

def __repr__(self):
return "<dpctl." + self.__name__ + " at {}>".format(hex(id(self)))

def _get_capsule(self):
cdef DPCTLSyclQueueRef QRef = NULL
QRef = DPCTLQueue_Copy(self._queue_ref)
if (QRef is NULL):
raise ValueError("SyclQueue copy failed.")
return pycapsule.PyCapsule_New(<void *>QRef, "SyclQueueRef", &_queue_capsule_deleter)