Skip to content

Reuse Reactant staging buffers and copy results on the device - #73

Draft
rsenne wants to merge 3 commits into
mainfrom
reactant-device-buffers
Draft

rsenne wants to merge 3 commits into
mainfrom
reactant-device-buffers

Conversation

@rsenne

@rsenne rsenne commented Sep 20, 2026 •

Copy link
Copy Markdown
Owner

Fixes the host round trip in ReactantExt (#69, and wsmoses's comment on #66).

Closes #69

Copilot AI lite review requested due to automatic review settings September 20, 2026 20:57

Copilot AI 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.

Copilot review overview

🟡 Changes recommended

GPU device-to-device integration remains unverified, and preparation performs an unnecessary compiled execution.

Get a fresh assessment by requesting another Copilot review.

Review effort: Lite
Findings: 1 Medium severity

Open (1)
What changed in this PR

Improves Reactant/CUDA interoperability by reusing staging buffers and enabling device-to-device output copies.

Changes:

  • Adds staging and device-pointer interop hooks.
  • Reuses Reactant input/output staging buffers.
  • Adds CUDA and Reactant tests, documentation, and changelog updates.
File Summary
test/​test-Reactant-HVP.jl Tests staged Reactant execution.
test/​test-CUDA-Extension.jl Tests CUDA hooks and pointer aliasing.
src/​ParallelMCMC.jl Defines staging and pointer-wrapper hooks.
ext/​ReactantExt.jl Implements reusable buffers and device-result handling.
ext/​CUDAExt.jl Adds pinned memory and CUDA pointer wrapping.
docs/​src/​15-gpu.md Documents updated GPU behavior.
CHANGELOG.md Records the optimization.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread ext/ReactantExt.jl Outdated
Comment on lines +123 to +126
view = _device_view(template, out, platform)
if view !== nothing
res = similar(template, eltype(out), size(out))
GC.@preserve out copyto!(res, view)
@codecov

codecov Bot commented Sep 20, 2026 •

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 5.88235% with 32 lines in your changes missing coverage. Please review.
✅ Project coverage is 88.25%. Comparing base (cbe5c14) to head (1d4870f).

Files with missing lines Patch % Lines
ext/ReactantExt.jl 0.00% 31 Missing ⚠️
src/ParallelMCMC.jl 66.66% 1 Missing ⚠️

❌ Your patch check has failed because the patch coverage (5.88%) is below the target coverage (90.00%). You can increase the patch coverage or adjust the target coverage.
❌ Your project check has failed because the head coverage (88.25%) is below the target coverage (90.00%). You can increase the head coverage or adjust the target coverage.

Additional details and impacted files
@@            Coverage Diff             @@
##             main      #73      +/-   ##
==========================================
- Coverage   89.54%   88.25%   -1.29%     
==========================================
  Files           8        8              
  Lines        1282     1303      +21     
==========================================
+ Hits         1148     1150       +2     
- Misses        134      153      +19     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@rsenne
rsenne marked this pull request as draft September 20, 2026 21:49
@rsenne
rsenne force-pushed the reactant-device-buffers branch from 7ea1ef5 to 617ba3e Compare September 20, 2026 22:10
ReactantExt copied every compiled AutoReactant call through the host:
Array(x), a new XLA upload, Array(out), then a copy into a new device
array. With CuArray inputs on a CUDA XLA client that is two PCIe transfers
and three allocations per call.

Add two hooks next to needs_host_staging: _host_staging_buffer (CUDAExt
returns pinned memory) and _device_array_from_pointer (CUDAExt wraps a
"cuda" pointer as a non-owning CuArray). ReactantExt builds one callable
per compiled function that owns reusable host stages and copies results
on the device when the XLA buffer can be wrapped, falling back to the host
stage otherwise. Inputs are still uploaded fresh each call: Reactant has no
device-pointer import, and its copyto! into a ConcreteRArray runs a compiled
device copy on top of the upload, so persistent XLA inputs would be slower.

Results are still fresh arrays every call and keep eltype promotions.

Closes #69
@rsenne
rsenne force-pushed the reactant-device-buffers branch from 617ba3e to b061c62 Compare September 20, 2026 22:19
@rsenne rsenne changed the title Reuse Reactant staging buffers and copy device results device-to-device Reuse Reactant staging buffers and copy results on the device Sep 20, 2026
Copy device results through a copy-and-synchronize hook instead of handing back
a non-owning view. The view was read by an async copyto! on CUDA.jl's stream, so
GC.@preserve held the XLA buffer only until the copy was enqueued, not until it
ran. The extension now owns the copy and synchronizes before returning.

Drop the output staging buffer and the extra compiled call that sized it. The
platform is known at compile time from the default client, and the fallback is a
plain host download. Collapse the two arity-specific callables into one
ReactantCall, and drop a try/catch that could not trigger.

Share one StagedArray test double between the CUDA and Reactant test files.

Copilot AI 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.

Copilot review overview

🟢 Approval recommended

No unresolved review issues were identified.

Review effort: Lite
Findings: 1 Medium severity

Open (1)

@rsenne
rsenne requested a balanced review from Copilot September 24, 2026 17:10

Copilot AI 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.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

This branch has not been deployed

No deployments
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.

AutoReactant round-trips every call through the host

2 participants