Skip to content

[None][perf] Default Minimax-m3 to unified draft-target kv manager + change CI test to GQA eagle head - #17835

Closed
zheyuf wants to merge 6 commits into
NVIDIA:feat/m3_with_msafrom
zheyuf:perf/minimax-m3-agg-shared-draft
Closed

[None][perf] Default Minimax-m3 to unified draft-target kv manager + change CI test to GQA eagle head#17835
zheyuf wants to merge 6 commits into
NVIDIA:feat/m3_with_msafrom
zheyuf:perf/minimax-m3-agg-shared-draft

Conversation

@zheyuf

@zheyuf zheyuf commented Aug 17, 2026

Copy link
Copy Markdown
Collaborator

Description

MiniMax-M3 target KV uses P128 pages while the Eagle3 drafter consumes P32 pages. The existing non-owning sub-page view bridges that geometry, so every supported MiniMax-M3 one-model speculative configuration can use the unified target KV manager instead of owning a separate draft cache.

This PR:

  • Makes MiniMax-M3 use unified draft/target KV for all supported draft lengths.
  • Preserves P32 drafter geometry through the non-owning sub-page view.
  • Keeps _should_create_separate_draft_kv_cache generic and identical to the base-branch policy; MiniMax-M3 selects unified KV through _allow_separate_draft_kv_cache = False during executor creation.
  • Fully incorporates [None][test] Switch the MiniMax-M3 Eagle3 CI to the GQA draft head #17514, switching both MiniMax-M3 Eagle3 CI arms to MiniMax-M3-EAGLE3-GQA.
  • Fixes a generic piecewise-multistream exit-ordering race exposed by the GQA drafter.
  • Fixes TP-context to attention-DP-generation transfer of the shared draft layer's grouped-HND representation.
  • Adds a complete-window acceptance gate that detects draft-KV corruption even when target accuracy remains healthy.

test_minimax_m3_unified_draft_view.py is byte-for-byte unchanged from feat/m3_with_msa. test_m3_agg_shared_draft_routing.py and test_auto_multi_stream.py are absent from the final tree and PR diff.

Unified KV policy

_should_create_separate_draft_kv_cache remains the generic base-branch logic:

  • Attention DP returns false because a separate draft KV cache is unsupported.
  • Otherwise it returns should_use_separate_draft_kv_cache(speculative_config).

MiniMax-M3 sets speculative_config._allow_separate_draft_kv_cache = False before manager construction, budget accounting, attention metadata, and worker creation. It therefore uses unified KV for every supported one-model configuration, including draft lengths other than 3. Tree decoding and SA enhancer are not supported MiniMax-M3 modes, so this PR adds no branches for them and does not change other models' policy.

Root causes and fixes

1. Unreturned multistream side effect

inplace_slice_copy records Eagle hidden states by mutating a buffer on an auxiliary CUDA stream and returns no FX value. The original multistream DAG joined operations reachable through returned dataflow, but this void side effect was not reachable from the graph output. The compiled context callable could therefore return while the auxiliary cudaMemcpy2DAsync was still writing, and the graph-external speculative worker could read stale or partially updated hidden states.

The generic fix makes graph exit depend on the latest mutation of every in-place target. The scheduler consequently inserts the event/wait before FX output. Target accuracy can remain healthy during this race because verification rejects bad drafts; acceptance length is the sensitive signal.

2. Grouped-HND draft KV transfer

The shared draft layer has a P128 physical allocation, but its P32 view consumes that storage as four independently head-major token groups: logically [group=4, local_head, 32, head_dim]. In the failing route, TP2 context has two local KV heads while attention-DP generation has four.

The old HND head-mismatch mapper emitted one contiguous head slice per physical K/V buffer, as if the draft bytes were ordinary [local_head, 128, head_dim]. That selects the correct logical heads only in the first P32 group and scrambles subsequent groups. NIXL copied exactly the requested ranges, but the requested ranges were semantically wrong.

The page table now carries a backward-compatible hnd_token_groups field (default 1). MiniMax-M3 marks shared draft K/V as four groups, peer matching validates the value, and the HND mapper emits one descriptor per (layer, K/V, token group). Ordinary HND and NHD paths remain unchanged.

Included #17514 and base-branch fixes

Commit a4c7a91e is patch-equivalent to #17514 head af6ddb12: both Eagle3 CI arms use the GQA drafter. #17514 remains open, but this PR supersedes it, so only #17835 needs to merge.

The plain test_nvfp4[use_msa=True-eval_mode=inferencemax] case has no speculative model and therefore has no drafter head to switch.

#17656, including the blocks_in_primary_pool correction, is already in feat/m3_with_msa. This branch is based on it and does not duplicate that fix. A direct A/B showed the corrected bound modestly helps acceptance; it did not cause the regression.

Acceptance and accuracy evidence

All acceptance rows use the same 200-question chat-GSM8K probe, greedy decoding, and 512 generated tokens.

route / experiment acceptance rate mean acceptance length accuracy
aggregated formal (Slurm 766375) 0.834 3.503 95.679
TP context -> ADP generation, formal fixed PR (767807) 0.842 3.525 95.299
fixed grouped-HND mapper, isolated A/B (767761) 0.82884 3.48652 skipped
old contiguous-HND mapper, same A/B (767762) 0.780 3.339 skipped
ADP context -> ADP generation control (767763) 0.830 3.490 skipped
final bounded-stat configuration (767842) 0.83178 3.49535 skipped

The ADP->ADP control is indistinguishable from the fixed TP->ADP route, so the TP/ADP numerical topology boundary is not a systematic disaggregated-acceptance deficit.

