Skip to content

[SparkInfer] Account persistent PCIe DMA output in KV profiling#76

Open
voipmonitor wants to merge 1 commit into
masterfrom
fix/pcie-dma-persistent-output-20260723
Open

[SparkInfer] Account persistent PCIe DMA output in KV profiling#76
voipmonitor wants to merge 1 commit into
masterfrom
fix/pcie-dma-persistent-output-20260723

Conversation

@voipmonitor

@voipmonitor voipmonitor commented Jul 23, 2026

Copy link
Copy Markdown
Contributor

Summary

  • replace per-call default-output allocation in PCIe DMA all-reduce with one
    reusable, exact-capacity workspace;
  • allocate it lazily on the first default-output dispatch, so vLLM profiling
    observes the persistent allocation before KV-cache sizing;
  • preserve a stable output pointer across eager calls and CUDA graph replay;
  • keep explicit out= calls allocation-free;
  • release the owner reference during close().

The allocation is exactly max_bytes. This PR does not add a mapped tail or
permit any downstream kernel to access bytes outside the logical allocation.

Root cause and scope

A long prefill could be the first call to
PCIeDmaAllReduce.all_reduce(..., out=None) after vLLM had already assigned
remaining memory to KV blocks. The late default-output allocation could then
fail, and allocating a fresh output per call also violates the stable-address
contract required by CUDA graph replay.

Constructor allocation is too early for this integration: the ring exists
before vLLM's initial memory snapshot, so constructor-owned bytes are not
charged by the later profile delta. The first profiled default-output dispatch
is both early enough and visible to KV sizing.

The separately reproduced cuBLAS read-ahead issue is not solved by allocator
padding here. Its consumer path must use a legal GEMM/layout contract; carrying
a 64 KiB tail in a general communication allocator would hide an invalid
consumer and permanently waste memory per pool.

Validation

  • test_pcie_dma_output.py and test_pcie_dma_gpu.py with the two-GPU opt-in:
    18 passed;
  • eager default-output calls reuse one pointer across shapes;
  • explicit-output calls do not instantiate persistent storage;
  • CUDA graph capture/replay passes with changing inputs;
  • all configured compressed wire modes pass on two GPUs;
  • backing storage is asserted to be exactly max_bytes and is released on
    close.

Complete
rtx6kpro#34
E2E validation used current GG, vLLM #172 plus the MRV2 pool-lifecycle
successor to #168, and this PR:

Gate Result
TP4/DCP4/MTP3 NF3, GMU 0.98, graph 64 booted; 563,712 KV tokens; 300,017-token prefill plus 16 decode completed
TP8/DCP2/MTP3 A4 online MXFP8, ring DMA 300,066-token prefill plus 512 decode completed in 65.924 s; server remained healthy

AI assistance disclosure

The implementation review, tests, E2E validation, and this write-up were
prepared with OpenAI Codex assistance and reviewed by the human submitter.

@coderabbitai

coderabbitai Bot commented Jul 23, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

Changes

Persistent PCIe DMA output workspace

Layer / File(s) Summary
Workspace allocation and tensor view
sparkinfer/comm/pcie/pcie_dma.py
Adds lazy persistent uint8 storage and creates validated input-shaped views over it for omitted outputs.
Reuse, validation, and cleanup
sparkinfer/comm/pcie/pcie_dma.py, tests/comm/test_pcie_dma_gpu.py, tests/comm/test_pcie_dma_output.py
Verifies explicit-output handling, pointer reuse across shapes, CUDA graph use, storage validation, extension loading, and release during close.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Suggested reviewers: lukealonso

Sequence Diagram(s)

sequenceDiagram
  participant Caller
  participant PCIeDmaAllReduce
  participant OutputStorage
  participant PersistentOutputView
  Caller->>PCIeDmaAllReduce: all_reduce(inp, out=None)
  PCIeDmaAllReduce->>OutputStorage: _ensure_output_storage()
  OutputStorage-->>PCIeDmaAllReduce: persistent uint8 storage
  PCIeDmaAllReduce->>PersistentOutputView: create output view
  PersistentOutputView-->>Caller: input-shaped output tensor
Loading
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 11.76% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly reflects the main change: accounting for persistent PCIe DMA output during KV profiling.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/pcie-dma-persistent-output-20260723

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot 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.

Actionable comments posted: 2

