Skip to content

fix(core): compare CUdeviceptr as int so the VMM grow fast path can run#2407

Draft
aryanputta wants to merge 1 commit into
NVIDIA:mainfrom
aryanputta:fix/vmm-fast-path-ptr-compare
Draft

fix(core): compare CUdeviceptr as int so the VMM grow fast path can run#2407
aryanputta wants to merge 1 commit into
NVIDIA:mainfrom
aryanputta:fix/vmm-fast-path-ptr-compare

Conversation

@aryanputta

@aryanputta aryanputta commented Jul 22, 2026

Copy link
Copy Markdown
Contributor

Description

Addresses defect 2 of #2388 (the dead grow fast path). The other three defects in that issue are not touched here, so this does not close it.

modify_allocation() asks cuMemAddressReserve for the address immediately after the current range, then checks whether the driver granted that exact address before taking the fast path:

res, new_ptr = driver.cuMemAddressReserve(..., int(buf.handle) + aligned_prev_size, 0)

if res != driver.CUresult.CUDA_SUCCESS or new_ptr != (int(buf.handle) + aligned_prev_size):

new_ptr is a CUdeviceptr. That type defines __int__ and __repr__ but no __eq__ or __richcmp__ (cuda_bindings/cuda/bindings/driver.pyx), so comparing it against a plain int falls back to identity and is unconditionally unequal. The guard is therefore always taken, _grow_allocation_fast_path is unreachable, and every grow runs the slow path: a full re-reserve plus remap, with the buffer's base pointer changing even when the driver did grant a contiguous extension.

The fix is the int() conversion suggested in the issue.

Behavior change, not a pure cleanup

This makes a previously unreachable path live. After it, a grow the driver can satisfy contiguously preserves the base pointer instead of moving it. That is the documented intent of the fast path, but it has never actually executed in production, so it deserves explicit attention in review. The existing test asserting a grown buffer's pointer may change (test_vmm_allocator_grow_allocation) still passes, since it only requires a non-null handle.

Testing

  • test_cudeviceptr_is_never_equal_to_plain_int pins the underlying pitfall directly: CUdeviceptr(x) == x is False and call sites must go through int(). This one needs no device.
  • test_vmm_allocator_grow_dispatches_to_fast_path stubs cuMemAddressReserve to grant exactly the address requested and asserts the dispatch reaches the fast path. It should fail on current main, recording "slow".

test_vmm_allocator_grow_allocation_fast_path already covered _grow_allocation_fast_path itself by calling it directly, which is why the broken dispatch was invisible. The gap was coverage of the decision that reaches it.

Checklist

  • New or existing tests cover these changes.
  • The documentation is up to date with these changes.

`modify_allocation()` asks `cuMemAddressReserve` for the address immediately
after the current range, then checks whether the driver granted that exact
address before taking the fast path.

`cuMemAddressReserve` returns `new_ptr` as a `CUdeviceptr`. That type defines
`__int__` and `__repr__` but no `__eq__` or `__richcmp__`, so `new_ptr != <int>`
falls back to identity comparison and is unconditionally true. The guard is
therefore always taken and `_grow_allocation_fast_path` is unreachable: every
grow runs the slow path, re-reserving the whole range and remapping it, so the
buffer's base pointer changes even when a contiguous extension was available.

Convert with `int()` before comparing. Reported as defect 2 in NVIDIA#2388.

Two tests cover this:

- `test_cudeviceptr_is_never_equal_to_plain_int` pins the underlying pitfall,
  that `CUdeviceptr(x) == x` is False and call sites must go through `int()`.
- `test_vmm_allocator_grow_dispatches_to_fast_path` stubs `cuMemAddressReserve`
  to grant the requested address and asserts the dispatch reaches the fast path.
  It fails on the current code, which records "slow".

Note this makes a previously unreachable code path live, so it is a behavior
change rather than a pure cleanup: successful contiguous grows now preserve the
base pointer instead of moving it. The existing
`test_vmm_allocator_grow_allocation_fast_path` already exercised
`_grow_allocation_fast_path` directly, so the helper itself is covered; what was
missing was coverage of the dispatch decision that reaches it.

Signed-off-by: Aryan Putta <aryansputta@gmail.com>
@copy-pr-bot

copy-pr-bot Bot commented Jul 22, 2026

Copy link
Copy Markdown
Contributor

This pull request requires additional validation before any workflows can run on NVIDIA's runners.

Pull request vetters can view their responsibilities here.

Contributors can view more details about this message here.

@github-actions github-actions Bot added the cuda.core Everything related to the cuda.core module label Jul 22, 2026
@aryanputta
aryanputta marked this pull request as draft July 22, 2026 15:38
@aryanputta

Copy link
Copy Markdown
Contributor Author

Marking this as a draft. I commented on #2388 asking to be assigned before I opened this, but I did not wait for a reply first, which is not the process CONTRIBUTING asks for. The change is here if it is useful, but I am not asking for review time until a maintainer decides who should take #2388, and I am happy to close this if you would rather handle the four defects together or assign them elsewhere.

Worth noting for whoever picks it up: the GPU-gated test here has not run, since workflows on this PR are waiting on vetter validation, and I do not have an NVIDIA GPU to run it locally. test_vmm_allocator_grow_dispatches_to_fast_path is expected to fail on current main.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

cuda.core Everything related to the cuda.core module

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant