Skip to content

Commit 3809a33

Browse files
committed
give our ABC class (MemoryResource) fast access in C/Cython
1 parent a5e6bcf commit 3809a33

File tree

1 file changed

+64
-68
lines changed

1 file changed

+64
-68
lines changed

cuda_core/cuda/core/experimental/_memory.pyx

Lines changed: 64 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -39,9 +39,6 @@ if TYPE_CHECKING:
3939
from ._device import Device
4040
import uuid
4141

42-
# TODO: define a memory property mixin class and make Buffer and
43-
# MemoryResource both inherit from it
44-
4542

4643
PyCapsule = TypeVar("PyCapsule")
4744
"""Represent the capsule type."""
@@ -50,7 +47,56 @@ DevicePointerT = Union[driver.CUdeviceptr, int, None]
5047
"""A type union of :obj:`~driver.CUdeviceptr`, `int` and `None` for hinting :attr:`Buffer.handle`."""
5148

5249

53-
cdef class Buffer:
50+
cdef class _cyBuffer:
51+
"""
52+
Internal only. Responsible for offering fast C method access.
53+
"""
54+
cdef:
55+
intptr_t _ptr
56+
size_t _size
57+
_cyMemoryResource _mr
58+
object _ptr_obj
59+
60+
61+
cdef class _cyMemoryResource:
62+
"""
63+
Internal only. Responsible for offering fast C method access.
64+
"""
65+
cdef Buffer _allocate(self, size_t size, cyStream stream):
66+
raise NotImplementedError
67+
68+
cdef void _deallocate(self, intptr_t ptr, size_t size, cyStream stream) noexcept:
69+
raise NotImplementedError
70+
71+
72+
class MemoryResourceAttributes(abc.ABC):
73+
74+
@property
75+
@abc.abstractmethod
76+
def is_device_accessible(self) -> bool:
77+
"""bool: True if buffers allocated by this resource can be accessed on the device."""
78+
...
79+
80+
@property
81+
@abc.abstractmethod
82+
def is_host_accessible(self) -> bool:
83+
"""bool: True if buffers allocated by this resource can be accessed on the host."""
84+
...
85+
86+
@property
87+
@abc.abstractmethod
88+
def device_id(self) -> int:
89+
"""int: The device ordinal for which this memory resource is responsible.
90+
91+
Raises
92+
------
93+
RuntimeError
94+
If the resource is not bound to a specific device.
95+
"""
96+
...
97+
98+
99+
cdef class Buffer(_cyBuffer, MemoryResourceAttributes):
54100
"""Represent a handle to allocated memory.
55101
56102
This generic object provides a unified representation for how
@@ -59,12 +105,7 @@ cdef class Buffer:
59105
60106
Support for data interchange mechanisms are provided by DLPack.
61107
"""
62-
63-
cdef:
64-
intptr_t _ptr
65-
size_t _size
66-
object _mr
67-
object _ptr_obj
108+
cdef dict __dict__ # required if inheriting from both Cython/Python classes
68109

