Repository navigation
fix: use decode-phase Mamba2 rows and gate the Mamba2 operator by database mode - #641
Conversation
📝 Summary
Merge Risk:
|
|
@simone-chen this pull request is ready for your review. It is a consumer-side fix in the Rust perf model, and nothing changes on the collector side.
The SILICON readiness rule for Mamba2 is split out to AISIM-2194 and stays out of this pull request. Checks: 61 passed, 8 still running, none failed. Please squash on merge, and trim the readiness sentences of the first commit from the squash message. |
…s a miss Decode queries of the Mamba2 table returned an error on purpose, so decode Mamba2 kernels used the analytic estimate even when rows existed. The error copied a defect of a Python loader that no longer exists. Readiness also accepted Mamba2 operations without a table in every database mode, so a check for data misses could not see them. This change removes the error, so decode rows resolve like context rows. In SILICON mode, readiness now reports a missing or empty Mamba2 table as a miss. The other modes keep the documented analytic fallback for Mamba2. New unit tests cover a decode row, the context path, a decode kernel without rows, and readiness with and without a table. The Rust workspace tests and the embedded Python feature tests pass. Rustfmt passes, and clippy reports no warning on the changed lines. The prediction regression gate reports no blocking regression. Its only differences are decode rows of NemotronH models on the TensorRT-LLM version that ships the Mamba2 table. In the engine-step goldens, the static and disaggregated records of the TensorRT-LLM Nemotron-H-56B case change as intended. This commit does not refresh those goldens. One existing Python test expects op-level readiness for a NemotronH deployment without a Mamba2 table, and it now fails. All other Python unit and golden test results match the base revision. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Signed-off-by: Yiming Liu <yimingl@nvidia.com>
The previous commit lets decode Mamba2 kernels read measured rows instead of the analytic estimate. In the engine-step goldens, this moves only the TensorRT-LLM Nemotron-H-56B smoke case. Its static record changes static_gen and static_total, and its disaggregated record changes disagg_tpot and disagg_request. The totals move by exactly the decode change, while static_ctx and disagg_ttft stay identical. The mixed and aggregated records stay unchanged because the mixed step does not evaluate decode Mamba2 operations. The other NemotronH cases stay unchanged because their backends ship no Mamba2 table. The two refreshed keys now record the fix commit in post_freeze_pins. The compiled-engine and per-op goldens are unchanged. Both parity suites and the numerical sentinels pass. The prediction regression gate shows only the expected decode drift and no blocking regression. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Signed-off-by: Yiming Liu <yimingl@nvidia.com>
Mamba2Op::query ignored the database mode, so SOL and EMPIRICAL modes read measured Mamba2 rows and labelled them silicon. On the base revision, only the context rows leaked this way, because decode rows were never read. Once decode rows became readable, they leaked in the same way. SOL and SOL_FULL now return the analytic SOL without reading the table, as the GEMM, attention, MoE and mHC operators do. Mamba2 has no util-space empirical layer, so EMPIRICAL now also returns the analytic SOL. SILICON and HYBRID keep reading the table and fall back to the analytic SOL on a miss. A new unit test checks the context and decode operations in every database mode. No golden record moves, because no parity case runs a model with Mamba2 rows in SOL or EMPIRICAL mode. Both parity suites, the numerical sentinels and the Rust workspace tests pass. The prediction regression gate is unchanged, because it runs in SILICON mode. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Signed-off-by: Yiming Liu <yimingl@nvidia.com>
The owner decided to move the SILICON readiness rule for Mamba2 into its own issue. This commit restores readiness.rs to its content on the base revision and removes the readiness test. Without the rule, NemotronH models keep op-level readiness on backends without a Mamba2 table, as before this branch. Decode-phase Mamba2 rows stay in use, and the operator still reads rows only in SILICON and HYBRID modes. The other new tests and the golden refresh stay unchanged. The Rust workspace tests and the embedded Python feature tests pass. Rustfmt is clean, and clippy reports no warning on a changed line. The Python unit and golden test results now match the base revision. The test test_nemotron_super_fp8_native_estimation_uses_packaged_moe_data passes again. Both parity suites and the numerical sentinels pass without a golden change. The prediction regression gate shows only the expected decode drift and no blocking regression. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Signed-off-by: Yiming Liu <yimingl@nvidia.com>
d4db1d7 to
a013935
Compare
|
@simone-chen the branch is rebased onto the current main (head a013935) and the CI is green. It is ready for your review. The description has the local evidence: the cargo and embedded suites, the parity run, and the consumer gate on main plus this branch. |
|
@simone-chen one more input for this review, now that a complete op-level dataset for a NemotronH model exists on our side. A coverage gate runs The branch is rebased on main and the CI is green, so the review is the only step left. Thanks for taking a look when you have a moment. |
Brings in ai-dynamo#669, ai-dynamo#670, ai-dynamo#671, ai-dynamo#641 and seven other changes. Two conflicts: - vllm/core.rs: ai-dynamo#671's emit_ready_tokens returns (decode, output_signals) and pricing moved to resolve_pass; the hybrid CPU-tier stores still run right after emission. - whole-forward.md: ai-dynamo#606's cache_layout: unmodeled paragraph is kept before main's rewritten supported-queries paragraph. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: Shahar Mor <smor@nvidia.com>
Why and what changed
Decode-phase (generation) Mamba2 rows were never used.
StateSpaceTable::query_mamba2returned an error for every decode query on purpose. That parity gate copied a defect of a Python loader (load_mamba2_data) that no longer exists, so every decode Mamba2 kernel fell back to its analytic SOL estimate even when measured rows were packaged.Mamba2Op::queryalso ignored the database mode. In SOL and EMPIRICAL modes it read measured rows and labelled them silicon. Before this branch, only the context path leaked this way, because decode rows were never read.crates/core/src/perfmodel/perf_database/state_space.rs: remove the parity gate. Decode queries now resolve like context queries, with the same key lookup on the 1-axis batch curve; the query sequence length feeds SOL only. The comments that described the gate are removed.crates/core/src/perfmodel/operators/mamba.rs:Mamba2Op::querynow follows the database-mode semantics of the GEMM, attention, MoE and mHC operators.crates/core/parity_tests/perfmodel/goldens/engine_step.json: refresh, withpin_goldens.py --refresh, of the two records that the decode change moves. See the golden diff below.Who consumes this: op-level estimation of NemotronH-family models on data that ships a Mamba2 table. Today that is the TensorRT-LLM 1.3.0rc29 tables of eight systems (the default
currentslot since the data campaign of #517); the rc20 tables of the same systems also ship a Mamba2 table. Decode Mamba2 conv1d kernels now use their measured rows in SILICON and HYBRID. In SOL and EMPIRICAL, Mamba2 context and decode now return the analytic SOL on every backend.Readiness rule split: this branch first also made SILICON readiness report a missing Mamba2 table as a data miss. That rule removed default-mode op-level support for NemotronH-family models on backends without a Mamba2 table. By the owner's decision, it moves to AISIM-2194. Commit
a0139351restorescrates/core/src/perfmodel/engine/readiness.rsto its base content and removes that rule's test. The branch history keeps the first commit, whose message still describes the rule; this description supersedes it, so trim the readiness sentences of that commit from the squash message when merging.Review map
Mamba2Op::queryinoperators/mamba.rs;StateSpaceTable::query_mamba2inperf_database/state_space.rs;readiness.rsis identical to the base revision.Evidence
Local runs on the branch head
a0139351, from the repository root unless noted. The branch was rebased on 2026-10-30 onto main7980e950, after the data campaign #517, which moved the default TensorRT-LLM slot to 1.3.0rc29, added the Mamba2 alias table tostate_space.rsand re-pinned the goldens; the rebase kept main's alias lookup next to the removed gate and regenerated the two golden records withpin_goldens.py --refresh. The native extension was rebuilt from the same tree, and the HTTP proxy variables were unset. The base for comparisons is7980e950.cargo test --workspace --no-fail-fast: 2680 passed, 0 failed, 1 ignored. The base has 2677 passed; the difference is the three new tests.cargo test --workspace --features embed-python,replay-bench, with a local Python embedding andAIC_REQUIRE_EMBEDDED_ROUND_TRIP=1: 2772 passed, 0 failed, 1 ignored.cargo fmt --all -- --checkis clean.cargo clippy --workspace --all-targetsreports no warning on a changed line.python -m pytest -q -rx -n 4 -c python/aisimulate/pytest.ini crates/core/parity_tests/perfmodel/test_engine_step_parity.py: 304 passed.test_compile_engine_parity.py: 85 passed.python scripts/prediction_regression/check_prediction_numerics.py --output <file>: 16 cases, 0 failures.python/aisimulate:python -m pytest -q -p no:timeout -n 10 tests/unit tests/golden --ignore=tests/unit/sdk/database/test_moe_dispatch.py. Per-test results are identical to the base revision: 13411 passed and 29 skipped. The same 3 failures occur on both sides and come from the local environment: nosklearn, andcollector.fpm_forwardis not importable from an editable install..github/workflows/prediction-regression-gate.yml(collect_static.py,run_tier2.py,run_silicon.py, thenreport.pyagainst the base snapshot): exit 0. It compared 174437 rows across 29 combos and found DRIFT 685, which is report-only. There is no REGRESSION, STATUS_CHANGE, GAIN, ROWS_ADDED, ROWS_REMOVED or RELABELED row. Tier-1 status totals are equal on both sides, and the tier-2 and silicon snapshots are byte-identical.a0139351after the rebase; the earlier runs were ond4db1d79.d4db1d79, before the rebase; the review ofa0139351is pending.selective_state_update) keeps the analytic estimate. The rc29 tables ship decode SSM rows under the physical labelselective_state_update_flashinfer, and no alias maps the logical name to it yet; that mapping is a follow-up.evaluate_ops_sol_jsonstill rejects Mamba2 for having no SOL decomposition (evaluate_ops_sol_json_rejects_unexported_families).Solinstead ofSilicon.Siliconin EMPIRICAL.scale_factor.Golden diff
engine_step.jsonchanges six leaves in two records of the TensorRT-LLM Nemotron-H-56B smoke case inSMOKE_CASES, whose key isnemotron-h-56b-<system>-trtllm-isl1024-osl2. The diff shows the full key.::staticstatic_gen::staticstatic_totalstatic_genchange::staticstatic_ctx::disaggdisagg_tpot::disaggdisagg_requestdisagg_tpotchange::disaggdisagg_ttftThe two
post_freeze_pinsentries of these records now name the pin commit19067832.Unchanged:
::mixedand::aggrecords of the same case;compile_engine.jsonandper_op.json.This is the intended effect:
generation_mamba_conv1d(causal_conv1d_update) moves from the analytic SOL to its measured row.generation_mamba_ssm(selective_state_update) stays analytic: the rc29 tables ship its rows under the physical labelselective_state_update_flashinfer, which no alias maps to the logical name yet.9f8551ba) nor the readiness split (a0139351) moved a golden: no parity case runs a model with Mamba2 rows in SOL or EMPIRICAL mode, and readiness does not change predictions.To reproduce:
Run the head code against the base
engine_step.json. It fails exactly these two records (302 passed, 2 failed).The refresh ran from a clean tree at
19067832with a matching native build:PYTHONPATH=python/aisimulate/src:python/aisimulate python/aisimulate/.venv/bin/python crates/core/parity_tests/perfmodel/pin_goldens.py --refresh $(python3 -c "import json; c=json.load(open('crates/core/parity_tests/perfmodel/goldens/engine_step.json'))['cases']; print(' '.join(f'{k}::{s}' for k in c if k.startswith('nemotron-h-56b-') and '-trtllm-' in k for s in ('static', 'disagg')))")Prediction gate drift
All 685 drift rows are decode (
gen) rows on the TensorRT-LLM 1.3.0rc29 combos of the eight systems that ship the Mamba2 table. They cover nine NemotronH-family models: Nemotron-3 Nano BF16 and NVFP4, Nemotron-3 Super FP8 and NVFP4, Nemotron-3 Ultra BF16, FP8 and NVFP4, Nemotron-3.5 Lightning NVFP4, and Nemotron-H-56B.652 rows go up and 33 go down. All 33 decreases are on the two systems (L40S and RTX PRO 6000) whose measured decode conv1d rows fall below the bandwidth-only SOL at some batch sizes. That is a data-quality question for the collector, not a property of this code.
Beyond the parity records, these move:
decode_step_latencyruns the full generation graph, so aggregated serving moves in decode-only steps;Mixed prefill-and-decode steps do not move.
Modeling or data provenance
No performance data changes. The decode rows were already packaged in
mamba2_perf.parquet(TensorRT-LLM 1.3.0rc20 and 1.3.0rc29, eight systems); this pull request stops discarding them. Decode rows resolve today only forcausal_conv1d_update; the rc29 decode SSM rows carry a physical label that no alias maps yet. The unit tests use synthetic fixtures. The goldens are regression baselines, not accuracy validation. The silicon-accuracy layer of the gate has no NemotronH reference, so this pull request makes no accuracy claim.Known limitations, unchanged here:
d_model, which AISIM-2185 tracks.view_mamba2(table_view.rs) still drops decode rows, so the engine and the data plane disagree for Mamba2 decode.Tracking
d_modelfallback.Linear: AISIM-2184
🤖 Generated with Claude Code