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
9 changes: 8 additions & 1 deletion cuda_core/tests/helpers/memory.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

import pytest

from cuda.core import ManagedMemoryResource, PinnedMemoryResource
from cuda.core import Device, ManagedMemoryResource, PinnedMemoryResource
from cuda.core._utils.cuda_utils import CUDAError


Expand Down Expand Up @@ -33,6 +33,13 @@ def skip_if_managed_memory_unsupported(device):

def create_managed_memory_resource_or_skip(*args, xfail_device=None, **kwargs):
# Keep the established "skip" helper name for call-site readability.
if not args and kwargs.get("options") is None and not Device().properties.concurrent_managed_access:
# Without options this looks up the device's default managed pool, which
# supports managed allocations only with concurrent managed access. Check
# the property instead of the lookup's error: the driver returns
# CUDA_ERROR_NOT_SUPPORTED on some machines and CUDA_ERROR_OUT_OF_MEMORY
# on others. Dedicated pools (options given) work without it.
pytest.skip("Device does not support concurrent managed memory access")
try:
return ManagedMemoryResource(*args, **kwargs)
except CUDAError as e:
Expand Down
38 changes: 38 additions & 0 deletions cuda_core/tests/test_helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
from helpers.buffers import PatternGen, compare_equal_buffers, make_scratch_buffer, thread_unsafe_on_windows
from helpers.latch import LatchKernel
from helpers.logging import TimestampedLogger
from helpers.memory import create_managed_memory_resource_or_skip
from helpers.oom_diagnostics import (
DEFAULT_FILENAME,
OOM_MARKER,
Expand Down Expand Up @@ -467,3 +468,40 @@ def test_gl_context_not_on_nvidia_gpu_reason_rejects_other_vendors(monkeypatch,
reason = gl_context_not_on_nvidia_gpu_reason()
assert reason is not None
assert "not on an NVIDIA GPU" in reason


def _patch_managed_mr_factory(monkeypatch, concurrent_managed_access):
# Stand in for the helper's Device and ManagedMemoryResource so the skip
# decision does not depend on the local device.
device = types.SimpleNamespace(
properties=types.SimpleNamespace(concurrent_managed_access=concurrent_managed_access)
)
monkeypatch.setattr("helpers.memory.Device", lambda: device)
factory = Mock(name="ManagedMemoryResource")
monkeypatch.setattr("helpers.memory.ManagedMemoryResource", factory)
return factory


@pytest.mark.thread_unsafe(reason="patches module globals of helpers.memory")
@pytest.mark.agent_authored(model="claude-opus-5.5")
def test_managed_mr_helper_skips_default_pool_without_concurrent_access(monkeypatch):
factory = _patch_managed_mr_factory(monkeypatch, concurrent_managed_access=False)
with pytest.raises(pytest.skip.Exception, match="concurrent managed memory access"):
create_managed_memory_resource_or_skip()
factory.assert_not_called()


@pytest.mark.thread_unsafe(reason="patches module globals of helpers.memory")
@pytest.mark.parametrize(
("concurrent_managed_access", "args", "kwargs"),
[
pytest.param(False, ("options",), {}, id="positional-options"),
pytest.param(False, (), {"options": "options"}, id="keyword-options"),
pytest.param(True, (), {}, id="default-pool-with-concurrent-access"),
],
)
@pytest.mark.agent_authored(model="claude-opus-5.5")
def test_managed_mr_helper_constructs_when_pool_is_usable(monkeypatch, concurrent_managed_access, args, kwargs):
factory = _patch_managed_mr_factory(monkeypatch, concurrent_managed_access)
assert create_managed_memory_resource_or_skip(*args, **kwargs) is factory.return_value
factory.assert_called_once_with(*args, **kwargs)
14 changes: 12 additions & 2 deletions cuda_core/tests/test_managed_memory_warning.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
These tests only run on affected platforms (concurrent_managed_access is False).
"""

import sys
import warnings

import pytest
Expand All @@ -16,6 +17,7 @@
import cuda.bindings
from cuda.core import Device, ManagedMemoryResource, ManagedMemoryResourceOptions
from cuda.core._memory._managed_memory_resource import reset_concurrent_access_warning
from cuda.core._utils.cuda_utils import CUDAError

_cuda_major = int(cuda.bindings.__version__.split(".")[0])

Expand Down Expand Up @@ -51,8 +53,16 @@ def device_without_concurrent_managed_access(init_cuda):
@requires_cuda_13
def test_default_pool_error_without_concurrent_access(device_without_concurrent_managed_access):
"""ManagedMemoryResource() raises RuntimeError when the default pool doesn't support managed."""
with pytest.raises(RuntimeError, match="does not support managed allocations"):
ManagedMemoryResource()
try:
with pytest.raises(RuntimeError, match="does not support managed allocations"):
ManagedMemoryResource()
except CUDAError as e:
# nvbugs5815123: on some Windows machines the driver fails to reserve VA
# for the default managed pool lookup and returns CUDA_ERROR_OUT_OF_MEMORY
# instead of CUDA_ERROR_NOT_SUPPORTED, so the RuntimeError is never raised.
if sys.platform == "win32" and "CUDA_ERROR_OUT_OF_MEMORY" in str(e):
pytest.xfail("default managed pool lookup ran out of VA on Windows (nvbugs5815123)")
raise
Comment thread
coderabbitai[bot] marked this conversation as resolved.


@requires_cuda_13
Expand Down
Loading