Skip to content

add CUDA buffer support - #293

Merged
lkdvos merged 3 commits into
mainfrom
cuda-buffer
Aug 7, 2026
Merged

add CUDA buffer support#293
lkdvos merged 3 commits into
mainfrom
cuda-buffer

Conversation

@lkdvos

@lkdvos lkdvos commented Aug 6, 2026

Copy link
Copy Markdown
Member

This PR extends the BufferAllocator support to also include CUDA-backed storage types.
While CUDA itself hosts a memory pool as well, this can be used for a little more fine-grained control, for example when memory is really tight.
Will try and have a look to generalize to AMD too, but hope to do that in a separate PR.

Also for follow-up: I think the cuTENSOR implementations actually have a way to provide the workspace manually as well, so possibly that could take of a little more of the memory pressure.

Comment thread docs/src/man/backends.md Outdated
The prose said `BufferAllocator` while the example below it constructs a
`CUDABufferAllocator`, which read as inconsistent.
@lkdvos
lkdvos requested a review from kshyatt August 6, 2026 20:02
@codecov

codecov Bot commented Aug 7, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 93.22034% with 4 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
ext/TensorOperationsCUDACoreExt.jl 85.18% 4 Missing ⚠️
Files with missing lines Coverage Δ
ext/TensorOperationscuTENSORExt.jl 95.78% <100.00%> (+0.04%) ⬆️
src/implementation/allocator.jl 95.68% <100.00%> (+0.95%) ⬆️
ext/TensorOperationsCUDACoreExt.jl 91.48% <85.18%> (-8.52%) ⬇️
🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@lkdvos lkdvos closed this Aug 7, 2026
@lkdvos lkdvos reopened this Aug 7, 2026
@lkdvos
lkdvos merged commit 58c6e03 into main Aug 7, 2026
10 of 11 checks passed
@lkdvos
lkdvos deleted the cuda-buffer branch August 7, 2026 13:04
JoeyT1994 pushed a commit to JoeyT1994/TensorNetworkQuantumSimulator.jl that referenced this pull request Aug 7, 2026
Describe one block of the double-layer contraction as an `ncon` network -- one
integer label per bond, read off each tensor's own `inds` -- instead of a
hand-written permutedims!/mul! chain, and compile that network once per message
into a list of pairwise `tensorcontract!` steps replayed per block. Temporaries
come from a `TensorOperations.BufferAllocator` arena that sizes itself, so
`message_scratch_length`, `scratch_buffer!` and the manual offset carving are
gone along with the fixed-shape kernel.

Three capability changes follow from the generic network:

  * Any vertex degree. The old `length(ms) == 2` guard meant the kernel never
    fired on a degree-4 vertex -- i.e. never on a square lattice interior, which
    then took the ~6-factor `contract` path.
  * A non-identity on-site operator is one more tensor in the network rather
    than a fallback. The identity is still detected and dropped.
  * `backend` is selectable via `Algorithm("blocked"; backend = ...)` and
    otherwise resolved from the array type, so cuTENSOR is reachable.

Whether the closing layer is pre-permuted is a backend trait: the strided/Base
backends contract by permuting into temporaries and need it, cuTENSOR takes
arbitrary index modes and would pay a wasted factor for it.

Measured against the previous kernel (hexagonal(3,3) and grid(4,4), ComplexF64):

  hex chi=64 blocked sweep     701 ms / 15.7 MiB  ->  422 ms / 7.4 MiB
  grid(4,4) chi=64 sweep      27.7 s / 30.7 GiB   ->  18.3 s / 7.2 MiB
  vertex_scalar hex chi=32    58.4 ms / 5.7 MiB   ->  35.8 ms / 2.9 MiB

The arena tracks its high-water mark: 1.19 factors at chi=256, degree 3.

Adds `message_arena_stats` and `@debug` reporting for the arena, and takes
TensorOperations from QuantumKitHub/TensorOperations.jl#293 via `[sources]` for its
`BufferAllocator` device support.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
lkdvos added a commit that referenced this pull request Aug 7, 2026
Wire `ROCArray` and `JLArray` into the storage-generic `BufferAllocator` from
#293, through `AMDBufferAllocator` and `JLBufferAllocator`.

Unlike the CUDA extension, neither can serve temporaries via `unsafe_wrap`:
`AMDGPU.unsafe_wrap` queries `hipPointerGetAttributes` on every call and would
re-register host buffers, and `JLArrays` has no `unsafe_wrap` at all. Both
instead share the buffer's refcounted `DataRef` at an offset, the way their own
`reshape` does, which needs no API call and keeps the buffer alive by refcount.

`JLArray` offsets are in elements rather than bytes, so element types whose size
does not divide the alignment fall back on a regular allocation instead of
landing on a truncated offset.

The `JLArray` backing also makes the foreign-storage paths testable without GPU
hardware, which they previously were not.

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants