Skip to content

moe: stabilize Trellis arena memory profiling - #92

Merged
lukealonso merged 3 commits into
masterfrom
fix/trellis-stable-profile-20260730
Jul 30, 2026
Merged

moe: stabilize Trellis arena memory profiling#92
lukealonso merged 3 commits into
masterfrom
fix/trellis-stable-profile-20260730

Conversation

@voipmonitor

@voipmonitor voipmonitor commented Jul 30, 2026

Copy link
Copy Markdown
Contributor

Problem

The unified Trellis fused_moe path used the generic W4A16 compile bucket for its caller-owned arena and left several fixed launch variants to first use. For a 3,072-token EXL3 prefill plan this rounded the arena to 4,096 rows, reserving about 320 MiB/rank that execution could not use. First-use compilation during vLLM profiling also produced non-repeatable rank-local activation peaks and therefore non-repeatable distributed KV capacity.

Changes

  • Preserve exact fixed capacity for exl3_trellis_mcg scratch plans; generic W4A16 plans retain compile bucketing.
  • Compile fixed Trellis fused-MoE and top-k-sum variants during plan creation.
  • Prewarm mapped and unmapped route packing before memory profiling.
  • Retain strong references to launch objects but leave runtime binding unresolved, preserving the faster live-M resolver used by the unified API.
  • Add exact-capacity and prewarm/dispatch contract tests.

The original Trellis implementation from closed #90 is already present on master; this PR contains only the follow-up profiling and capacity fix.

Validation

  • SparkInfer Trellis regression set: 124 passed
  • Paired vLLM worker tests: 3 passed
  • TP4/DCP4/MTP0, three cold starts: 834,560 KV tokens every time, 1.62 GiB activation peak on every rank
  • MTP0 decode: 48.00 and 48.58 tok/s, no errors
  • TP4/DCP4/MTP3: 485,888 KV tokens, 101.02 tok/s, acceptance 0.6847
  • git diff --check: clean

Paired vLLM PRs: local-inference-lab/vllm#190 and local-inference-lab/vllm#198.

Summary by CodeRabbit

  • Performance Improvements

    • Enhanced Trellis FP4 (W4A16, full-rotation) planning by precompiling and caching fused and top‑k-sum launches for reuse.
    • Improved W4A16 workspace/token capacity handling for more consistent scratch-plan sizing.
    • Reduced unnecessary runtime dispatch during scratch-plan binding by using preplanned launches.
  • Bug Fixes

    • Tightened fixed-capacity workspace sizing to match expected Trellis geometry and prevent under-provisioning.
  • Tests

    • Added CUDA Trellis coverage for launch planning and scratch-plan prewarming, including validation across expected launch and mapping variants.

@coderabbitai

coderabbitai Bot commented Jul 30, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: ee425d49-2e25-4bf8-ba37-f8bb0e482293

📥 Commits

Reviewing files that changed from the base of the PR and between de04125 and 06032ce.

📒 Files selected for processing (1)
  • tests/moe/test_tp_moe_scratch_bindings.py

📝 Walkthrough

Walkthrough

Trellis W4A16 scratch planning now disables source-incompatible token bucketing, precompiles full-rotation fused and top-k-sum launches, retains them on TPMoEScratchPlan, and preserves unset runtime dispatch values during binding. Tests cover capacity, launch coverage, and retention.

Changes

Trellis W4A16 planning

Layer / File(s) Summary
Trellis arena capacity
sparkinfer/moe/fused_moe/_impl.py, tests/moe/test_tp_moe_scratch_bindings.py
W4A16 token bucketing is disabled for exl3_trellis_mcg, and fixed Trellis capacity and workspace bounds are tested.
Full-rotation launch prewarming
sparkinfer/moe/fused_moe/_impl.py, tests/moe/test_tp_moe_scratch_bindings.py
Planning validates capture state, route geometry, and Trellis formats, then compiles fixed fused/top-k-sum launches and validates their coverage.
Scratch-plan launch retention and binding
sparkinfer/moe/fused_moe/_impl.py, tests/moe/test_tp_moe_scratch_bindings.py
Prewarmed launches are retained on TPMoEScratchPlan; FP4 binding construction accepts launch objects while eager binding passes None, as tested.

