Skip to content

Commit a933a88

Browse files
cpcloudclaude
andcommitted
Fix Buffer.is_managed to merge driver and resource signals
Previous fix unconditionally delegated Buffer.is_managed to _memory_resource.is_managed, which returns False for any MemoryResource subclass that does not opt in. That broke DummyUnifiedMemoryResource (and any user-defined MR wrapping cuMemAllocManaged) where the driver pointer attribute correctly reports IS_MANAGED=1 but the resource does not override is_managed. Query the driver first; only fall back to the memory resource when the driver does not report IS_MANAGED (the pool-allocated managed memory path). This keeps both old-style cuMemAllocManaged buffers and ManagedMemoryResource pool allocations correctly classified. Also rework the regression test parametrization to skip the pinned case when PinnedMemoryResource is unavailable (CUDA < 13.0), and pick up the ruff-format reflow of the helper call site. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 27b309f commit a933a88

File tree

2 files changed

+15
-17
lines changed

2 files changed

+15
-17
lines changed

cuda_core/cuda/core/_memory/_buffer.pyx

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -390,10 +390,12 @@ cdef class Buffer:
390390
@property
391391
def is_managed(self) -> bool:
392392
"""Return True if this buffer is CUDA managed (unified) memory, otherwise False."""
393-
if self._memory_resource is not None:
394-
return self._memory_resource.is_managed
395393
_init_mem_attrs(self)
396-
return self._mem_attrs.is_managed
394+
if self._mem_attrs.is_managed:
395+
return True
396+
# Pool-allocated managed memory does not set CU_POINTER_ATTRIBUTE_IS_MANAGED,
397+
# so fall back to the memory resource when it advertises managed allocations.
398+
return self._memory_resource is not None and self._memory_resource.is_managed
397399

398400
@property
399401
def is_mapped(self) -> bool:

cuda_core/tests/test_memory.py

Lines changed: 10 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -617,9 +617,7 @@ def test_managed_memory_resource_buffer_dlpack_device_type():
617617
device = Device()
618618
device.set_current()
619619
skip_if_managed_memory_unsupported(device)
620-
mr = create_managed_memory_resource_or_skip(
621-
ManagedMemoryResourceOptions(preferred_location=device.device_id)
622-
)
620+
mr = create_managed_memory_resource_or_skip(ManagedMemoryResourceOptions(preferred_location=device.device_id))
623621
buf = mr.allocate(1024)
624622

625623
assert mr.is_managed
@@ -630,23 +628,21 @@ def test_managed_memory_resource_buffer_dlpack_device_type():
630628
assert view.__dlpack_device__() == (int(DLDeviceType.kDLCUDAManaged), 0)
631629

632630

633-
@pytest.mark.parametrize(
634-
("mr_factory", "expected_managed"),
635-
[
636-
(lambda dev: DeviceMemoryResource(dev), False),
637-
(lambda dev: PinnedMemoryResource(), False),
638-
],
639-
)
640-
def test_non_managed_resources_report_not_managed(mr_factory, expected_managed):
631+
@pytest.mark.parametrize("mr_kind", ["device", "pinned"])
632+
def test_non_managed_resources_report_not_managed(mr_kind):
641633
"""Non-managed memory resources must report is_managed=False."""
642634
device = Device()
643635
device.set_current()
644636
if not device.properties.memory_pools_supported:
645637
pytest.skip("Device does not support mempool operations")
646-
mr = mr_factory(device)
647-
assert mr.is_managed is expected_managed
638+
if mr_kind == "device":
639+
mr = DeviceMemoryResource(device)
640+
else:
641+
skip_if_pinned_memory_unsupported(device)
642+
mr = PinnedMemoryResource()
643+
assert mr.is_managed is False
648644
buf = mr.allocate(1024)
649-
assert buf.is_managed is expected_managed
645+
assert buf.is_managed is False
650646
buf.close()
651647

652648

0 commit comments

Comments
 (0)