69110
def __init__(self, *args, **kwargs):
70111
raise RuntimeError("Buffer objects cannot be instantiated directly. Please use MemoryResource APIs.")
@@ -96,17 +137,12 @@ cdef class Buffer:
96137
The stream object to use for asynchronous deallocation. If None,
97138
the behavior depends on the underlying memory resource.
98139
"""
99-
cdef _cyMemoryResource cy_mr
100140
if self._ptr and self._mr is not None:
101-
if isinstance(self._mr, _cyMemoryResource):
102-
# FIXME
103-
if stream is None:
104-
stream = Stream.__new__(Stream)
105-
(<cyStream>(stream))._handle = <cydriver.CUstream>(0)
106-
cy_mr = <_cyMemoryResource>(self._mr)
107-
cy_mr._deallocate(self._ptr, self._size, <cyStream>stream)
108-
else:
109-
self._mr.deallocate(self._ptr, self._size, stream)
141+
# To be fixed in NVIDIA/cuda-python#1032
142+
if stream is None:
143+
stream = Stream.__new__(Stream)
144+
(<cyStream>(stream))._handle = <cydriver.CUstream>(0)
145+
self._mr._deallocate(self._ptr, self._size, <cyStream>stream)
110146
self._ptr = 0
111147
self._mr = None
112148
self._ptr_obj = None
@@ -303,18 +339,7 @@ cdef class Buffer:
303339
return Buffer._init(ptr, size, mr=mr)
304340

305341

306-
cdef class _cyMemoryResource:
307-
"""
308-
Internal only. Responsible for offering fast C method access.
309-
"""
310-
cdef Buffer _allocate(self, size_t size, cyStream stream):
311-
raise NotImplementedError
312-
313-
cdef int _deallocate(self, intptr_t ptr, size_t size, cyStream stream) except?-1:
314-
raise NotImplementedError
315-
316-
317-
class MemoryResource(abc.ABC):
342+
cdef class MemoryResource(_cyMemoryResource, MemoryResourceAttributes, abc.ABC):
318343
"""Abstract base class for memory resources that manage allocation and deallocation of buffers.
319344
320345
Subclasses must implement methods for allocating and deallocation, as well as properties
@@ -323,14 +348,10 @@ class MemoryResource(abc.ABC):
323348
hold a reference to self, the buffer properties are retrieved simply by looking up the underlying
324349
memory resource's respective property.)
325350
"""
351+
cdef dict __dict__ # required if inheriting from both Cython/Python classes
326352

327-
@abc.abstractmethod
328-
def __init__(self, *args, **kwargs):
329-
"""Initialize the memory resource.
330-
331-
Subclasses may use additional arguments to configure the resource.
332-
"""
333-
...
353+
cdef void _deallocate(self, intptr_t ptr, size_t size, cyStream stream) noexcept:
354+
self.deallocate(ptr, size, stream)
334355

335356
@abc.abstractmethod
336357
def allocate(self, size_t size, stream: Stream = None) -> Buffer:
@@ -370,30 +391,6 @@ class MemoryResource(abc.ABC):
370391
"""
371392
...
372393

373-
@property
374-
@abc.abstractmethod
375-
def is_device_accessible(self) -> bool:
376-
"""bool: True if buffers allocated by this resource can be accessed on the device."""
377-
...
378-
379-
@property
380-
@abc.abstractmethod
381-
def is_host_accessible(self) -> bool:
382-
"""bool: True if buffers allocated by this resource can be accessed on the host."""
383-
...
384-
385-
@property
386-
@abc.abstractmethod
387-
def device_id(self) -> int:
388-
"""int: The device ordinal for which this memory resource is responsible.
389-
390-
Raises
391-
------
392-
RuntimeError
393-
If the resource is not bound to a specific device.
394-
"""
395-
...
396-
397394

398395
# IPC is currently only supported on Linux. On other platforms, the IPC handle
399396
# type is set equal to the no-IPC handle type.
@@ -570,7 +567,7 @@ class DeviceMemoryResourceAttributes:
570567
_ipc_registry = {}
571568

572569

573-
cdef class DeviceMemoryResource(_cyMemoryResource, MemoryResource):
570+
cdef class DeviceMemoryResource(MemoryResource):
574571
"""
575572
Create a device memory resource managing a stream-ordered memory pool.
576573
@@ -657,7 +654,7 @@ cdef class DeviceMemoryResource(_cyMemoryResource, MemoryResource):
657654
bint _is_mapped
658655
object _uuid
659656
IPCAllocationHandle _alloc_handle
660-
dict __dict__ # TODO: check if we still need this
657+
dict __dict__ # required if inheriting from both Cython/Python classes
661658
object __weakref__
662659

663660
def __cinit__(self):
@@ -917,14 +914,13 @@ cdef class DeviceMemoryResource(_cyMemoryResource, MemoryResource):
917914
stream = default_stream()
918915
return self._allocate(size, <cyStream>stream)
919916

920-
cdef int _deallocate(self, intptr_t ptr, size_t size, cyStream stream) except?-1:
917+
cdef void _deallocate(self, intptr_t ptr, size_t size, cyStream stream) noexcept:
921918
cdef cydriver.CUstream s = stream._handle
922919
cdef cydriver.CUdeviceptr devptr = <cydriver.CUdeviceptr>ptr
923920
with nogil:
924921
HANDLE_RETURN(cydriver.cuMemFreeAsync(devptr, s))
925-
return 0
926922

927-
def deallocate(self, ptr: DevicePointerT, size_t size, stream: Stream = None):
923+
cpdef deallocate(self, ptr: DevicePointerT, size_t size, stream: Stream = None):
928924
"""Deallocate a buffer previously allocated by this resource.
929925
930926
Parameters

0 commit comments

Comments
 (0)