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
12 changes: 1 addition & 11 deletions cuda_core/cuda/core/_memory/_buffer.pxd
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,10 @@
#
# SPDX-License-Identifier: Apache-2.0

from libc.stdint cimport uintptr_t
from libcpp cimport bool as cpp_bool
from libcpp.atomic cimport atomic as std_atomic, memory_order_acquire, memory_order_release
from libcpp.atomic cimport atomic as std_atomic

from cuda.bindings cimport cydriver
from cuda.core._resource_handles cimport DevicePtrHandle
from cuda.core._stream cimport Stream


cdef struct _MemAttrs:
Expand Down Expand Up @@ -47,10 +44,3 @@ cdef Buffer Buffer_from_deviceptr_handle(
object ipc_descriptor = *,
type cls = *,
)

# Memory attribute query helpers (used by _managed_memory_ops)
cdef void _init_mem_attrs(Buffer self)
cdef int _query_memory_attrs(
_MemAttrs& out,
cydriver.CUdeviceptr ptr,
) except -1 nogil
134 changes: 67 additions & 67 deletions cuda_core/cuda/core/_memory/_buffer.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ from __future__ import annotations

cimport cython
from libc.stdint cimport uintptr_t
from libcpp.atomic cimport memory_order_acquire, memory_order_release

from cuda.bindings cimport cydriver
from cuda.core._memory._device_memory_resource import DeviceMemoryResource
Expand Down Expand Up @@ -76,6 +77,68 @@ register_mr_dealloc_callback(_mr_dealloc_callback)
__all__ = ['Buffer', 'MemoryResource']


# Memory Attribute Query Helpers
# ------------------------------
cdef inline int _query_memory_attrs(
_MemAttrs& out,
cydriver.CUdeviceptr ptr
) except -1 nogil:
"""Query memory attributes for a device pointer."""
cdef unsigned int memory_type = 0
cdef int is_managed = 0
cdef int device_id = 0
cdef cydriver.CUpointer_attribute[3] attrs = [
cydriver.CUpointer_attribute.CU_POINTER_ATTRIBUTE_MEMORY_TYPE,
cydriver.CUpointer_attribute.CU_POINTER_ATTRIBUTE_IS_MANAGED,
cydriver.CUpointer_attribute.CU_POINTER_ATTRIBUTE_DEVICE_ORDINAL,
]
cdef uintptr_t[3] vals = [
<uintptr_t><void*>&memory_type,
<uintptr_t><void*>&is_managed,
<uintptr_t><void*>&device_id,
]

cdef cydriver.CUresult ret
ret = cydriver.cuPointerGetAttributes(3, attrs, <void**>vals, ptr)
if ret == cydriver.CUresult.CUDA_ERROR_NOT_INITIALIZED:
with cython.gil:
# Device class handles the cuInit call internally
Device()
ret = cydriver.cuPointerGetAttributes(3, attrs, <void**>vals, ptr)
HANDLE_RETURN(ret)

# TODO: HMM/ATS-enabled sysmem should also report is_managed=True; the
# CU_POINTER_ATTRIBUTE_IS_MANAGED query does not capture that yet.
out.is_managed = is_managed != 0

if memory_type == 0:
# unregistered host pointer
out.is_host_accessible = True
out.is_device_accessible = False
out.device_id = -1
elif (
is_managed
or memory_type == cydriver.CUmemorytype.CU_MEMORYTYPE_HOST
):
# Managed memory or pinned host memory
out.is_host_accessible = True
out.is_device_accessible = True
out.device_id = device_id
elif memory_type == cydriver.CUmemorytype.CU_MEMORYTYPE_DEVICE:
out.is_host_accessible = False
out.is_device_accessible = True
out.device_id = device_id
else:
with cython.gil:
raise ValueError(f"Unsupported memory type: {memory_type}")
return 0


cdef inline void _init_memory_attrs(Buffer self):
"""Initialize memory attributes by querying the pointer."""
if not self._mem_attrs_inited.load(memory_order_acquire):
_query_memory_attrs(self._mem_attrs, as_cu(self._h_ptr))
self._mem_attrs_inited.store(True, memory_order_release)


cdef class Buffer:
Expand Down Expand Up @@ -381,7 +444,7 @@ cdef class Buffer:
"""Return the device ordinal of this buffer."""
if self._memory_resource is not None:
return self._memory_resource.device_id
_init_mem_attrs(self)
_init_memory_attrs(self)
return self._mem_attrs.device_id

@property
Expand Down Expand Up @@ -416,21 +479,21 @@ cdef class Buffer:
"""Return True if this buffer can be accessed by the GPU, otherwise False."""
if self._memory_resource is not None:
return self._memory_resource.is_device_accessible
_init_mem_attrs(self)
_init_memory_attrs(self)
return self._mem_attrs.is_device_accessible

@property
def is_host_accessible(self) -> bool:
"""Return True if this buffer can be accessed by the CPU, otherwise False."""
if self._memory_resource is not None:
return self._memory_resource.is_host_accessible
_init_mem_attrs(self)
_init_memory_attrs(self)
return self._mem_attrs.is_host_accessible