Estimated code review effort: 4 (Complex) | ~45 minutes

Sequence Diagram(s)

sequenceDiagram
  participant plan_tp_moe_scratch
  participant _plan_full_rotation_w4a16_launches
  participant TrellisKernels
  participant _build_tp_moe_fp4_binding_from_views
  plan_tp_moe_scratch->>_plan_full_rotation_w4a16_launches: plan fixed-capacity Trellis launches
  _plan_full_rotation_w4a16_launches->>TrellisKernels: compile fused and top-k-sum launches
  TrellisKernels-->>plan_tp_moe_scratch: return launch objects
  plan_tp_moe_scratch->>_build_tp_moe_fp4_binding_from_views: build binding with fused_launch=None and topk_sum_launch=None
Loading

Possibly related PRs

Suggested reviewers: brandonmmusic-max

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title is concise and matches the main change: stabilizing Trellis arena memory profiling.
Linked Issues check ✅ Passed The changes align with #90 by preserving Trellis W4A16 planning, unified scratch/bind flow, route packing, and graph-safe launch behavior.
Out of Scope Changes check ✅ Passed No clear out-of-scope changes are present; the code and tests stay focused on Trellis planning, launch prewarming, and scratch binding.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
✨ 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/trellis-stable-profile-20260730

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.

@voipmonitor

Copy link
Copy Markdown
Contributor Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jul 30, 2026

Copy link
Copy Markdown
Contributor
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@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 (3)
tests/moe/test_tp_moe_scratch_bindings.py (2)

557-561: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Bound the arena size from both sides.

core_workspace_nbytes < 1060 MiB is a one-sided magic threshold: an accidental under-sizing of the Trellis arena also satisfies it, so the assertion can't distinguish "bucketing correctly disabled" from "capacity regressed". Add a lower bound (or assert equality against the size a 3072-token plan should produce) so the exact-capacity contract is actually pinned.

💚 Suggested tightening
     assert plan.layout.route_workspace_nbytes == 0
-    assert plan.layout.core_workspace_nbytes < 1060 * (1 << 20)
+    # Must land on the exact 3072-token capacity, not the 4096 compile bucket
+    # (~1060 MiB) and not an under-sized arena.
+    assert 1000 * (1 << 20) < plan.layout.core_workspace_nbytes < 1060 * (1 << 20)
     assert plan.layout.total_nbytes == plan.layout.core_workspace_nbytes
🤖 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 `@tests/moe/test_tp_moe_scratch_bindings.py` around lines 557 - 561, Add a
lower-bound assertion for plan.layout.core_workspace_nbytes in this test, using
the expected minimum capacity for the 3072-token plan while retaining the
existing upper bound. This should verify both that Trellis bucketing is disabled
and that the arena is not accidentally undersized.

574-578: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

The real launch planner is left untested.

Stubbing _plan_full_rotation_w4a16_launches is right for isolating the retention/dispatch contract, but it means the ~190 lines of new compile/prewarm logic have no direct coverage — only its CPU early-return is touched (via the sibling test). A prewarm miss fails silently as a memory-profiling regression, not an exception, so a GPU-gated test asserting the compiled fused token-count set (range(1, capacity+1) for capacity ≤ 32 vs. a single capacity entry above it) and the four (ids_dtype, mapped) top-k-sum variants would be worth adding.

Want me to draft that GPU-gated test?

🤖 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 `@tests/moe/test_tp_moe_scratch_bindings.py` around lines 574 - 578, Add a
GPU-gated test that exercises the real _plan_full_rotation_w4a16_launches
planner instead of monkeypatching it, and verify the compiled fused token-count
set is range(1, capacity+1) for capacities up to 32 or only the capacity entry
above 32. Also assert compilation/prewarm covers all four (ids_dtype, mapped)
top-k-sum variants, while preserving the existing isolated retention/dispatch
test.
sparkinfer/moe/fused_moe/_impl.py (1)

