Skip to content

[https://nvbugs/6373447][fix] Restore rc17 throughput by trimming per-iter host overhead#16047

Closed
chenfeiz0326 wants to merge 1 commit into
NVIDIA:mainfrom
chenfeiz0326:repair-bot-bug6373447
Closed

[https://nvbugs/6373447][fix] Restore rc17 throughput by trimming per-iter host overhead#16047
chenfeiz0326 wants to merge 1 commit into
NVIDIA:mainfrom
chenfeiz0326:repair-bot-bug6373447

Conversation

@chenfeiz0326

@chenfeiz0326 chenfeiz0326 commented Jul 7, 2026

Copy link
Copy Markdown
Collaborator

Summary

  • Root cause: The regression came from added per-iteration host-side work in PyTorchModelEngine._prepare_tgen_inputs/_prepare_inputs and PyExecutor: an extra sum(num_cached_tokens_per_seq) for cached_kv_tokens, an unconditional get_runtime_tokens_per_gen_step call that resolves to a constant when spec decode is off, repeated LOAD_ATTR on per-request Python attributes inside the generation loop, and an earlier-than-necessary _wait_for_model_engine_input_copy sync on the legacy scheduler path. These accumulated CPU overhead per step, degrading Total_Token_Throughput vs 1.3.0rc17 on decode-heavy workloads.
  • Fix: Removed the unused cached_kv_tokens bookkeeping, inlined the constant runtime_tokens_per_gen_step = 1 when spec decode is disabled, snapshotted request.py_batch_idx and request.max_beam_num_tokens once per request so read-sites use LOAD_FAST, and restored the pre-[None][feat] DSv4 follow-up: runtime KV and cache foundations #15633 behavior of deferring the input-copy wait for the legacy scheduler. These are minimal, semantics-preserving micro-optimizations that reverse the specific hot-path additions introduced since rc17 without changing scheduler or spec-decode behavior.
  • Automated fix generated by repair-bot

Test plan

  • Verify fix on the same GPU type as the original failure
  • Check for regressions in related tests

Links

Summary by CodeRabbit

  • Bug Fixes
    • Improved executor behavior by avoiding unnecessary synchronization work in supported configurations, which should reduce overhead and speed up request processing.
    • Streamlined model input preparation to make batch handling more efficient and consistent, including better handling of multimodal requests.

@chenfeiz0326
chenfeiz0326 requested a review from a team as a code owner July 7, 2026 07:05
@chenfeiz0326
chenfeiz0326 requested a review from achartier July 7, 2026 07:05
@coderabbitai

coderabbitai Bot commented Jul 7, 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: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: 2a6458ab-12d6-4338-9485-0af82adcecfe

📥 Commits

Reviewing files that changed from the base of the PR and between c09fbbd and cd675a4.

📒 Files selected for processing (2)
  • tensorrt_llm/_torch/pyexecutor/model_engine.py
  • tensorrt_llm/_torch/pyexecutor/py_executor.py

📝 Walkthrough

Walkthrough

Modifies PyTorchModelEngine's input preparation to remove cached_kv_tokens tracking, inline runtime_tokens_per_gen_step for non-spec-decode paths, and snapshot per-request attributes into locals for reduced repeated reads. Also gates PyExecutor's model_engine input copy wait calls behind an _is_kv_manager_v2 check.

Changes

Model engine input preparation optimizations

Layer / File(s) Summary
Remove cached_kv_tokens iteration tracking
tensorrt_llm/_torch/pyexecutor/model_engine.py
iter_states no longer records cached_kv_tokens in _prepare_incremental_update_metadata or at the end of _prepare_tp_inputs, keeping only ctx/generation token counters.
Inline runtime_tokens_per_gen_step for non-spec-decode
tensorrt_llm/_torch/pyexecutor/model_engine.py
runtime_tokens_per_gen_step is set to 1 directly when spec decode is disabled instead of calling get_runtime_tokens_per_gen_step.
Snapshot per-request locals in generation packing
tensorrt_llm/_torch/pyexecutor/model_engine.py
py_batch_idx and max_beam_num_tokens are snapshotted into locals and reused across branch conditions, previous-batch-index appends, past-seen-token computation, and multimodal stripping checks.

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

Gate Model Engine Input Copy Wait Behind KV Manager V2

Layer / File(s) Summary
Conditional wait gating
tensorrt_llm/_torch/pyexecutor/py_executor.py
Three calls to wait for model_engine input copy in _executor_loop_overlap are now gated behind _is_kv_manager_v2, with comments clarifying the wait is only required for KV cache manager V2.

Estimated code review effort: 2 (Simple) | ~10 minutes

Sequence Diagram(s)

sequenceDiagram
  participant PyExecutor
  participant ModelEngine
  participant KVCacheManager

  PyExecutor->>PyExecutor: check _is_kv_manager_v2
  alt is_kv_manager_v2 true
    PyExecutor->>ModelEngine: wait_for_model_engine_input_copy()
    ModelEngine-->>PyExecutor: input copy complete
  else is_kv_manager_v2 false
    PyExecutor->>PyExecutor: skip wait
  end
  PyExecutor->>KVCacheManager: _update_request_states / _process_previous_batch
Loading

Possibly related PRs

  • NVIDIA/TensorRT-LLM#15750: Both PRs modify the same PyTorchModelEngine TP input preparation hot path, hoisting per-request locals like py_batch_idx and gating multimodal stripping conditions.

Suggested reviewers: joyang-nv, yechank-nvidia, litaotju

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title matches the PR’s main fix and follows the required [ticket][type] summary format.
Description check ✅ Passed The description covers Summary, Test plan, and Links, with only the PR checklist section omitted.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
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.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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

self.iter_states['num_ctx_tokens'] = num_ctx_tokens
self.iter_states['num_generation_tokens'] = num_generation_tokens
# Count the already-cached prefix for the sequences scheduled this iteration.
self.iter_states['cached_kv_tokens'] = sum(num_cached_tokens_per_seq)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it safe to remove this?

…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>
@chenfeiz0326
chenfeiz0326 force-pushed the repair-bot-bug6373447 branch from cd675a4 to e7734fb Compare July 7, 2026 14:07
self.runtime_draft_len)
else:
# Non-spec-decode path: callee is `lambda _: 1` when spec_config is None
# (see __init__:539). Inline the constant to skip the per-call frame setup.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Line number reference in comments go stale - replace by an actual description.

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.

3 participants