Skip to content

Commit 3aced4c

Browse files
Static method of _Memory to create from external allocation
Method takes USMRef, number of bytes and queue reference. If USMRef is bound to context in the queue and USM type comes back not 'unknown', appropriate MemoryUSM* object is created which assumes ownership of this memory. Optional `memory_owner` keyword argument may be specified to set the recorded reference object to something other than None (signaling that _Memory is responsible for memory deallocation). This can be used to create MemoryUSM* Python object from natively allocated memory, populate it, but leave deallocation to the caller. It could also be set to a PyCapsule object that carries a custom deleter.
1 parent 5a60bd0 commit 3aced4c

File tree

3 files changed

+62
-3
lines changed

3 files changed

+62
-3
lines changed

.flake8

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ per-file-ignores =
2020
dpctl/_sycl_platform.pyx: E999, E225
2121
dpctl/_sycl_queue.pyx: E999, E225, E226, E227
2222
dpctl/_sycl_queue_manager.pyx: E999, E225
23-
dpctl/memory/_memory.pyx: E999, E225, E226, E227
23+
dpctl/memory/_memory.pyx: E999, E225, E226, E227, E125
2424
dpctl/program/_program.pyx: E999, E225, E226, E227
2525
dpctl/tensor/numpy_usm_shared.py: F821
2626
examples/cython/sycl_buffer/_buffer_example.pyx: E999, E225, E402

dpctl/memory/_memory.pxd

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,13 @@ cdef public class _Memory [object Py_MemoryObject, type Py_MemoryType]:
5555
DPCTLSyclUSMRef p, SyclContext ctx)
5656
@staticmethod
5757
cdef public bytes get_pointer_type(DPCTLSyclUSMRef p, SyclContext ctx)
58+
@staticmethod
59+
cdef public object create_from_usm_pointer_size_qref(
60+
DPCTLSyclUSMRef USMRef,
61+
Py_ssize_t nbytes,
62+
DPCTLSyclQueueRef QRef,
63+
object memory_owner=*
64+
)
5865

5966

6067
cdef public class MemoryUSMShared(_Memory) [object PyMemoryUSMSharedObject,

dpctl/memory/_memory.pyx

Lines changed: 54 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,9 +39,11 @@ from dpctl._backend cimport ( # noqa: E211
3939
DPCTLQueue_Copy,
4040
DPCTLQueue_Create,
4141
DPCTLQueue_Delete,
42+
DPCTLQueue_GetContext,
4243
DPCTLQueue_Memcpy,
4344
DPCTLSyclContextRef,
4445
DPCTLSyclDeviceRef,
46+
DPCTLSyclUSMRef,
4547
DPCTLUSM_GetPointerDevice,
4648
DPCTLUSM_GetPointerType,
4749
)
@@ -106,7 +108,8 @@ def _to_memory(unsigned char[::1] b, str usm_kind):
106108
else:
107109
raise ValueError(
108110
"Unrecognized usm_kind={} stored in the "
109-
"pickle".format(usm_kind))
111+
"pickle".format(usm_kind)
112+
)
110113
res.copy_from_host(b)
111114

112115
return res
@@ -214,7 +217,7 @@ cdef class _Memory:
214217
self.memory_ptr, ctx.get_context_ref()
215218
)
216219
if kind == b'device':
217-
raise ValueError('USM Device memory is not host accessible')
220+
raise ValueError("USM Device memory is not host accessible")
218221
buffer.buf = <char*>self.memory_ptr
219222
buffer.format = 'B' # byte
220223
buffer.internal = NULL # see References
@@ -431,6 +434,55 @@ cdef class _Memory:
431434

432435
return <bytes>usm_type
433436

437+
@staticmethod
438+
cdef object create_from_usm_pointer_size_qref(
439+
DPCTLSyclUSMRef USMRef, Py_ssize_t nbytes,
440+
DPCTLSyclQueueRef QRef, object memory_owner=None):
441+
r"""
442+
Create appropriate `MemoryUSM*` object from pre-allocated
443+
USM memory bound to SYCL context in the reference SYCL queue.
444+
445+
Memory will be freed by `MemoryUSM*` object for default
446+
value of memory_owner keyword. The non-default value should
447+
be an object whose dealloc slot frees the memory.
448+
449+
The object may not be a no-op dummy Python object to
450+
delay freeing the memory until later times.
451+
"""
452+
cdef const char *usm_type
453+
cdef DPCTLSyclContextRef CRef = NULL
454+
cdef DPCTLSyclQueueRef QRef_copy = NULL
455+
cdef _Memory _mem
456+
cdef object mem_ty
457+
if nbytes <= 0:
458+
raise ValueError("Number of bytes must must be positive")
459+
if (QRef is NULL):
460+
raise TypeError("Argument DPCTLSyclQueueRef is NULL")
461+
CRef = DPCTLQueue_GetContext(QRef)
462+
if (CRef is NULL):
463+
raise ValueError("Could not retrieve context from QRef")
464+
usm_type = DPCTLUSM_GetPointerType(USMRef, CRef)
465+
if usm_type == b"shared":
466+
mem_ty = MemoryUSMShared
467+
elif usm_type == b"device":
468+
mem_ty = MemoryUSMDevice
469+
elif usm_type == b"host":
470+
mem_ty = MemoryUSMHost
471+
else:
472+
raise ValueError(
473+
"Argument pointer is not bound to "
474+
"context in the given queue"
475+
)
476+
res = _Memory.__new__(_Memory)
477+
_mem = <_Memory> res
478+
_mem._cinit_empty()
479+
_mem.memory_ptr = USMRef
480+
_mem.nbytes = nbytes
481+
QRef_copy = DPCTLQueue_Copy(QRef)
482+
_mem.queue = SyclQueue._create(QRef_copy)
483+
_mem.refobj = memory_owner
484+
return mem_ty(res)
485+
434486

435487
cdef class MemoryUSMShared(_Memory):
436488
"""

0 commit comments

Comments
 (0)