6198-6210: 🗄️ Data Integrity & Integration | 🔵 Trivial | ⚡ Quick win

Prefer failing loudly over re-deriving block_size_m when the plan omits it.

core_plan.route_block_size_m or select_route_block_size_m(...) re-derives a value the arena was already sized with. If the plan's block size is ever absent/zero, the fallback can choose a different block size than the one used to size block_expert_ids / packed_route_indices, and that mismatched capacity_m_blocks is then baked into the compiled launch's max_m_blocks grid contract — a silent geometry divergence rather than an error.

♻️ Suggested change
-    block_size_m = core_plan.route_block_size_m or select_route_block_size_m(
-        capacity_tokens,
-        core_plan.num_topk,
-        core_plan.route_E,
-    )
+    if core_plan.route_block_size_m:
+        block_size_m = int(core_plan.route_block_size_m)
+    else:
+        # No planned route geometry: derive it once, identically to the arena.
+        block_size_m = select_route_block_size_m(
+            capacity_tokens,
+            core_plan.num_topk,
+            core_plan.route_E,
+        )
🤖 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/moe/fused_moe/_impl.py` around lines 6198 - 6210, Update the
block-size selection near capacity_m_blocks to require a valid nonzero
core_plan.route_block_size_m and fail immediately when it is absent or zero;
remove the select_route_block_size_m fallback. Continue using the validated plan
block size for max_packed_route_slots and capacity_m_blocks so the compiled
launch geometry matches the arena sizing.
🤖 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/moe/fused_moe/_impl.py`:
- Around line 6287-6288: Move the torch.cuda.is_current_stream_capturing() guard
to the beginning of the route-pack prewarm/planning function, before any
compilation or other CUDA-visible work. Preserve the existing RuntimeError
message and ensure the function exits immediately whenever capture is active.
- Around line 6247-6261: The Trellis prewarm configuration must use the same
normalized W4a16 scale format, weight layout, and w13 layout as the runtime
path. Update the prewarm code around the visible trellis settings to derive
these values from the plan or prepared_payload through
_normalize_w4a16_scale_format and _normalize_w4a16_weight_layout, or explicitly
validate the required Trellis contract before prewarming so mismatches fail
during planning rather than producing divergent cache keys.

---

Nitpick comments:
In `@sparkinfer/moe/fused_moe/_impl.py`:
- Around line 6198-6210: Update the block-size selection near capacity_m_blocks
to require a valid nonzero core_plan.route_block_size_m and fail immediately
when it is absent or zero; remove the select_route_block_size_m fallback.
Continue using the validated plan block size for max_packed_route_slots and
capacity_m_blocks so the compiled launch geometry matches the arena sizing.

In `@tests/moe/test_tp_moe_scratch_bindings.py`:
- Around line 557-561: Add a lower-bound assertion for
plan.layout.core_workspace_nbytes in this test, using the expected minimum
capacity for the 3072-token plan while retaining the existing upper bound. This
should verify both that Trellis bucketing is disabled and that the arena is not
accidentally undersized.
- Around line 574-578: Add a GPU-gated test that exercises the real
_plan_full_rotation_w4a16_launches planner instead of monkeypatching it, and
verify the compiled fused token-count set is range(1, capacity+1) for capacities
up to 32 or only the capacity entry above 32. Also assert compilation/prewarm
covers all four (ids_dtype, mapped) top-k-sum variants, while preserving the
existing isolated retention/dispatch test.
🪄 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: 2ba3e8ac-003b-45e7-969a-5a86c0c528f3

📥 Commits

Reviewing files that changed from the base of the PR and between 36cade0 and 394b9b0.

📒 Files selected for processing (2)
  • sparkinfer/moe/fused_moe/_impl.py
  • tests/moe/test_tp_moe_scratch_bindings.py

Comment thread sparkinfer/moe/fused_moe/_impl.py
Comment thread sparkinfer/moe/fused_moe/_impl.py Outdated
@voipmonitor

Copy link
Copy Markdown
Contributor Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jul 30, 2026

Copy link
Copy Markdown
Contributor
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

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