For a real 249-token prompt, the fixed TP-context pre-send draft-layer KV and ADP-generation post-receive KV were reconstructed by logical layer/head. All eight layer-60 tensors (K/V x four heads) were bitwise equal: identical SHA-256, exact fraction 1.0, and max absolute difference 0. The same proof passed for ADP->ADP. TP-context and ADP-context arithmetic does produce expected numerical differences for an individual prompt, but transfer before/after is exact and the full-workload control above shows no systematic AL penalty.

A 64-token versus 1024-token generation budget produced bitwise-identical prompt traces and comparable complete-window acceptance, eliminating generation KV capacity as the cause.

CI calibration

The default /metrics buffers retain only the latest 1000 iteration records. Under attention DP that is roughly the tail 500 engine iterations and can bias the sample toward whichever requests finish last.

The test now:

  • enables a bounded 5000-record engine and OpenAI-server window (full 200-prompt runs used at most 2966 records);
  • drains stats after the accuracy evaluation;
  • waits for the background collector's 0.5-second queue drain before clearing and reading the HTTP snapshot;
  • evaluates the complete probe window; and
  • gates both aggregated and disaggregated arms at acceptance rate > 0.80 and mean acceptance length > 3.4.

The old mapper fails both floors (0.780 / 3.339); all fixed complete-window runs pass with clear headroom.

Performance evidence

The strict one-hour TP4/C35 paired comparison changed only separate versus shared draft-KV lifecycle ownership:

arm interactivity TPS/user throughput TPS/GPU TTFT P50 TTFT P90 success/error
separate P32 125.6980 52,188.89 2477.26 ms 4059.93 ms 4594/2
shared P32 138.4837 53,742.90 2269.89 ms 3795.30 ms 4677/2
shared delta +10.1717% +2.9777% -8.3711% -6.5180% -

Both arms passed strict postprocessing with submission_valid=true, was_cancelled=false, zero runtime fatal signatures, zero context overflow, and zero OSL mismatch. The full optimized AgentX sweep completed all 14 one-hour TP2, TP4, and TP8 points with strict QC; 12 of 14 points lie on the new-stack Pareto envelope.

Validation

  • Formal disaggregated + attention-DP InferenceMAX test: PASS, accuracy 95.299, acceptance 0.842 / 3.525 (Slurm 767807).
  • Final bounded-window probe: PASS, 2712 records, 14834 speculative iterations, acceptance 0.83178 / 3.49535 (767842).
  • Exact fixed/old mapper A/B: fixed 0.82884 / 3.48652; old 0.780 / 3.339 and correctly rejected.
  • Focused disaggregation unit suite: 92 passed (767848).
  • Full pre-commit suite passed: isort, YAPF, autoflake, codespell, Ruff lint/format, legacy lint, and repository policy checks.
  • Python compilation, git diff --check, DCO sign-offs, and a conflict-free merge-tree against the latest feat/m3_with_msa passed.

PR checklist

@zheyuf
zheyuf force-pushed the perf/minimax-m3-agg-shared-draft branch 2 times, most recently from c9593c9 to c1aa316 Compare August 18, 2026 05:32
@zheyuf zheyuf changed the title [None][perf] Share MiniMax-M3 draft KV in aggregated serving [None][perf] Change Minimax-m3 to unified draft-target kv manager by default Aug 18, 2026
@zheyuf zheyuf changed the title [None][perf] Change Minimax-m3 to unified draft-target kv manager by default [None][perf] Default Minimax-m3 to unified draft-target kv manager + change CI test to GQA eagle head Aug 18, 2026
zheyuf added 2 commits August 17, 2026 22:55
Signed-off-by: Zheyu Fu <zheyuf@nvidia.com>
Both arms now run Inferact/MiniMax-M3-EAGLE3-GQA, the head production
is moving to: same training data as the MHA head with the drafter's
attention changed from 64 to 4 KV heads, so its draft KV cache is 16x
smaller and matches the target's head count.

Measured on this branch (4-GPU node, InferenceMAX eval + the shared
chat-GSM8K acceptance probe):

  aggregated  (separate draft manager)  3.515 / 0.838, accuracy 95.45
  disaggregated (unified sub-page view) 3.369 / 0.790, accuracy 95.15
                                        3.395 / 0.798, accuracy 95.45

The aggregated figure is indistinguishable from the MHA card's GSM8K
reference (3.518 / 0.839), which is why that reference stands in for
the GQA card's missing GSM8K entry; the two cards agree on the
benchmark they do share (MT-Bench 2.698 vs 2.668). The disaggregated
arm measures ~0.14 lower, so the rate floor drops 0.78 -> 0.76 for
headroom while the length floor stays at 3.3 — still between the
measured healthy range and the 3.33 plateau a drafter-KV transfer
regression produced on this workload.

Signed-off-by: Zheyu Fu <zheyuf@nvidia.com>
(cherry picked from commit af6ddb1)
@zheyuf
zheyuf force-pushed the perf/minimax-m3-agg-shared-draft branch from c1aa316 to a4c7a91 Compare August 18, 2026 05:56
zheyuf added 4 commits August 18, 2026 10:36
Make graph exit depend on the latest mutation of every in-place target, including void side effects that are not reachable from the FX return value. This prevents an auxiliary-stream Eagle hidden-state capture from racing the graph-external speculative worker.

Add a structural scheduler test covering the event and wait inserted before graph output.

Signed-off-by: Zheyu Fu <zheyuf@nvidia.com>
Signed-off-by: Zheyu Fu <zheyuf@nvidia.com>
Signed-off-by: Zheyu Fu <zheyuf@nvidia.com>
Signed-off-by: Zheyu Fu <zheyuf@nvidia.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.

1 participant