🧹 Nitpick comments (1)
sparkinfer/comm/pcie/pcie_dma.py (1)

145-160: 🩺 Stability & Availability | 🔵 Trivial | ⚡ Quick win

Validate the actual storage before creating the typed view.

The helper checks size_bytes <= max_bytes, but never verifies that storage actually contains max_bytes bytes. It also views the entire byte tensor, so a storage length not divisible by the target dtype can fail unexpectedly. Validate the storage capacity and create the view from storage[:size_bytes].

Because this relies on PyTorch’s dtype-view rules, verify the behavior against the declared torch 2.12.0 dependency.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@sparkinfer/comm/pcie/pcie_dma.py` around lines 145 - 160, Update
_persistent_output_view to validate that storage contains at least max_bytes
bytes before creating the typed view, while retaining the existing size_bytes
limit check and device/dtype validation. Create the typed view from
storage[:size_bytes] rather than the entire storage tensor, ensuring
non-dtype-aligned excess capacity cannot cause view failures. Confirm the
implementation is compatible with the declared torch 2.12.0 dependency.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@sparkinfer/comm/pcie/pcie_dma.py`:
- Around line 215-220: Update close() cleanup to release the owner reference to
_output_storage after callers and captured graphs have stopped using the ring,
allowing the persistent CUDA allocation to be reclaimed. Preserve the existing
cleanup ordering and behavior for the rest of the ring.
- Around line 380-386: Move the _ensure_output_storage() call inside the `if out
is None` branch in `all_reduce`, and pass its result to
`_persistent_output_view` there. Keep explicit-output calls free of workspace
allocation while preserving the existing default-output behavior.

---

Nitpick comments:
In `@sparkinfer/comm/pcie/pcie_dma.py`:
- Around line 145-160: Update _persistent_output_view to validate that storage
contains at least max_bytes bytes before creating the typed view, while
retaining the existing size_bytes limit check and device/dtype validation.
Create the typed view from storage[:size_bytes] rather than the entire storage
tensor, ensuring non-dtype-aligned excess capacity cannot cause view failures.
Confirm the implementation is compatible with the declared torch 2.12.0
dependency.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 8a0b5371-a849-45e4-994c-f4fdedbc3a1c

📥 Commits

Reviewing files that changed from the base of the PR and between cc9b476 and 8670c57.

📒 Files selected for processing (3)
  • sparkinfer/comm/pcie/pcie_dma.py
  • tests/comm/test_pcie_dma_gpu.py
  • tests/comm/test_pcie_dma_output.py

Comment thread sparkinfer/comm/pcie/pcie_dma.py Outdated
Comment thread sparkinfer/comm/pcie/pcie_dma.py Outdated
@voipmonitor

Copy link
Copy Markdown
Contributor Author

Addressed both workspace-lifetime review findings in 3f4b657:

  • explicit out= calls no longer allocate the persistent default-output workspace;
  • close() releases the persistent output owner reference after IPC cleanup;
  • added CPU lifecycle coverage and a two-GPU explicit/default/CUDA-graph integration assertion.

Validation: 6 passed for test_pcie_dma_output.py, Ruff clean, and test_pcie_dma_all_reduce_eager_and_graph passed on 2 GPUs.

@voipmonitor
voipmonitor force-pushed the fix/pcie-dma-persistent-output-20260723 branch from 3f4b657 to 0c98d6b Compare July 26, 2026 08:21

@coderabbitai coderabbitai Bot 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.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@sparkinfer/comm/pcie/pcie_dma.py`:
- Around line 367-375: Update _ensure_output_storage in
sparkinfer/comm/pcie/pcie_dma.py (lines 367-375) to allocate max_bytes plus the
required 64 KiB workspace tail, while keeping returned output views limited to
the input footprint. Update tests/comm/test_pcie_dma_gpu.py (lines 101-102) to
assert the full backing capacity and verify returned output views exclude the
tail bytes.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 1f75a394-58f4-4295-b8b8-57f7bbad2e98

📥 Commits

Reviewing files that changed from the base of the PR and between 3f4b657 and 0c98d6b.

📒 Files selected for processing (3)
  • sparkinfer/comm/pcie/pcie_dma.py
  • tests/comm/test_pcie_dma_gpu.py
  • tests/comm/test_pcie_dma_output.py

Comment thread sparkinfer/comm/pcie/pcie_dma.py
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.

1 participant