Skip to content

cuda.core: don't require a CUDA context for host-only memory - #2773

Merged
Andy-Jost merged 1 commit into
NVIDIA:mainfrom
Andy-Jost:ajost/issue-2769
Sep 8, 2026
Merged

cuda.core: don't require a CUDA context for host-only memory#2773
Andy-Jost merged 1 commit into
NVIDIA:mainfrom
Andy-Jost:ajost/issue-2769

Conversation

@Andy-Jost

@Andy-Jost Andy-Jost commented Sep 4, 2026

Copy link
Copy Markdown
Contributor

Summary

Since 1.2.0, Buffer.from_handle binds a default-stream deallocation token to the current CUDA context for every owning memory resource (#2526) when no other deallocation stream is supplied. A memory resource whose memory the device cannot access has no stream ordering to preserve, yet it could no longer create a Buffer in a process that never initialized CUDA. This is a regression from 1.1.x, reported against nvmath-python's NVPL-backed host APIs.

Changes

  • When mr.is_device_accessible is False, Buffer.from_handle records no deallocation stream and does not call the driver. mr.deallocate() still receives the default stream, as in 1.1.
  • The "no deallocation stream was recorded" warning is removed from the teardown path, because host-only buffers legitimately have none.
  • Tests cover a host-only resource with no current context and a spawned process that never initializes CUDA, using both a ctypes-backed resource and the reporter's NumPy-backed one.

Related Work

@Andy-Jost Andy-Jost added this to the cuda.core 1.3.0 milestone Sep 4, 2026
@Andy-Jost Andy-Jost added bug Something isn't working cuda.core Everything related to the cuda.core module labels Sep 4, 2026
@Andy-Jost Andy-Jost self-assigned this Sep 4, 2026
@copy-pr-bot

copy-pr-bot Bot commented Sep 4, 2026

Copy link
Copy Markdown
Contributor

Auto-sync is disabled for draft pull requests in this repository. Workflows must be run manually.

Contributors can view more details about this message here.

Since 1.2.0, Buffer.from_handle binds a default-stream deallocation
token to the current context for every owning memory resource. Memory
the device cannot access has no stream ordering to preserve, so skip the
binding when mr.is_device_accessible is False. Such buffers record no
deallocation stream and never call the driver.

Fixes NVIDIA#2769

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@Andy-Jost
Andy-Jost requested a review from rparolin September 5, 2026 15:51
@Andy-Jost
Andy-Jost marked this pull request as ready for review September 5, 2026 15:57
@Andy-Jost
Andy-Jost requested a review from carterbox September 5, 2026 15:58
@Andy-Jost Andy-Jost added the P0 High priority - Must do! label Sep 5, 2026
@github-actions

github-actions Bot commented Sep 5, 2026

Copy link
Copy Markdown

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't see why both of these Host-only MRs are needed. For test coverage we just need one or the other.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree that it's not necessary to have both. The key point is that the MemoryResource does not use any CUDA abstractions and it able to be allocated and deallocated without an CUDA context.

@Andy-Jost
Andy-Jost merged commit 3fef50b into NVIDIA:main Sep 8, 2026
115 checks passed
@Andy-Jost
Andy-Jost deleted the ajost/issue-2769 branch September 8, 2026 16:33

@carterbox carterbox left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have run the affected nvmath-python integrations tests against this branch, and they pass.

Only non-blocking suggestions from me.

Comment on lines 65 to 69
if not h_stream:
print(
"Warning: no deallocation stream was recorded; falling back to "
"the default stream for mr.deallocate() during Buffer "
"destruction. This is an internal cuda-core error; please "
"report it with your CUDA driver, CUDA Toolkit, and "
"cuda-python versions.",
file=sys.stderr,
)
# No stream was recorded: host-only memory (Buffer._init records
# none) or a Buffer released before one was set. The default-stream
# token needs no CUDA context to construct.
stream = default_stream()

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In order to retain the existing behavior, wouldn't you want to check that mr.is_device_accessible is false before deciding whether or not to print the error?

s = Stream_accept(default_stream() if stream is None else stream)
# Host-only memory needs no CUDA context to free, so no deallocation
# stream is recorded and the driver is not called.
record_stream = mr.is_device_accessible

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

record_stream is used exactly once? Inline the expression instead?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree that it's not necessary to have both. The key point is that the MemoryResource does not use any CUDA abstractions and it able to be allocated and deallocated without an CUDA context.

Comment on lines +182 to +183
def device_id(self) -> int:
raise RuntimeError("the pinned memory resource is not bound to any GPU")

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe host-only MemoryResources should have device_id=-1 as below, and as documented in the release notes here: https://github.com/NVIDIA/cuda-python/pull/2750/changes#diff-793ada78d6808b82e09c2cbbc503b1d202ad6467a4b8b2846e894ffb234fa4b3

Andy-Jost added a commit to Andy-Jost/cuda-python that referenced this pull request Sep 8, 2026
… stderr

The host-only Buffer tests from NVIDIA#2773 asserted that nothing containing
"Warning" reached stderr. Under the error handling policy a teardown failure
is a CUDAWarning, not stderr text, so that assertion no longer checks anything.
Use assert_no_cuda_warning() around allocate/close instead (marked
thread_unsafe, as warning capture is process-global). The spawned-process
variant checks inside the child, since warnings do not cross processes; a
failure surfaces as the non-zero exit code the parent already asserts on.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working cuda.core Everything related to the cuda.core module P0 High priority - Must do!

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[BUG]: cuda-core 1.2.0 breaks Buffer use for non-CUDA memory implementations

3 participants