@property
def is_managed(self) -> bool:
"""Return True if this buffer is CUDA managed (unified) memory, otherwise False."""
_init_mem_attrs(self)
_init_memory_attrs(self)
if self._mem_attrs.is_managed:
return True
# Pool-allocated managed memory does not set CU_POINTER_ATTRIBUTE_IS_MANAGED,
Expand Down Expand Up @@ -459,69 +522,6 @@ cdef class Buffer:
return self._owner


# Memory Attribute Query Helpers
# ------------------------------
cdef inline void _init_mem_attrs(Buffer self):
"""Initialize memory attributes by querying the pointer."""
if not self._mem_attrs_inited.load(memory_order_acquire):
_query_memory_attrs(self._mem_attrs, as_cu(self._h_ptr))
self._mem_attrs_inited.store(True, memory_order_release)


cdef inline int _query_memory_attrs(
_MemAttrs& out,
cydriver.CUdeviceptr ptr
) except -1 nogil:
"""Query memory attributes for a device pointer."""
cdef unsigned int memory_type = 0
cdef int is_managed = 0
cdef int device_id = 0
cdef cydriver.CUpointer_attribute attrs[3]
cdef uintptr_t vals[3]

attrs[0] = cydriver.CUpointer_attribute.CU_POINTER_ATTRIBUTE_MEMORY_TYPE
attrs[1] = cydriver.CUpointer_attribute.CU_POINTER_ATTRIBUTE_IS_MANAGED
attrs[2] = cydriver.CUpointer_attribute.CU_POINTER_ATTRIBUTE_DEVICE_ORDINAL
vals[0] = <uintptr_t><void*>&memory_type
vals[1] = <uintptr_t><void*>&is_managed
vals[2] = <uintptr_t><void*>&device_id

cdef cydriver.CUresult ret
ret = cydriver.cuPointerGetAttributes(3, attrs, <void**>vals, ptr)
if ret == cydriver.CUresult.CUDA_ERROR_NOT_INITIALIZED:
with cython.gil:
# Device class handles the cuInit call internally
Device()
ret = cydriver.cuPointerGetAttributes(3, attrs, <void**>vals, ptr)
HANDLE_RETURN(ret)

# TODO: HMM/ATS-enabled sysmem should also report is_managed=True; the
# CU_POINTER_ATTRIBUTE_IS_MANAGED query does not capture that yet.
out.is_managed = is_managed != 0

if memory_type == 0:
# unregistered host pointer
out.is_host_accessible = True
out.is_device_accessible = False
out.device_id = -1
elif (
is_managed
or memory_type == cydriver.CUmemorytype.CU_MEMORYTYPE_HOST
):
# Managed memory or pinned host memory
out.is_host_accessible = True
out.is_device_accessible = True
out.device_id = device_id
elif memory_type == cydriver.CUmemorytype.CU_MEMORYTYPE_DEVICE:
out.is_host_accessible = False
out.is_device_accessible = True
out.device_id = device_id
else:
with cython.gil:
raise ValueError(f"Unsupported memory type: {memory_type}")
return 0


cdef class MemoryResource:
"""Abstract base class for memory resources that manage allocation and
deallocation of buffers.
Expand Down
1 change: 0 additions & 1 deletion cuda_core/cuda/core/_memory/_device_memory_resource.pxd
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
# SPDX-License-Identifier: Apache-2.0

from cuda.core._memory._memory_pool cimport _MemPool
from cuda.core._memory._ipc cimport IPCDataForMR


cdef class DeviceMemoryResource(_MemPool):
Expand Down
10 changes: 0 additions & 10 deletions cuda_core/cuda/core/_memory/_memory_pool.pxd
Original file line number Diff line number Diff line change
Expand Up @@ -41,13 +41,3 @@ cdef int MP_raise_release_threshold(_MemPool self) except? -1
# Buffer). Subclasses (e.g. ManagedMemoryResource) pass their own buffer
# subclass so their `allocate` returns the typed object.
cdef Buffer _MP_allocate(_MemPool self, size_t size, Stream stream, type cls = *)


cdef class _MemPoolAttributes:
cdef:
MemoryPoolHandle _h_pool

@staticmethod
cdef _MemPoolAttributes _init(MemoryPoolHandle h_pool)

cdef int _getattribute(self, cydriver.CUmemPool_attribute attr_enum, void* value) except? -1
2 changes: 2 additions & 0 deletions cuda_core/cuda/core/_memory/_memory_pool.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@ if TYPE_CHECKING:

cdef class _MemPoolAttributes:
"""Provides access to memory pool attributes."""
cdef:
MemoryPoolHandle _h_pool

def __init__(self, *args, **kwargs) -> None:
raise RuntimeError("_MemPoolAttributes cannot be instantiated directly. Please use MemoryResource APIs.")
Expand Down
3 changes: 1 addition & 2 deletions cuda_core/cuda/core/_memory/_pinned_memory_resource.pxd
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
# SPDX-FileCopyrightText: Copyright (c) 2024-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
# SPDX-FileCopyrightText: Copyright (c) 2024-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
#
# SPDX-License-Identifier: Apache-2.0

from cuda.core._memory._memory_pool cimport _MemPool
from cuda.core._memory._ipc cimport IPCDataForMR


cdef class PinnedMemoryResource(_MemPool):
Expand Down
Loading