[None][feat] DSv4 follow-up: runtime KV and cache foundations#15633
Conversation
b07c107 to
6746a1f
Compare
📝 WalkthroughWalkthroughThe PR updates KV-cache stats, executor stats limits and buffering, request token transport, SWA scratch reuse, disaggregation mapping, and serving telemetry. ChangesKV-cache Stats Reporting
Executor Stats Limits and Buffering
Request Token Serialization
SWA Scratch Reuse and DeepSeek V4
Disaggregation Mapping and Transceiver
Serving Telemetry
Estimated code review effort🎯 5 (Critical) | ⏱️ ~120 minutes Possibly related PRs
Suggested labels
Suggested reviewers
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
Actionable comments posted: 9
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (2)
tensorrt_llm/serve/openai_server.py (1)
940-940: 🩺 Stability & Availability | 🟠 Major | ⚡ Quick winReturn an empty metrics payload for VisualGen before draining stats.
register_visual_gen_routes()exposes/metrics, and_get_iteration_stats_buffer_maxlen()handles VisualGen, butget_iteration_stats()still eventually callsself.generator.get_stats_async(...). The providedVisualGenclass does not expose that method, so VisualGen/metricswill 500.Suggested change
async def get_iteration_stats(self) -> JSONResponse: + if isinstance(self.generator, VisualGen): + return JSONResponse(content=[]) + # When the background collector loop is active it is the sole🤖 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 `@tensorrt_llm/serve/openai_server.py` at line 940, The get_iteration_stats path still falls through to self.generator.get_stats_async even for VisualGen, which causes /metrics to fail because VisualGen lacks that method. Update get_iteration_stats in openai_server.py to detect the VisualGen generator type, return an empty metrics payload for that case, and only drain or fetch stats for generators that actually implement get_stats_async; use the existing VisualGen handling in register_visual_gen_routes and _get_iteration_stats_buffer_maxlen as the reference points.tensorrt_llm/_torch/pyexecutor/py_executor.py (1)
1815-1839: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick winPreserve the
max_stats_len == 0disabled contract and exact cap.
max_stats_len == 0still appends one stats record in the legacy path and one per-rank iteration in the ADP path. For positive caps, the legacy path also trims before append with>, so it retainsmax_stats_len + 1records. This breaks the stated stats limit contract.Proposed fix
if self.dist.tp_rank == 0: with self.stats_lock: + if self.max_stats_len == 0: + return # Wrap as ("per_rank_dict", dict) so the serializer can # distinguish from the legacy (stats, req_stats, kv) tuple. @@ # [7] gpu_forward_time_ms: Optional[float] with self.stats_lock: - if (not _stats_buffer_is_unbounded(self.max_stats_len) - and len(self.stats) > self.max_stats_len): - self.stats.pop(0) + if self.max_stats_len == 0: + return self.stats.append( (stats, req_stats, kv_iter_stats, attention_dp_rank, host_step_time_ms, prev_device_step_time_ms, scheduler_mode, gpu_forward_time_ms)) + if not _stats_buffer_is_unbounded(self.max_stats_len): + overflow = max(0, len(self.stats) - self.max_stats_len) + if overflow: + del self.stats[:overflow]🤖 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 `@tensorrt_llm/_torch/pyexecutor/py_executor.py` around lines 1815 - 1839, The stats buffering logic in py_executor.py is violating the max_stats_len contract in both the legacy path and the per-rank iteration path. Update the checks around self.stats handling so max_stats_len == 0 truly disables storage and no records are appended, and for positive limits enforce an exact cap before appending (use the existing _stats_buffer_is_unbounded helper, the self.stats_lock section, and the gathered/per-rank append loop as the key places to adjust). Make the legacy trim condition and the ADP overflow trimming consistent so the buffer never exceeds max_stats_len.
🧹 Nitpick comments (2)
tensorrt_llm/runtime/kv_cache_manager_v2/_core/_kv_cache_manager.py (1)
463-562: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winConsolidate the duplicated
PoolGroupPeakBlockStats-from-statistics construction.The same
make_typed(lambda pool_group_index: PoolGroupPeakBlockStats(available=..., unavailable=..., evictable=...), self._storage.num_pool_groups)block is repeated three times: in_current_block_stats_by_cache_level.collect(469-477), in the non-Nonebranch of_reset_iteration_peak_num_blocks(487-495), and inget_and_reset_iteration_peak_block_stats(546-559). Extracting a single helper that maps acache_levelto its per-pool-groupPoolGroupPeakBlockStatslist would remove the duplication and keep the three call sites in sync if the stat fields ever change.♻️ Sketch
+ def _pool_group_block_stats( + self, cache_level: CacheLevel + ) -> TypedIndexList[PoolGroupIndex, PoolGroupPeakBlockStats]: + stats_by_pool_group = self._storage.get_statistics(cache_level) + return make_typed( + lambda pool_group_index: PoolGroupPeakBlockStats( + available=stats_by_pool_group[pool_group_index].available, + unavailable=stats_by_pool_group[pool_group_index].unavailable, + evictable=stats_by_pool_group[pool_group_index].evictable, + ), + self._storage.num_pool_groups, + )
_current_block_stats_by_cache_level,_reset_iteration_peak_num_blocks, andget_and_reset_iteration_peak_block_statscan then reuse it.As per coding guidelines (DRY in
CODING_GUIDELINES.md).🤖 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 `@tensorrt_llm/runtime/kv_cache_manager_v2/_core/_kv_cache_manager.py` around lines 463 - 562, The same PoolGroupPeakBlockStats construction from get_statistics is duplicated in _current_block_stats_by_cache_level, _reset_iteration_peak_num_blocks, and get_and_reset_iteration_peak_block_stats. Add a small helper on KVCacheManagerV2 to build the per-cache-level TypedIndexList[PoolGroupIndex, PoolGroupPeakBlockStats] from a cache_level, then have those three methods call it so the mapping logic stays in one place and remains consistent if the tracked fields change.Source: Coding guidelines
tensorrt_llm/executor/request.py (1)
203-203: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winAdd return/type annotations to the new helpers.
These new methods are unannotated; add annotations such as
-> list[int] | list[list[int]] | None,-> None,-> object, and-> dict[str, object]as appropriate. As per coding guidelines, “Always annotate functions with return types.” Based on learnings, Python 3.10+ features can be used throughout the codebase.Also applies to: 213-213, 217-217, 225-225, 239-239
🤖 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 `@tensorrt_llm/executor/request.py` at line 203, The new helper methods/properties in Request are missing return annotations, so add explicit return types to each one to match the coding guidelines. Update prompt_token_ids and the other newly added helpers to use precise Python 3.10+ annotations such as list[int] | list[list[int]] | None, None, object, or dict[str, object] depending on what each accessor returns. Keep the signatures consistent across the new accessors so the Request API remains fully typed.Sources: Coding guidelines, Learnings
🤖 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 `@cpp/tensorrt_llm/executor/executorImpl.cpp`:
- Around line 1935-1945: The bounded stats trimming in `appendMultipleIterStats`
can call `pop_front()` more times than `mIterationStats` currently holds when
`currentIterStatsVec` alone exceeds the cap. Update the removal logic to clamp
the number of pops to the existing deque size before draining `mIterationStats`,
and apply the same fix in `appendMultipleRequestStats` so both batch-append
paths avoid empty-deque access.
In `@cpp/tensorrt_llm/nanobind/executor/request.cpp`:
- Around line 634-637: The request deserialization in request.cpp around the
inputTokenIdsBytes to VecTokens conversion should validate that the byte buffer
size is evenly divisible by sizeof(VecTokens::value_type) before calling
std::memcpy. If the size is invalid, reject the state or throw an error in the
same requestGetstate/request restore path; otherwise compute the element count
and copy only the validated number of bytes into inputTokenIds.
In `@tensorrt_llm/_torch/pyexecutor/model_engine.py`:
- Around line 3898-3899: The cached_kv_tokens stat is only updated in
_prepare_tp_inputs(), so incremental-update batches can leave it stale. Update
_prepare_incremental_update_metadata() in model_engine.py to assign
self.iter_states['cached_kv_tokens'] from the current num_cached_tokens_per_seq,
keeping the exported value in sync for both incremental-update flows.
In `@tensorrt_llm/_torch/pyexecutor/py_executor.py`:
- Around line 2735-2789: Make the benchmark stall abort decision collective
across ADP ranks in the py_executor logic that checks benchmark fill progress.
The current timeout in the disagg benchmark path uses per-rank `time.time()` and
`_bench_disagg_last_gen_count_time`, which can make some ranks call
`_handle_errors()` and enter different collectives earlier than others. Update
the `is_benchmark_disagg` / `_benchmark_fill_phase_active` branch so all ranks
agree on whether the stall timeout has expired, and reset or suppress the stall
timer whenever any rank still reports fitting work via the `tp_allgather`
result. Keep the decision synchronized around `tp_allgather`, `total_ready_gen`,
`any_rank_has_fitting`, and `_handle_errors()` so no rank can diverge into abort
handling alone.
In `@tensorrt_llm/_torch/pyexecutor/request_utils.py`:
- Around line 83-105: The diagnostic helper in request_utils is using broad
Exception handlers in the state counting and kv_cache_manager info path, which
should be narrowed to the expected failure types instead of silently swallowing
everything. Update the logic around LlmRequestState(req.state_value).name,
idx_mapper.num_free_slots()/size(), and kv_cache_manager.get_num_free_blocks()
to catch only the specific enum/accessor errors you expect, and when a field is
unavailable, record a clear fallback marker in the output rather than ignoring
it. Keep the best-effort behavior, but avoid generic Exception in these branches
to satisfy the repository’s exception-handling guidelines and Ruff findings.
In `@tensorrt_llm/executor/base_worker.py`:
- Around line 457-461: The prompt token selection in base_worker.py is
incorrectly preferring _prompt_token_ids_i32 even after request.prompt_token_ids
has been materialized and may have been mutated in place. Update the logic
around the prompt_token_ids assignment in the request handling path so it only
uses the packed buffer when request._prompt_token_ids is still None, and
otherwise always uses the current list value from request.prompt_token_ids. Keep
the behavior consistent with prompt_adapter_request checks and the existing
request field names.
In `@tensorrt_llm/serve/openai_server.py`:
- Around line 948-950: The `/metrics` path in the background stats flow can
block while holding `_iteration_stats_lock` because
`_drain_iteration_stats_to_sinks_unlocked` is called with a 2-second timeout
even when the collector is already running. Update the metrics handling in
`openai_server.py` so the on-demand drain is non-blocking in background mode, or
skip draining entirely and read directly from `_iteration_stats_buffer`/the tee
buffer instead. Keep the change localized around `_iteration_stats_lock`,
`_drain_iteration_stats_to_sinks_unlocked`, and the `/metrics` stats collection
path.
In `@tests/unittest/_torch/executor/test_kv_cache_v2_scheduler.py`:
- Line 168: The resize callback setup in KV cache scheduler tests needs to
accept the new history_length keyword argument consistently. Update the custom
failure-path callback in test_kv_cache_v2_scheduler alongside the existing
resize_context_fn fallback so both signatures can receive history_length without
TypeError. Make sure the test cases that exercise skip behavior still use
resize_context on the same mocked manager path and validate both the positive
and failure paths after the callback signature change.
In `@tests/unittest/llmapi/apps/test_openai_server_iteration_stats.py`:
- Around line 88-96: Add a test in this file to cover the VisualGen-specific
branch of `get_iteration_stats` in the OpenAI server path: assert that a
VisualGen-style server returns an empty list from `/metrics` and does not invoke
`get_stats_async()`. Use the existing
`test_metrics_endpoint_reads_queue_without_background_buffer` style and the
`server.get_iteration_stats()` / `metrics_collector` setup to locate the right
branch, and keep the assertion focused on VisualGen behavior rather than the
buffered/unbuffered LLM drain cases.
---
Outside diff comments:
In `@tensorrt_llm/_torch/pyexecutor/py_executor.py`:
- Around line 1815-1839: The stats buffering logic in py_executor.py is
violating the max_stats_len contract in both the legacy path and the per-rank
iteration path. Update the checks around self.stats handling so max_stats_len ==
0 truly disables storage and no records are appended, and for positive limits
enforce an exact cap before appending (use the existing
_stats_buffer_is_unbounded helper, the self.stats_lock section, and the
gathered/per-rank append loop as the key places to adjust). Make the legacy trim
condition and the ADP overflow trimming consistent so the buffer never exceeds
max_stats_len.
In `@tensorrt_llm/serve/openai_server.py`:
- Line 940: The get_iteration_stats path still falls through to
self.generator.get_stats_async even for VisualGen, which causes /metrics to fail
because VisualGen lacks that method. Update get_iteration_stats in
openai_server.py to detect the VisualGen generator type, return an empty metrics
payload for that case, and only drain or fetch stats for generators that
actually implement get_stats_async; use the existing VisualGen handling in
register_visual_gen_routes and _get_iteration_stats_buffer_maxlen as the
reference points.
---
Nitpick comments:
In `@tensorrt_llm/executor/request.py`:
- Line 203: The new helper methods/properties in Request are missing return
annotations, so add explicit return types to each one to match the coding
guidelines. Update prompt_token_ids and the other newly added helpers to use
precise Python 3.10+ annotations such as list[int] | list[list[int]] | None,
None, object, or dict[str, object] depending on what each accessor returns. Keep
the signatures consistent across the new accessors so the Request API remains
fully typed.
In `@tensorrt_llm/runtime/kv_cache_manager_v2/_core/_kv_cache_manager.py`:
- Around line 463-562: The same PoolGroupPeakBlockStats construction from
get_statistics is duplicated in _current_block_stats_by_cache_level,
_reset_iteration_peak_num_blocks, and get_and_reset_iteration_peak_block_stats.
Add a small helper on KVCacheManagerV2 to build the per-cache-level
TypedIndexList[PoolGroupIndex, PoolGroupPeakBlockStats] from a cache_level, then
have those three methods call it so the mapping logic stays in one place and
remains consistent if the tracked fields change.
🪄 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: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Enterprise
Run ID: f27f2760-20a5-4b3c-8bf1-3bd41e89a424
📒 Files selected for processing (38)
cpp/include/tensorrt_llm/batch_manager/kvCacheManager.hcpp/include/tensorrt_llm/executor/executor.hcpp/tensorrt_llm/executor/executorConfig.cppcpp/tensorrt_llm/executor/executorImpl.cppcpp/tensorrt_llm/executor/executorImpl.hcpp/tensorrt_llm/nanobind/batch_manager/kvCacheManager.cppcpp/tensorrt_llm/nanobind/executor/request.cppcpp/tests/unit_tests/executor/executorConfigTest.cpptensorrt_llm/_torch/attention_backend/interface.pytensorrt_llm/_torch/attention_backend/trtllm.pytensorrt_llm/_torch/pyexecutor/_util.pytensorrt_llm/_torch/pyexecutor/kv_cache_manager_v2.pytensorrt_llm/_torch/pyexecutor/kv_cache_stats.pytensorrt_llm/_torch/pyexecutor/model_engine.pytensorrt_llm/_torch/pyexecutor/py_executor.pytensorrt_llm/_torch/pyexecutor/request_utils.pytensorrt_llm/_torch/pyexecutor/scheduler/scheduler_v2.pytensorrt_llm/_torch/pyexecutor/trace_log_utils.pytensorrt_llm/executor/base_worker.pytensorrt_llm/executor/request.pytensorrt_llm/llmapi/llm_args.pytensorrt_llm/runtime/kv_cache_manager_v2/__init__.pytensorrt_llm/runtime/kv_cache_manager_v2/__init__.pyitensorrt_llm/runtime/kv_cache_manager_v2/_core/__init__.pytensorrt_llm/runtime/kv_cache_manager_v2/_core/_kv_cache.pytensorrt_llm/runtime/kv_cache_manager_v2/_core/_kv_cache_manager.pytensorrt_llm/runtime/kv_cache_manager_v2/_page.pytensorrt_llm/runtime/kv_cache_manager_v2/_stats.pytensorrt_llm/runtime/kv_cache_manager_v2/_storage_manager.pytensorrt_llm/serve/openai_server.pytensorrt_llm/serve/perf_metrics.pytests/unittest/_torch/executor/test_kv_cache_v2_scheduler.pytests/unittest/bindings/test_executor_bindings.pytests/unittest/executor/test_stats_serializer.pytests/unittest/kv_cache_manager_v2_tests/test_kv_cache_stats_behavior.pytests/unittest/llmapi/apps/test_disagg_perf_metrics_collector.pytests/unittest/llmapi/apps/test_openai_server_iteration_stats.pytests/unittest/llmapi/test_llm_args.py
|
/bot run |
|
PR_Github #56155 [ run ] triggered by Bot. Commit: |
|
PR_Github #56155 [ run ] completed with state
|
Signed-off-by: Jiagan Cheng <jiaganc@nvidia.com> (cherry picked from commit 773943a)
…ndexMapper release (NVIDIA#14423) Source-Commit: 02ac906 Signed-off-by: Jiagan Cheng <jiaganc@nvidia.com>
NVIDIA#14308) Source-Commit: 2de7acb Signed-off-by: Jiagan Cheng <jiaganc@nvidia.com>
…ength (NVIDIA#14627) Source-Commit: eeb09d1 Signed-off-by: Jiagan Cheng <jiaganc@nvidia.com>
…euse' + evictable gauges (NVIDIA#14544) Source-Commit: 772f750 Signed-off-by: Jiagan Cheng <jiaganc@nvidia.com>
…s for safe order (NVIDIA#14674) Source-Commit: 808b24f Signed-off-by: Jiagan Cheng <jiaganc@nvidia.com>
…uests (+ probe hang-detector fix) (NVIDIA#14912) Source-Commit: 49f1ce6ce5d6847af7217e3cf5ba3ff9f5e2fdb2 Signed-off-by: Jiagan Cheng <jiaganc@nvidia.com>
Source-Commit: 95cd755 Signed-off-by: Jiagan Cheng <jiaganc@nvidia.com>
Source-Commit: 337b4a5 Signed-off-by: Jiagan Cheng <jiaganc@nvidia.com>
…er attention-DP DSpark speculative decoding hung (or crashed with "unspecified launch failure") when combined with the DeepGEMM MegaMoE backend (MoeConfig.backend=MEGAMOE_DEEPGEMM) under attention-DP on multi-GPU EP. MegaMoE is a FUSED_COMM backend whose fp8_fp4_mega_moe kernel synchronizes EP ranks with an in-kernel phase-flip NVLink barrier that flips on every kernel call, so every EP rank must invoke the draft MoE the same number of times, with the same globally-gathered per-rank token counts, or the barrier desyncs. The DSpark draft violated this in two ways: 1. DSparkDraftModel._forward_stage passed a rank-local [num_tokens] list as all_rank_num_tokens to the draft MoE. The FUSED_COMM scheduler derives its chunk (kernel-invocation) count from max(all_rank_num_tokens) and indexes the local slice by moe_ep_rank, so a length-1 local list makes ranks launch a different number of chunks under attention-DP. 2. Ranks with zero local generation requests skipped the draft MoE entirely while gen-bearing ranks ran it, so the barrier never balanced. Fix: gather per-rank generation-request counts (all_rank_num_gens) at metadata-prep time (outside the CUDA-graph capture region) and thread the resulting global draft-token list [num_gens_r * block] into the draft MoE on every stage. Ranks with no local gen requests replay the per-stage MoE with a single 1-row dummy (encoded as 1 in the shared list) so they still cross the barrier the same number of times; a 0-row input is avoided because DeepseekV4MoE's router / shared-expert dense GEMMs reject an empty matmul (cuBLAS CUBLAS_STATUS_INVALID_VALUE). Non-ADP / single-rank / CUTLASS paths fall back to the previous local [num_tokens] behavior (no functional change). Validated end-to-end on 8xB300 (DeepSeek-V4-Pro-DSpark + MEGAMOE_DEEPGEMM): coherent generation, no barrier timeout. A separate KV-cache-estimation deadlock under attention-DP + spec-dec is addressed by PR NVIDIA#15633 (V2 estimation rework); until that lands, TRTLLM_SKIP_KV_CACHE_ESTIMATION=1 is the workaround. Signed-off-by: Jonas Li <6110159+longlee0622@users.noreply.github.com> (cherry picked from commit acee25d5b719d2318a33a4e44450c0bb2ef9bbd6)
…er attention-DP DSpark speculative decoding hung (or crashed with "unspecified launch failure") when combined with the DeepGEMM MegaMoE backend (MoeConfig.backend=MEGAMOE_DEEPGEMM) under attention-DP on multi-GPU EP. MegaMoE is a FUSED_COMM backend whose fp8_fp4_mega_moe kernel synchronizes EP ranks with an in-kernel phase-flip NVLink barrier that flips on every kernel call, so every EP rank must invoke the draft MoE the same number of times, with the same globally-gathered per-rank token counts, or the barrier desyncs. The DSpark draft violated this in two ways: 1. DSparkDraftModel._forward_stage passed a rank-local [num_tokens] list as all_rank_num_tokens to the draft MoE. The FUSED_COMM scheduler derives its chunk (kernel-invocation) count from max(all_rank_num_tokens) and indexes the local slice by moe_ep_rank, so a length-1 local list makes ranks launch a different number of chunks under attention-DP. 2. Ranks with zero local generation requests skipped the draft MoE entirely while gen-bearing ranks ran it, so the barrier never balanced. Fix: gather per-rank generation-request counts (all_rank_num_gens) at metadata-prep time (outside the CUDA-graph capture region) and thread the resulting global draft-token list [num_gens_r * block] into the draft MoE on every stage. Ranks with no local gen requests replay the per-stage MoE with a single 1-row dummy (encoded as 1 in the shared list) so they still cross the barrier the same number of times; a 0-row input is avoided because DeepseekV4MoE's router / shared-expert dense GEMMs reject an empty matmul (cuBLAS CUBLAS_STATUS_INVALID_VALUE). Non-ADP / single-rank / CUTLASS paths fall back to the previous local [num_tokens] behavior (no functional change). Validated end-to-end on 8xB300 (DeepSeek-V4-Pro-DSpark + MEGAMOE_DEEPGEMM): coherent generation, no barrier timeout. A separate KV-cache-estimation deadlock under attention-DP + spec-dec is addressed by PR NVIDIA#15633 (V2 estimation rework); until that lands, TRTLLM_SKIP_KV_CACHE_ESTIMATION=1 is the workaround. Signed-off-by: Jonas Li <6110159+longlee0622@users.noreply.github.com> (cherry picked from commit acee25d5b719d2318a33a4e44450c0bb2ef9bbd6)
… (fork PR #1) Supersedes the previous PR NVIDIA#15653 squash with the updated v2kv_mamba branch from #1: - V2 Mamba state snapshot reuse (updated after upstream review) - Fix KV cache v2 test request mocks - Fix V2 page table roles for Mamba pools - Support V2 Mamba hybrid cache in disagg Also carries the upstream main commits pulled in by the v2kv_mamba merge: DSv4 follow-up runtime KV and cache foundations (NVIDIA#15633), DeepGEMM and MegaMoE (NVIDIA#15632), and _is_effective_dynamic_tree fix (NVIDIA#15842). Signed-off-by: nv-guomingz <137257613+nv-guomingz@users.noreply.github.com>
… (fork PR #1) Supersedes the previous PR NVIDIA#15653 squash with the updated v2kv_mamba branch from nv-guomingz#1: - V2 Mamba state snapshot reuse (updated after upstream review) - Fix KV cache v2 test request mocks - Fix V2 page table roles for Mamba pools - Support V2 Mamba hybrid cache in disagg Also carries the upstream main commits pulled in by the v2kv_mamba merge: DSv4 follow-up runtime KV and cache foundations (NVIDIA#15633), DeepGEMM and MegaMoE (NVIDIA#15632), and _is_effective_dynamic_tree fix (NVIDIA#15842). Signed-off-by: nv-guomingz <137257613+nv-guomingz@users.noreply.github.com>
…er attention-DP DSpark speculative decoding hung (or crashed with "unspecified launch failure") when combined with the DeepGEMM MegaMoE backend (MoeConfig.backend=MEGAMOE_DEEPGEMM) under attention-DP on multi-GPU EP. MegaMoE is a FUSED_COMM backend whose fp8_fp4_mega_moe kernel synchronizes EP ranks with an in-kernel phase-flip NVLink barrier that flips on every kernel call, so every EP rank must invoke the draft MoE the same number of times, with the same globally-gathered per-rank token counts, or the barrier desyncs. The DSpark draft violated this in two ways: 1. DSparkDraftModel._forward_stage passed a rank-local [num_tokens] list as all_rank_num_tokens to the draft MoE. The FUSED_COMM scheduler derives its chunk (kernel-invocation) count from max(all_rank_num_tokens) and indexes the local slice by moe_ep_rank, so a length-1 local list makes ranks launch a different number of chunks under attention-DP. 2. Ranks with zero local generation requests skipped the draft MoE entirely while gen-bearing ranks ran it, so the barrier never balanced. Fix: gather per-rank generation-request counts (all_rank_num_gens) at metadata-prep time (outside the CUDA-graph capture region) and thread the resulting global draft-token list [num_gens_r * block] into the draft MoE on every stage. Ranks with no local gen requests replay the per-stage MoE with a single 1-row dummy (encoded as 1 in the shared list) so they still cross the barrier the same number of times; a 0-row input is avoided because DeepseekV4MoE's router / shared-expert dense GEMMs reject an empty matmul (cuBLAS CUBLAS_STATUS_INVALID_VALUE). Non-ADP / single-rank / CUTLASS paths fall back to the previous local [num_tokens] behavior (no functional change). Validated end-to-end on 8xB300 (DeepSeek-V4-Pro-DSpark + MEGAMOE_DEEPGEMM): coherent generation, no barrier timeout. A separate KV-cache-estimation deadlock under attention-DP + spec-dec is addressed by PR NVIDIA#15633 (V2 estimation rework); until that lands, TRTLLM_SKIP_KV_CACHE_ESTIMATION=1 is the workaround. Signed-off-by: Jonas Li <6110159+longlee0622@users.noreply.github.com> (cherry picked from commit acee25d5b719d2318a33a4e44450c0bb2ef9bbd6)
…d/onboard bytes + I-7 VSWA V2 regression Re-ran §2d I-5/I-6/I-7/I-8 on the rebuilt rc21 wheel (rebased onto origin/main incl. NVIDIA#15633). Updates §6 tracking table: - I-6: quantify the GPU<->host round-trip from NVIDIA#15633 stats (kvCacheIterationStatsByPoolGroup): V2 iterOffloadBytes=75,497,472 (72 MiB), iterOnboardBytes=56,623,104 (54 MiB), iterReusedBlocks=24. - I-7: TP=1/2/4 re-confirmed green; VSWA V2 REGRESSED (yellow) — CuOOMError in V2 storage init (CacheLevelStorage -> CudaVirtMem.resize, _storage/_core.py:132), fraction-independent (OOMs at 0.4/0.3/0.2). Passed on V2 at rc20 with a byte-identical config -> regression from the rebase; NVIDIA#15633 prime suspect. - I-5/I-8: re-confirmed green on rc21. Signed-off-by: Yueh-Ting Chen <yuehtingc@nvidia.com>
copy_batch_block_offsets()/copy_batch_sliding_block_tables() read self._num_tables, which is only assigned in compute_sliding_block_tables() (a forward-time method). During attention warmup the copy runs before any forward, raising AttributeError: 'DeepseekV4CacheManager' object has no attribute '_num_tables'. Initialize it to 0 in __init__ so the warmup copy is a harmless empty slice; the real value is still set per-batch. Regression surfaced by the runtime KV/cache foundations change (NVIDIA#15633). Signed-off-by: Jonas Li <6110159+longlee0622@users.noreply.github.com>
…puts on non-spec / non-mrope path PR NVIDIA#11943 added per-request Python LOAD_ATTR overhead in the generation-input prep path. PR NVIDIA#15633 added three unconditional _wait_for_model_engine_input_copy() syncs in PyExecutor's run loop. For dense non-multimodal / non-spec-decode workloads (e.g. gpt-oss-120b disagg dep2 at con=2048), the aggregate host-side ticks explain a ~6% throughput regression on GB200. Changes (Python-only, no runtime behavior change on the affected path): * Snapshot request.py_batch_idx and request.max_beam_num_tokens once per generation-request iteration in _prepare_tp_inputs; read sites now pay LOAD_FAST instead of LOAD_ATTR. The write-site `request.py_batch_idx = request.py_seq_slot` still fires after the reads, so snapshot-before-write ordering is preserved. * Skip get_runtime_tokens_per_gen_step() call when self.enable_spec_decode is False (callee is `lambda _: 1` when spec_config is None). * Gate 3 _wait_for_model_engine_input_copy() calls in PyExecutor on self._is_kv_manager_v2. Pre-NVIDIA#15633 the legacy V1 scheduler ran without any such sync; the sync is only needed for V2's host page-table. Verified on Lyris GB200 in the auto-perf-fix-pro workflow, 3-rep median: test: disagg-e2e-gb200_gpt-oss-120b-fp4_1k1k_con2048_ctx1_tp1_gen1_dep2_eplb0_mtp0_ccb-UCX good median (15d06c0): 105905.45 tok/s bad median (c25fa74): 99217.72 tok/s ToT median (a0c406f): 98526.45 tok/s Fix median (this diff): 103082.72 tok/s (+4.62% over ToT, +3.90% over bad) Signed-off-by: Chenfei Zhang <chenfeiz@nvidia.com>
…1 = main ef6ebc2 + NVIDIA#15633) Signed-off-by: Yueh-Ting Chen <yuehtingc@nvidia.com>
… V2 OOM regression, build provenance (main ef6ebc2 + NVIDIA#15633) Signed-off-by: Yueh-Ting Chen <yuehtingc@nvidia.com>
…#15633) Signed-off-by: Jiagan Cheng Based on the offline discussion with Jiagan/Fanrong carefully, by combining the following two CI runs: * https://prod.blsm.nvidia.com/sw-tensorrt-top-1/job/LLM/job/main/job/L0_MergeRequest_PR/45969/ * https://prod.blsm.nvidia.com/sw-tensorrt-top-1/job/LLM/job/main/job/L0_MergeRequest_PR/46187/ The pre-merge CI is clean now. To unblock the subsequent merge of other two DS V4 PRs, I just go ahead with force merging this PR to main branch directly. Though I have confidence of this PR, this is still a special operation, so Jiagan will soon start another full pre-merge CI based on the new ToT of main to do sanity check in case there are any unlucky things.
…er attention-DP DSpark speculative decoding hung (or crashed with "unspecified launch failure") when combined with the DeepGEMM MegaMoE backend (MoeConfig.backend=MEGAMOE_DEEPGEMM) under attention-DP on multi-GPU EP. MegaMoE is a FUSED_COMM backend whose fp8_fp4_mega_moe kernel synchronizes EP ranks with an in-kernel phase-flip NVLink barrier that flips on every kernel call, so every EP rank must invoke the draft MoE the same number of times, with the same globally-gathered per-rank token counts, or the barrier desyncs. The DSpark draft violated this in two ways: 1. DSparkDraftModel._forward_stage passed a rank-local [num_tokens] list as all_rank_num_tokens to the draft MoE. The FUSED_COMM scheduler derives its chunk (kernel-invocation) count from max(all_rank_num_tokens) and indexes the local slice by moe_ep_rank, so a length-1 local list makes ranks launch a different number of chunks under attention-DP. 2. Ranks with zero local generation requests skipped the draft MoE entirely while gen-bearing ranks ran it, so the barrier never balanced. Fix: gather per-rank generation-request counts (all_rank_num_gens) at metadata-prep time (outside the CUDA-graph capture region) and thread the resulting global draft-token list [num_gens_r * block] into the draft MoE on every stage. Ranks with no local gen requests replay the per-stage MoE with a single 1-row dummy (encoded as 1 in the shared list) so they still cross the barrier the same number of times; a 0-row input is avoided because DeepseekV4MoE's router / shared-expert dense GEMMs reject an empty matmul (cuBLAS CUBLAS_STATUS_INVALID_VALUE). Non-ADP / single-rank / CUTLASS paths fall back to the previous local [num_tokens] behavior (no functional change). Validated end-to-end on 8xB300 (DeepSeek-V4-Pro-DSpark + MEGAMOE_DEEPGEMM): coherent generation, no barrier timeout. A separate KV-cache-estimation deadlock under attention-DP + spec-dec is addressed by PR NVIDIA#15633 (V2 estimation rework); until that lands, TRTLLM_SKIP_KV_CACHE_ESTIMATION=1 is the workaround. Signed-off-by: Jonas Li <6110159+longlee0622@users.noreply.github.com> (cherry picked from commit acee25d5b719d2318a33a4e44450c0bb2ef9bbd6)
copy_batch_block_offsets()/copy_batch_sliding_block_tables() read self._num_tables, which is only assigned in compute_sliding_block_tables() (a forward-time method). During attention warmup the copy runs before any forward, raising AttributeError: 'DeepseekV4CacheManager' object has no attribute '_num_tables'. Initialize it to 0 in __init__ so the warmup copy is a harmless empty slice; the real value is still set per-batch. Regression surfaced by the runtime KV/cache foundations change (NVIDIA#15633). Signed-off-by: Jonas Li <6110159+longlee0622@users.noreply.github.com>
…er attention-DP DSpark speculative decoding hung (or crashed with "unspecified launch failure") when combined with the DeepGEMM MegaMoE backend (MoeConfig.backend=MEGAMOE_DEEPGEMM) under attention-DP on multi-GPU EP. MegaMoE is a FUSED_COMM backend whose fp8_fp4_mega_moe kernel synchronizes EP ranks with an in-kernel phase-flip NVLink barrier that flips on every kernel call, so every EP rank must invoke the draft MoE the same number of times, with the same globally-gathered per-rank token counts, or the barrier desyncs. The DSpark draft violated this in two ways: 1. DSparkDraftModel._forward_stage passed a rank-local [num_tokens] list as all_rank_num_tokens to the draft MoE. The FUSED_COMM scheduler derives its chunk (kernel-invocation) count from max(all_rank_num_tokens) and indexes the local slice by moe_ep_rank, so a length-1 local list makes ranks launch a different number of chunks under attention-DP. 2. Ranks with zero local generation requests skipped the draft MoE entirely while gen-bearing ranks ran it, so the barrier never balanced. Fix: gather per-rank generation-request counts (all_rank_num_gens) at metadata-prep time (outside the CUDA-graph capture region) and thread the resulting global draft-token list [num_gens_r * block] into the draft MoE on every stage. Ranks with no local gen requests replay the per-stage MoE with a single 1-row dummy (encoded as 1 in the shared list) so they still cross the barrier the same number of times; a 0-row input is avoided because DeepseekV4MoE's router / shared-expert dense GEMMs reject an empty matmul (cuBLAS CUBLAS_STATUS_INVALID_VALUE). Non-ADP / single-rank / CUTLASS paths fall back to the previous local [num_tokens] behavior (no functional change). Validated end-to-end on 8xB300 (DeepSeek-V4-Pro-DSpark + MEGAMOE_DEEPGEMM): coherent generation, no barrier timeout. A separate KV-cache-estimation deadlock under attention-DP + spec-dec is addressed by PR NVIDIA#15633 (V2 estimation rework); until that lands, TRTLLM_SKIP_KV_CACHE_ESTIMATION=1 is the workaround. Signed-off-by: Jonas Li <6110159+longlee0622@users.noreply.github.com> (cherry picked from commit acee25d5b719d2318a33a4e44450c0bb2ef9bbd6)
copy_batch_block_offsets()/copy_batch_sliding_block_tables() read self._num_tables, which is only assigned in compute_sliding_block_tables() (a forward-time method). During attention warmup the copy runs before any forward, raising AttributeError: 'DeepseekV4CacheManager' object has no attribute '_num_tables'. Initialize it to 0 in __init__ so the warmup copy is a harmless empty slice; the real value is still set per-batch. Regression surfaced by the runtime KV/cache foundations change (NVIDIA#15633). Signed-off-by: Jonas Li <6110159+longlee0622@users.noreply.github.com>
…epare_page_table_tensor PR NVIDIA#15633 (DSv4 follow-up: runtime KV and cache foundations) renamed the base KVCacheManagerV2 hook from _build_pool_mapping_tensors to _prepare_page_table_tensor and expanded its state contract. The MiniMaxM3KVCacheManagerV2 override kept the old name, so it became dead code: the base ran unmodified and hit exact_div(addr_offset, key_bytes * kv_factor * tokens_per_block) at kv_cache_manager_v2.py: 1075. That formula assumes each layer contributes exactly K+V to the pool; M3 production coalesces INDEX_KEY with K/V into one pool with a 3x-single-buffer stride, so exact_div asserts on TestMiniMaxM3. test_nvfp4[tp_size=4-ep_size=4] on GB300. Rename the override to _prepare_page_table_tensor(index_mapper_capacity) and populate the base's full state contract (kv_cache_pool_pointers, kv_cache_pool_mapping, index_scales, kv_offset, host_kv_cache_block_offsets) rather than returning tensors. The per-layer offset is computed from layer_grouping position (regardless of how many extra buffers coalesce with K/V), which sidesteps the broken exact_div while remaining consistent with the M3 forward path's direct get_buffers() / get_index_k_buffer() usage. Signed-off-by: trtllm-agent <296075020+trtllm-agent@users.noreply.github.com>
…er attention-DP DSpark speculative decoding hung (or crashed with "unspecified launch failure") when combined with the DeepGEMM MegaMoE backend (MoeConfig.backend=MEGAMOE_DEEPGEMM) under attention-DP on multi-GPU EP. MegaMoE is a FUSED_COMM backend whose fp8_fp4_mega_moe kernel synchronizes EP ranks with an in-kernel phase-flip NVLink barrier that flips on every kernel call, so every EP rank must invoke the draft MoE the same number of times, with the same globally-gathered per-rank token counts, or the barrier desyncs. The DSpark draft violated this in two ways: 1. DSparkDraftModel._forward_stage passed a rank-local [num_tokens] list as all_rank_num_tokens to the draft MoE. The FUSED_COMM scheduler derives its chunk (kernel-invocation) count from max(all_rank_num_tokens) and indexes the local slice by moe_ep_rank, so a length-1 local list makes ranks launch a different number of chunks under attention-DP. 2. Ranks with zero local generation requests skipped the draft MoE entirely while gen-bearing ranks ran it, so the barrier never balanced. Fix: gather per-rank generation-request counts (all_rank_num_gens) at metadata-prep time (outside the CUDA-graph capture region) and thread the resulting global draft-token list [num_gens_r * block] into the draft MoE on every stage. Ranks with no local gen requests replay the per-stage MoE with a single 1-row dummy (encoded as 1 in the shared list) so they still cross the barrier the same number of times; a 0-row input is avoided because DeepseekV4MoE's router / shared-expert dense GEMMs reject an empty matmul (cuBLAS CUBLAS_STATUS_INVALID_VALUE). Non-ADP / single-rank / CUTLASS paths fall back to the previous local [num_tokens] behavior (no functional change). Validated end-to-end on 8xB300 (DeepSeek-V4-Pro-DSpark + MEGAMOE_DEEPGEMM): coherent generation, no barrier timeout. A separate KV-cache-estimation deadlock under attention-DP + spec-dec is addressed by PR NVIDIA#15633 (V2 estimation rework); until that lands, TRTLLM_SKIP_KV_CACHE_ESTIMATION=1 is the workaround. Signed-off-by: Jonas Li <6110159+longlee0622@users.noreply.github.com> (cherry picked from commit acee25d5b719d2318a33a4e44450c0bb2ef9bbd6)
copy_batch_block_offsets()/copy_batch_sliding_block_tables() read self._num_tables, which is only assigned in compute_sliding_block_tables() (a forward-time method). During attention warmup the copy runs before any forward, raising AttributeError: 'DeepseekV4CacheManager' object has no attribute '_num_tables'. Initialize it to 0 in __init__ so the warmup copy is a harmless empty slice; the real value is still set per-batch. Regression surfaced by the runtime KV/cache foundations change (NVIDIA#15633). Signed-off-by: Jonas Li <6110159+longlee0622@users.noreply.github.com>
The KV Cache Manager V2 quota-inflation OOM on multi-GPU VSWA (variable sliding-window attention) configurations -- a regression from NVIDIA#15633 -- was fixed on main by a parallel effort, NVIDIA#15991 (nvbugs/6418103), which clamps the post-allreduce quota by the pre-allreduce quota so the cross-rank normalization can only reduce, never over-commit. That fix landed without a test guarding the V2 + VSWA path. This change amends the missing coverage. Parametrize TestGPTOSS::test_eagle3_vswa_reuse_4gpus over v2_kv_cache so the previously-uncovered V2 path (GPT-OSS-120B, TP=4, max_attention_window=[128, 32768], free_gpu_memory_fraction=0.4) runs and guards against regressing the fix -- this variant OOM'd before NVIDIA#15991. The v2_kv_cache + two-model combination is skipped (V2 is not compatible with two-model overlap scheduling). Register the new variants in llm_function_core.txt and llm_function_rtx6k.txt. Signed-off-by: Yueh-Ting Chen <yuehtingc@nvidia.com>
…er attention-DP DSpark speculative decoding hung (or crashed with "unspecified launch failure") when combined with the DeepGEMM MegaMoE backend (MoeConfig.backend=MEGAMOE_DEEPGEMM) under attention-DP on multi-GPU EP. MegaMoE is a FUSED_COMM backend whose fp8_fp4_mega_moe kernel synchronizes EP ranks with an in-kernel phase-flip NVLink barrier that flips on every kernel call, so every EP rank must invoke the draft MoE the same number of times, with the same globally-gathered per-rank token counts, or the barrier desyncs. The DSpark draft violated this in two ways: 1. DSparkDraftModel._forward_stage passed a rank-local [num_tokens] list as all_rank_num_tokens to the draft MoE. The FUSED_COMM scheduler derives its chunk (kernel-invocation) count from max(all_rank_num_tokens) and indexes the local slice by moe_ep_rank, so a length-1 local list makes ranks launch a different number of chunks under attention-DP. 2. Ranks with zero local generation requests skipped the draft MoE entirely while gen-bearing ranks ran it, so the barrier never balanced. Fix: gather per-rank generation-request counts (all_rank_num_gens) at metadata-prep time (outside the CUDA-graph capture region) and thread the resulting global draft-token list [num_gens_r * block] into the draft MoE on every stage. Ranks with no local gen requests replay the per-stage MoE with a single 1-row dummy (encoded as 1 in the shared list) so they still cross the barrier the same number of times; a 0-row input is avoided because DeepseekV4MoE's router / shared-expert dense GEMMs reject an empty matmul (cuBLAS CUBLAS_STATUS_INVALID_VALUE). Non-ADP / single-rank / CUTLASS paths fall back to the previous local [num_tokens] behavior (no functional change). Validated end-to-end on 8xB300 (DeepSeek-V4-Pro-DSpark + MEGAMOE_DEEPGEMM): coherent generation, no barrier timeout. A separate KV-cache-estimation deadlock under attention-DP + spec-dec is addressed by PR NVIDIA#15633 (V2 estimation rework); until that lands, TRTLLM_SKIP_KV_CACHE_ESTIMATION=1 is the workaround. Signed-off-by: Jonas Li <6110159+longlee0622@users.noreply.github.com> (cherry picked from commit acee25d5b719d2318a33a4e44450c0bb2ef9bbd6)
copy_batch_block_offsets()/copy_batch_sliding_block_tables() read self._num_tables, which is only assigned in compute_sliding_block_tables() (a forward-time method). During attention warmup the copy runs before any forward, raising AttributeError: 'DeepseekV4CacheManager' object has no attribute '_num_tables'. Initialize it to 0 in __init__ so the warmup copy is a harmless empty slice; the real value is still set per-batch. Regression surfaced by the runtime KV/cache foundations change (NVIDIA#15633). Signed-off-by: Jonas Li <6110159+longlee0622@users.noreply.github.com>
…er attention-DP DSpark speculative decoding hung (or crashed with "unspecified launch failure") when combined with the DeepGEMM MegaMoE backend (MoeConfig.backend=MEGAMOE_DEEPGEMM) under attention-DP on multi-GPU EP. MegaMoE is a FUSED_COMM backend whose fp8_fp4_mega_moe kernel synchronizes EP ranks with an in-kernel phase-flip NVLink barrier that flips on every kernel call, so every EP rank must invoke the draft MoE the same number of times, with the same globally-gathered per-rank token counts, or the barrier desyncs. The DSpark draft violated this in two ways: 1. DSparkDraftModel._forward_stage passed a rank-local [num_tokens] list as all_rank_num_tokens to the draft MoE. The FUSED_COMM scheduler derives its chunk (kernel-invocation) count from max(all_rank_num_tokens) and indexes the local slice by moe_ep_rank, so a length-1 local list makes ranks launch a different number of chunks under attention-DP. 2. Ranks with zero local generation requests skipped the draft MoE entirely while gen-bearing ranks ran it, so the barrier never balanced. Fix: gather per-rank generation-request counts (all_rank_num_gens) at metadata-prep time (outside the CUDA-graph capture region) and thread the resulting global draft-token list [num_gens_r * block] into the draft MoE on every stage. Ranks with no local gen requests replay the per-stage MoE with a single 1-row dummy (encoded as 1 in the shared list) so they still cross the barrier the same number of times; a 0-row input is avoided because DeepseekV4MoE's router / shared-expert dense GEMMs reject an empty matmul (cuBLAS CUBLAS_STATUS_INVALID_VALUE). Non-ADP / single-rank / CUTLASS paths fall back to the previous local [num_tokens] behavior (no functional change). Validated end-to-end on 8xB300 (DeepSeek-V4-Pro-DSpark + MEGAMOE_DEEPGEMM): coherent generation, no barrier timeout. A separate KV-cache-estimation deadlock under attention-DP + spec-dec is addressed by PR NVIDIA#15633 (V2 estimation rework); until that lands, TRTLLM_SKIP_KV_CACHE_ESTIMATION=1 is the workaround. Signed-off-by: Jonas Li <6110159+longlee0622@users.noreply.github.com> (cherry picked from commit acee25d5b719d2318a33a4e44450c0bb2ef9bbd6)
copy_batch_block_offsets()/copy_batch_sliding_block_tables() read self._num_tables, which is only assigned in compute_sliding_block_tables() (a forward-time method). During attention warmup the copy runs before any forward, raising AttributeError: 'DeepseekV4CacheManager' object has no attribute '_num_tables'. Initialize it to 0 in __init__ so the warmup copy is a harmless empty slice; the real value is still set per-batch. Regression surfaced by the runtime KV/cache foundations change (NVIDIA#15633). Signed-off-by: Jonas Li <6110159+longlee0622@users.noreply.github.com>
Summary by CodeRabbit
New Features
Bug Fixes
Description
Merge the DeepSeek V4 runtime/KV-cache foundation and DSv4-specific cache
manager work back onto current
main.The PR1 prefix provides the generic foundation:
KVCacheManagerV2integration in its currentkv_cache_manager_v2.pyowner, including config-controlled SWA scratchreuse and cache-size/statistics plumbing;
OpenAI serving, and disaggregated serving paths;
benchmark stall diagnostics;
after input-copy synchronization.
The DSv4-CM stack starts after dependency boundary
af57e65d8fand appliesnine source commits in feature-branch order:
This adds DSv4 role-specific block-table/page mapping, compiled scratch-copy
paths, MTP rewind, pool-ratio sizing, V2 estimation, block-reuse policy, and
disaggregated context-finalization ordering. Source V2 changes were ported from
the former
resource_manager.pylocation intokv_cache_manager_v2.py.Where the first DSv4 commit overlapped generic scratch integration, the current
main implementation from
82f180443dremains authoritative and DSv4 behavioris connected through the V2 page-table extension hook.
The final branch was compared file by file with
upstream/feat/deepseek_v4@af42658ecb. Every selected source hunk is present,already equivalent on the dependency base, or documented as a latest-main API
adaptation or moved owner. Feature-only Router/OpenAI policy, sparse custom-op,
MoE/CuTeDSL, and generated FMHA changes remain out of scope.
Test Coverage
A clean build ran on B300 host
umb-b300-dp-186at final SHAfadeb20ae3:Result: all 4,543 build targets passed, including bindings and raw-reference
generation.
Changed DSv4 cache-manager, compressor, executor, scheduler, disaggregation,
transfer, V2 runtime, cache-statistics, and LLM-args unit tests then ran in the
worktree-mounted development container:
The two failures are
TestTrtLlmArgs::test_build_config_from_engineandTestTorchLlmArgs::test_runtime_sizes. Both workers fail while importing thecontainer package with
ImportError: cannot import name 'bitwidth' from 'triton_kernels.tensor'.They reproduced before and after the clean build and are an environment package
mismatch rather than failures in the changed code.
Earlier PR1-focused remote validation also covered the disaggregated perf
metrics collector and OpenAI iteration-stat tests; that batch completed with
283 passed, 3 skippedbefore the final autosquash.Explicitly skipped by request:
tests/unittest/bindings/test_executor_bindings.pytests/unittest/_torch/modeling/test_modeling_deepseekv4.pytests/unittest/_torch/attention/sparse/deepseek_v4/test_deepseek_v4_sparse_mla.pytests/unittest/_torch/attention/sparse/deepseek_v4/test_deepseek_v4_indices_transform.pytests/unittest/_torch/speculative/test_eagle3.pyChanged accuracy integration tests were not run because their model data and
full integration environment were unavailable in the unit-test container.
Full-range pre-commit,
git diff --check, strict conflict-marker search,source-order/trailer audit, and forbidden-scope checks passed. The final branch
tree is byte-identical to the tree used for the clean build and final tests.
PR Checklist
Please review the following before submitting your PR:
PR description clearly explains what and why. If using CodeRabbit's summary, please make sure it makes sense.
PR Follows TRT-LLM CODING GUIDELINES to the best of your knowledge.
Test cases are provided for new code paths (see test instructions)
If PR introduces API changes, an appropriate PR label is added - either
api-compatibleorapi-breaking. Forapi-breaking, includeBREAKINGin the PR title.Any new dependencies have been scanned for license and vulnerabilities
CODEOWNERS updated if ownership changes
Documentation updated as needed
Update tava architecture diagram if there is a significant design change in PR.
The reviewers assigned automatically/manually are appropriate for the PR.
Please check this after reviewing the above items as appropriate for this PR.
GitHub Bot Help
To see a list of available CI bot commands, please comment
/bot help.