Skip to content

[None][feat] ADP conversation router: configurable least-queued placement for new conversations#16294

Merged
lancelly merged 1 commit into
NVIDIA:mainfrom
lancelly:feat/adp-least-queued-placement
Jul 23, 2026
Merged

[None][feat] ADP conversation router: configurable least-queued placement for new conversations#16294
lancelly merged 1 commit into
NVIDIA:mainfrom
lancelly:feat/adp-least-queued-placement

Conversation

@lancelly

@lancelly lancelly commented Jul 13, 2026

Copy link
Copy Markdown
Collaborator

Summary by CodeRabbit

  • New Features

    • Added configurable placement for new conversations in conversation-aware KV-cache routing.
    • Choose between round-robin assignment or least-queued placement.
    • Existing conversations remain pinned to their assigned rank.
    • Invalid placement values safely fall back to round-robin behavior.
  • Tests

    • Added coverage for load balancing, batch leveling, sticky routing, deterministic results, and configuration fallback.

Description

kv_cache_routing_conversation_affinity pins each conversation to one attention-DP rank and round-robins first turns across ranks. Round-robin equalizes per-rank conversation counts, but per-conversation load (turn rate, agentic fan-out, prefill length) is far from uniform. On an agentic multi-turn workload (4×(TP8, attention-DP) prefill workers in a disaggregated deployment, concurrency 1000, ~95% KV block reuse) we measured:

  • per-rank live conversation counts near-uniform: max/min ≤ 1.14×
  • yet per-rank scheduler queue depth skewed 1.8–3.4× (hot rank mean 24 queued vs 8 on its neighbors)
  • coldest ranks dummy-padded in up to 15.7% of iterations (lockstep ADP: an idle rank's iteration capacity is simply lost) while deep queues persisted elsewhere

This PR adds attention_dp_config.kv_cache_routing_new_conv_placement:

  • "round_robin" (default) — existing behavior, unchanged.
  • "least_queued" — place requests that have no pinned rank yet (first turn of a conversation, conversation-less requests, sticky overflow) on the rank with the fewest live requests, reusing the existing _least_loaded helper (previously only reachable as an RR fallback). Heavy pinned conversations keep their rank's count high, so new conversations steer away from hot ranks — emergent weight-awareness without predicting per-conversation weight. The shared in-batch count accumulator spreads bursts valley-first.

Sticky returns, soft/hard caps, and the padding invariant are untouched; routing remains a deterministic pure function of allgathered state (required by the replicated no-broadcast protocol — least-loaded is stateless, one less cross-iteration state than the RR cursor).

A/B on the workload above (only this knob changed):

metric round_robin least_queued
per-rank queue skew (max/min of rank means, worst instance) 3.4× 2.0×
dummy-padded iterations, worst rank 15.7% 9.9%
TTFT p90 35.5 s 30.0 s (−15.5%)
TTFT p99 105.6 s 87.5 s (−17.2%)
KV block reuse 95.0% 95.0%
request throughput 35.75 req/s 35.90 req/s

Remaining skew comes from already-pinned heavy conversations (not migrated, preserving prefix-cache residency by design).

@lancelly
lancelly force-pushed the feat/adp-least-queued-placement branch 5 times, most recently from 9ea88bd to ae5515b Compare July 13, 2026 03:25
@lancelly lancelly added the api-compatible Accepted LLM API contract change that is backwards-compatible label Jul 13, 2026
…ment for new conversations

kv_cache_routing_conversation_affinity pins conversations to ranks and
round-robins first turns, equalizing per-rank conversation counts. But
conversation weight (turn rate, agentic fan-out, prefill length) is not
uniform: on an agentic multi-turn workload at concurrency 1000 we
measured near-uniform per-rank conversation counts (max/min 1.14x) yet
1.8-3.4x per-rank queue-depth skew, with the coldest ranks dummy-padded
in up to 15.7% of iterations while hot ranks queued 24 deep.

Add attention_dp_config.kv_cache_routing_new_conv_placement:
- round_robin (default): existing behavior, unchanged.
- least_queued: place unpinned requests (first turns, conversation-less
  requests, sticky overflow) on the rank with the fewest live requests,
  reusing the existing _least_loaded helper. Heavy pinned conversations
  keep their rank's count high, so new conversations steer away from
  hot ranks; the in-batch count accumulator spreads bursts valley-first.

Sticky returns, soft/hard caps, and the padding invariant are
unchanged; routing stays a deterministic pure function of allgathered
state, as required by the replicated no-broadcast protocol.

Measured on a 4x(TP8, attention-DP) prefill disagg deployment at
concurrency 1000 (agentic multi-turn replay, 95% KV block reuse):
per-rank queue skew 3.4x -> 2.0x, TTFT p90 -15.5%, p99 -17.2%, KV
reuse unchanged, throughput neutral.

Signed-off-by: Lance Liao <108499334+lancelly@users.noreply.github.com>
@lancelly
lancelly force-pushed the feat/adp-least-queued-placement branch from ae5515b to 01da19e Compare July 13, 2026 03:28
@lancelly
lancelly marked this pull request as ready for review July 13, 2026 04:14
@lancelly
lancelly requested review from a team as code owners July 13, 2026 04:14
@lancelly
lancelly requested review from QiJune and arysef July 13, 2026 04:14
@lancelly

Copy link
Copy Markdown
Collaborator Author

/bot run --disable-fail-fast

@coderabbitai

coderabbitai Bot commented Jul 13, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Caution

Review failed

Failed to post review comments.

GitHub was unavailable or timed out while CodeRabbit was posting the review. Please request a new review later if the pull request still needs one. This happened while posting 1 inline comment. Use @coderabbitai full review to retry the review.

⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: 10934ab4-dfe1-41e9-92a2-864c758d2f8e

📥 Commits

Reviewing files that changed from the base of the PR and between 6bd6bb8 and 01da19e.

📒 Files selected for processing (4)
  • tensorrt_llm/_torch/pyexecutor/scheduler/adp_router.py
  • tensorrt_llm/llmapi/llm_args.py
  • tensorrt_llm/usage/llm_args_golden_manifest.json
  • tests/unittest/_torch/executor/test_adp_router.py
🧰 Additional context used
📓 Path-based instructions (6)
**/*

📄 CodeRabbit inference engine (AGENTS.md)

Add an NVIDIA copyright header to all new files, and update the copyright year in modified files.

Files:

  • tensorrt_llm/usage/llm_args_golden_manifest.json
  • tensorrt_llm/llmapi/llm_args.py
  • tensorrt_llm/_torch/pyexecutor/scheduler/adp_router.py
  • tests/unittest/_torch/executor/test_adp_router.py
**

⚙️ CodeRabbit configuration file

**:

TensorRT-LLM Coding Guidelines

C++ Coding Guidelines

The TensorRT-LLM C++ Coding Guidelines are mainly derived from the Google C++ Style Guide

General principle: Do not fight the tooling (clang-format, clang-tidy, pre-commit) without good reason. If the tool enforces a style, follow it.

Note: These guidelines have been inconsistently followed in the existing codebase. New code and modifications to existing code should adhere to these guidelines. Cleaning up existing code to match these guidelines as you touch it is encouraged, but bulk changes of surrounding code should be a separate PR.


Namespaces

  1. Closing braces of namespaces should have a comment saying the namespace it closes:
namespace foo
{
...
} // namespace foo
  1. Anonymous namespaces use the same convention:
namespace
{
...
} // namespace

Constants

  1. Prefer const or constexpr variables over #defines whenever possible, as the latter are not visible to the compiler.
  2. A variable that is not modified after its initialization should be declared as const. This applies to local and global variable declarations; it is not required for function parameters.
  3. Use east-const style: place const to the right of the type it qualifies (e.g. int const x rather than const int x). This applies throughout, not just to constant declarations. This is enforced by clang-format (QualifierAlignment: Right). See Common Pitfalls for how this clarifies pointer-to-const vs const-pointer.
  4. Non-POD constants (e.g. std::string, std::vector, std::unordered_map) must not be declared at file or namespace scope, as they are subject to the static initialization order fiasco. Wrap them in a function that returns a reference to a function-local static:
// Bad: non-POD at file scope — initialization order is undefined a...

Files:

  • tensorrt_llm/usage/llm_args_golden_manifest.json
  • tensorrt_llm/llmapi/llm_args.py
  • tensorrt_llm/_torch/pyexecutor/scheduler/adp_router.py
  • tests/unittest/_torch/executor/test_adp_router.py
**/*.py

📄 CodeRabbit inference engine (CODING_GUIDELINES.md)

Python files are split into legacy and modern linting groups; when editing legacy files, keep changes compatible with the legacy toolchain and update the legacy baseline/configuration artifacts when required.

Files:

  • tensorrt_llm/llmapi/llm_args.py
  • tensorrt_llm/_torch/pyexecutor/scheduler/adp_router.py
  • tests/unittest/_torch/executor/test_adp_router.py
**/*.{cpp,h,cc,cuh,cu,hpp,py}

📄 CodeRabbit inference engine (CODING_GUIDELINES.md)

All TensorRT-LLM source files should contain the NVIDIA copyright header with the current year and Apache 2.0 license text.

Files:

  • tensorrt_llm/llmapi/llm_args.py
  • tensorrt_llm/_torch/pyexecutor/scheduler/adp_router.py
  • tests/unittest/_torch/executor/test_adp_router.py
**/*.{py,cpp,h,hpp,cc,cxx,cu,cuh}

📄 CodeRabbit inference engine (AGENTS.md)

Read and follow CODING_GUIDELINES.md for all C++ and Python code changes.

Files:

  • tensorrt_llm/llmapi/llm_args.py
  • tensorrt_llm/_torch/pyexecutor/scheduler/adp_router.py
  • tests/unittest/_torch/executor/test_adp_router.py
tests/**

⚙️ CodeRabbit configuration file

tests/**: Act as a QA engineer reviewing test changes and coverage for TensorRT-LLM.
Keep feedback actionable: suggest concrete list file names and whether
coverage is sufficient, insufficient, or needs follow-up outside the PR.

Files:

  • tests/unittest/_torch/executor/test_adp_router.py
🧠 Learnings (14)
📚 Learning: 2026-02-13T10:15:37.120Z
Learnt from: ixlmar
Repo: NVIDIA/TensorRT-LLM PR: 11508
File: tests/unittest/_torch/sampler/test_beam_search_util.py:71-71
Timestamp: 2026-02-13T10:15:37.120Z
Learning: In TensorRT-LLM (Python requires >=3.10 and <4 as per setup.py), you can use Python 3.10+ features (e.g., PEP 585 generics like dict[str, int], list[str], etc.) throughout the codebase, and you do not need to add from __future__ import annotations. This applies to all Python files, including tests (e.g., tests/unittest/...); ensure tests and code consistently rely on Python 3.10+ features where applicable.

Applied to files:

  • tensorrt_llm/llmapi/llm_args.py
  • tensorrt_llm/_torch/pyexecutor/scheduler/adp_router.py
  • tests/unittest/_torch/executor/test_adp_router.py
📚 Learning: 2026-04-24T23:54:27.755Z
Learnt from: hnover-nv
Repo: NVIDIA/TensorRT-LLM PR: 13453
File: tensorrt_llm/_torch/modules/mamba/causal_conv1d_triton.py:1016-1018
Timestamp: 2026-04-24T23:54:27.755Z
Learning: In this TensorRT-LLM codebase, treat `get_sm_version()` as an intentional implementation detail: it always queries device 0 to determine the SM version. Since the project assumes homogeneous GPU deployments (all GPUs in a node share the same SM capability), code review should not flag `get_sm_version()` calls for not using the current device, a tensor’s `.device`, or an explicit device argument.

Applied to files:

  • tensorrt_llm/llmapi/llm_args.py
  • tensorrt_llm/_torch/pyexecutor/scheduler/adp_router.py
  • tests/unittest/_torch/executor/test_adp_router.py
📚 Learning: 2026-05-29T08:18:25.109Z
Learnt from: zhenhuaw-me
Repo: NVIDIA/TensorRT-LLM PR: 14733
File: tensorrt_llm/visual_gen/output.py:289-319
Timestamp: 2026-05-29T08:18:25.109Z
Learning: In this repository, Ruff rule A002 ("Function argument shadows a Python builtin") is not enabled in the configured Ruff rules. During code reviews, do not flag potential builtin-shadowing argument names (e.g., parameters like `format`) for A002, and do not recommend adding `# noqa: A002` suppressions—since the rule would not trigger here, such comments would be unnecessary noise, especially on public API surfaces.

Applied to files:

  • tensorrt_llm/llmapi/llm_args.py
  • tensorrt_llm/_torch/pyexecutor/scheduler/adp_router.py
  • tests/unittest/_torch/executor/test_adp_router.py
📚 Learning: 2026-05-29T08:18:27.934Z
Learnt from: zhenhuaw-me
Repo: NVIDIA/TensorRT-LLM PR: 14733
File: examples/visual_gen/serve/async_video_gen.py:36-37
Timestamp: 2026-05-29T08:18:27.934Z
Learning: In NVIDIA/TensorRT-LLM, Ruff’s `[tool.ruff.lint].select` enables only `D, E, F, I, PLE, W` and does NOT include `A` (flake8-builtins). Therefore, builtin-name shadowing issues like `A002` (e.g., using `format` as a function parameter) should not be treated as lint failures for this repo during code review.

Applied to files:

  • tensorrt_llm/llmapi/llm_args.py
  • tensorrt_llm/_torch/pyexecutor/scheduler/adp_router.py
  • tests/unittest/_torch/executor/test_adp_router.py
📚 Learning: 2026-06-25T13:04:55.284Z
Learnt from: taianz-nv
Repo: NVIDIA/TensorRT-LLM PR: 15555
File: tensorrt_llm/_torch/visual_gen/models/wan/wan_vae.py:23-24
Timestamp: 2026-06-25T13:04:55.284Z
Learning: For NVIDIA/TensorRT-LLM Python code, Ruff is configured in pyproject.toml to enable only {D, E, F, I, PLE, W}. In code review, do not request iterator/list-style cleanups tied to disabled Ruff rules B905, RUF005, or RUF007 (e.g., suggesting zip(..., strict=True), itertools.pairwise(), or rewriting `[x] + list_var` into unpacking) unless there is a separate, concrete correctness/performance/security reason. Prefer the repository’s existing plain forms for consistency.

Applied to files:

  • tensorrt_llm/llmapi/llm_args.py
  • tensorrt_llm/_torch/pyexecutor/scheduler/adp_router.py
  • tests/unittest/_torch/executor/test_adp_router.py
📚 Learning: 2026-03-06T11:45:02.068Z
Learnt from: ixlmar
Repo: NVIDIA/TensorRT-LLM PR: 11983
File: tensorrt_llm/_torch/pyexecutor/llm_request.py:237-240
Timestamp: 2026-03-06T11:45:02.068Z
Learning: In tensorrt_llm/_torch/pyexecutor/llm_request.py, LogProbStorage.append() relies on next(iter(prob.values())).logprob to accumulate cum_log_probs when cum_log_probs is None. This path assumes prob is a non-empty dict because TorchSampler places the sampled logprob first when num_logprobs >= 0. Therefore, no guard for empty dicts is needed here. If future changes may yield empty prob, consider adding a guard or a clearer invariant.

Applied to files:

  • tensorrt_llm/llmapi/llm_args.py
  • tensorrt_llm/_torch/pyexecutor/scheduler/adp_router.py
📚 Learning: 2026-03-09T12:34:56.631Z
Learnt from: yibinl-nvidia
Repo: NVIDIA/TensorRT-LLM PR: 12009
File: tensorrt_llm/_torch/visual_gen/models/ltx2/transformer_ltx2.py:296-299
Timestamp: 2026-03-09T12:34:56.631Z
Learning: In tensorrt_llm/_torch/visual_gen/models/ltx2/transformer_ltx2.py, BasicAVTransformerBlock should not be flagged for a config mismatch when config.parallel.dit_ulysses_size > 1. The function setup_sequence_parallelism() returns use_ulysses=True for dit_ulysses_size > 1, or raises a RuntimeError/ValueError/NotImplementedError; it never returns use_ulysses=False in that case. Treat this as intentional and correct; do not flag as a mismatch between raw config checks and setup_sequence_parallelism()'s result.

Applied to files:

  • tensorrt_llm/llmapi/llm_args.py
  • tensorrt_llm/_torch/pyexecutor/scheduler/adp_router.py
📚 Learning: 2026-04-16T00:07:18.998Z
Learnt from: venkywonka
Repo: NVIDIA/TensorRT-LLM PR: 12944
File: tensorrt_llm/_torch/auto_deploy/shim/ad_executor.py:654-679
Timestamp: 2026-04-16T00:07:18.998Z
Learning: When reviewing TensorRT-LLM multimodal handling, do not assume a bug/inconsistency just because `special_token_offsets` appears written in different locations for different backends. In the AutoDeploy path, `special_token_offsets` is written under `multimodal_data['layout_metadata']['special_token_offsets']` by the AD-specific input processor and is read by `ad_executor.py` via the nested `layout_metadata` lookup. In the PyTorch path, it’s written at the top level as `mm_data['special_token_offsets']` (e.g., via `tensorrt_llm/inputs/registry.py`) and is read by `model_engine.py` from the top level. These backends should not share requests, so the reviewer should verify reads/writes match the intended backend’s request structure rather than flaging cross-backend mismatches.

Applied to files:

  • tensorrt_llm/llmapi/llm_args.py
  • tensorrt_llm/_torch/pyexecutor/scheduler/adp_router.py
📚 Learning: 2026-04-24T03:28:03.123Z
Learnt from: yihwang-nv
Repo: NVIDIA/TensorRT-LLM PR: 13373
File: tests/integration/defs/accuracy/test_llm_api_pytorch.py:51-61
Timestamp: 2026-04-24T03:28:03.123Z
Learning: When reviewing TensorRT-LLM attention backend code, treat `_TRTLLM_ENABLE_TRTLLM_GEN_ATTENTION` (in `tensorrt_llm._torch.attention_backend.trtllm`) as a *gate* that enables the `trtllm_gen` path, not as an identifier of the executed backend. The same `TrtllmAttention` class may handle both legacy and `trtllm_gen`, and the actual per-forward branch is also governed by checks like `trtllm_gen.is_supported(...)`. Do not expect public LLM/attention object attributes to reveal which path executed; if test assertions require confirming GEN usage, reviewers should require production-side instrumentation/counters (or other observable signals) rather than relying on existing public fields.

Applied to files:

  • tensorrt_llm/llmapi/llm_args.py
  • tensorrt_llm/_torch/pyexecutor/scheduler/adp_router.py
📚 Learning: 2026-05-16T01:43:01.298Z
Learnt from: yibinl-nvidia
Repo: NVIDIA/TensorRT-LLM PR: 14161
File: tensorrt_llm/serve/cluster_storage.py:5-5
Timestamp: 2026-05-16T01:43:01.298Z
Learning: In the NVIDIA/TensorRT-LLM codebase, do not raise a code review issue for missing NVIDIA Apache 2.0 license headers in Python files (they are intentionally not required/enforced in this repository).

Applied to files:

  • tensorrt_llm/llmapi/llm_args.py
  • tensorrt_llm/_torch/pyexecutor/scheduler/adp_router.py
📚 Learning: 2025-12-12T03:27:08.565Z
Learnt from: tongyuantongyu
Repo: NVIDIA/TensorRT-LLM PR: 9655
File: tensorrt_llm/_torch/pyexecutor/sampler.py:3031-3031
Timestamp: 2025-12-12T03:27:08.565Z
Learning: In files under tensorrt_llm/_torch/pyexecutor, avoid accessing torch.Tensor objects inside for-loops when iterating over requests. Convert batched tensors to Python lists beforehand using tensor.tolist(), and then iterate over those lists. This improves performance by reducing tensor-bound operations inside hot loops. Apply this pattern to similar code paths that process batches to access simple Python data structures (lists) inside loops.

Applied to files:

  • tensorrt_llm/_torch/pyexecutor/scheduler/adp_router.py
📚 Learning: 2026-02-25T01:48:05.078Z
Learnt from: yibinl-nvidia
Repo: NVIDIA/TensorRT-LLM PR: 11683
File: tests/unittest/llmapi/_run_multi_mpi_comm_tasks.py:6-8
Timestamp: 2026-02-25T01:48:05.078Z
Learning: When reviewing cherry-pick PRs that backport commits (PRs that move fixes from one branch to another), do not suggest or require style/formatting changes in the backport. Cherry-picks should preserve the exact commit history and focus on functional correctness; style improvements are lower priority than preserving the integrity of the backported fixes. This guidance applies broadly to Python test files under tests/, ensuring reviews favor minimal, non-formatting changes that maintain correctness.

Applied to files:

  • tests/unittest/_torch/executor/test_adp_router.py
📚 Learning: 2026-05-29T08:18:31.547Z
Learnt from: zhenhuaw-me
Repo: NVIDIA/TensorRT-LLM PR: 14733
File: tests/unittest/_torch/visual_gen/test_trtllm_serve_endpoints.py:1838-1840
Timestamp: 2026-05-29T08:18:31.547Z
Learning: In NVIDIA/TensorRT-LLM, Ruff’s `ruff select` does not enable the flake8-bandit (“S*”) rules, so Bandit checks like S108 are not enforced by the lint gate. During review of test Python code, do not flag `/tmp/...` string literals (or other situations) as Ruff S108 violations unless the repo’s Ruff configuration is updated to select flake8-bandit rules.

Applied to files:

  • tests/unittest/_torch/executor/test_adp_router.py
📚 Learning: 2026-02-27T21:32:25.857Z
Learnt from: lucaslie
Repo: NVIDIA/TensorRT-LLM PR: 11796
File: tests/unittest/_torch/auto_deploy/unit/singlegpu/custom_ops/utils/test_block_table_ragged_conversion.py:713-747
Timestamp: 2026-02-27T21:32:25.857Z
Learning: When reviewing tests in this repository, lightweight benchmark tests (sub-second duration, ~100 iterations) that detect performance regressions should remain part of the standard test suite and should not be gated by environment variables or pytest markers. Only expensive/long-running benchmarks should be gated (e.g., via a pytest marker like pytest.mark.slow or a dedicated marker/flag) so they can be run selectively. This guidance applies to Python tests under tests/ and related subdirectories.

Applied to files:

  • tests/unittest/_torch/executor/test_adp_router.py
📝 Walkthrough

Walkthrough

Adds a configurable policy for assigning new conversations to tensor-parallel ranks. The default remains round-robin; least_queued selects the least-loaded rank while preserving existing conversation-to-rank stickiness.

Changes

Conversation placement policy

Layer / File(s) Summary
Placement configuration contract
tensorrt_llm/llmapi/llm_args.py, tensorrt_llm/usage/llm_args_golden_manifest.json
Adds the typed round_robin/least_queued option and corresponding manifest schema entry.
Router policy wiring and selection
tensorrt_llm/_torch/pyexecutor/scheduler/adp_router.py
Forwards and normalizes the policy, then selects least-loaded or round-robin ranks for new or unpinned conversations.
Placement behavior validation
tests/unittest/_torch/executor/test_adp_router.py
Tests defaults, invalid-value fallback, least-loaded assignment, batch leveling, stickiness, factory forwarding, and deterministic routing.

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

Sequence Diagram(s)

sequenceDiagram
  participant ADPRouter
  participant ConversationAwareADPRouter
  participant RankSelection
  ADPRouter->>ConversationAwareADPRouter: Pass new_conv_placement
  ConversationAwareADPRouter->>RankSelection: Select least-loaded rank when configured
  ConversationAwareADPRouter->>RankSelection: Select round-robin rank otherwise
  RankSelection-->>ConversationAwareADPRouter: Return target rank
Loading
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Description check ⚠️ Warning The description explains the change, but it omits the required Test Coverage and PR Checklist sections. Add a Test Coverage section with the relevant tests and complete the PR Checklist items required by the repository template.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title matches the PR's main change and uses the required [None][feat] format.
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.

@tensorrt-cicd

Copy link
Copy Markdown
Collaborator

PR_Github #58882 [ run ] triggered by Bot. Commit: 01da19e Link to invocation

@tensorrt-cicd

Copy link
Copy Markdown
Collaborator

PR_Github #58882 [ run ] completed with state SUCCESS. Commit: 01da19e
/LLM/main/L0_MergeRequest_PR pipeline #47425 completed with status: 'FAILURE'

CI Report

⚠️ Action Required:

  • Please check the failed tests and fix your PR
  • If you cannot view the failures, ask the CI triggerer to share details
  • Once fixed, request an NVIDIA team member to trigger CI again

CI Agent Failure Analysis

Link to invocation

@lancelly

Copy link
Copy Markdown
Collaborator Author

/bot run --disable-fail-fast

@tensorrt-cicd

Copy link
Copy Markdown
Collaborator

PR_Github #58979 [ run ] triggered by Bot. Commit: 01da19e Link to invocation

@tensorrt-cicd

Copy link
Copy Markdown
Collaborator

PR_Github #58979 [ run ] completed with state SUCCESS. Commit: 01da19e
/LLM/main/L0_MergeRequest_PR pipeline #47510 completed with status: 'SUCCESS'

CI Report

Link to invocation

lancelly added a commit to lancelly/TensorRT-LLM that referenced this pull request Jul 13, 2026
…scheduler queues

Diagnosing attention-DP load imbalance today requires reconstructing
state from per-request metrics. Add three cheap census logs that
expose routing decisions and per-rank queueing directly:

- py_executor iteration log (rides the existing print_iter_log line):
  num_active / num_queued / num_fetched per rank per iteration.
  num_queued counts CONTEXT_INIT requests with no prefill progress --
  requests that have never entered a batch -- sampled at the iteration
  boundary (after this iteration's completions, before the next
  fetch). num_fetched is the number of new requests the ADP router
  assigned to this rank during the iteration (delta of the cumulative
  fetch counter).
- ConversationAwareADPRouter: at most once per CENSUS_INTERVAL_SEC
  (60s), rank 0 logs conv_rank_census (live conversation->rank pins
  per rank) plus the post-assignment per-rank load snapshot.
- ConversationRouter (disagg orchestrator): at most once per
  CENSUS_INTERVAL_SEC (60s), logs conv_server_census (live
  conversation->server pins per instance).

No collectives and no new sync points; the censuses are log-only and
never feed routing. These logs were used to diagnose a 3.4x per-rank
queue skew under near-uniform per-rank conversation counts (see PR

Signed-off-by: Lance Liao <108499334+lancelly@users.noreply.github.com>
NVIDIA#16294).
lancelly added a commit to lancelly/TensorRT-LLM that referenced this pull request Jul 13, 2026
…scheduler queues

Diagnosing attention-DP load imbalance today requires reconstructing
state from per-request metrics. Add per-rank queueing and routing
fields to the existing print_iter_log iteration line:

  num_active = 14, num_queued = 12, num_fetched = 3, num_convs = 438

- num_queued: CONTEXT_INIT requests with no prefill progress --
  requests that have never entered a batch -- sampled at the iteration
  boundary (after this iteration's completions, before the next
  fetch). Counted directly instead of derived from active - scheduled,
  which mixes epochs (completions leave active_requests before the
  line prints; dummy padding is scheduled but never active).
- num_fetched: new requests the ADP router assigned to this rank
  during this iteration (delta of the cumulative fetch counter).
- num_convs: live conversations pinned to this rank by
  ConversationAwareADPRouter, maintained as O(1) incremental counters
  on bind/rebind/LRU-eviction and exposed via
  ADPRouter.num_pinned_conversations() (None for routers without
  pinning). Reading per-rank conversation counts next to queue depth
  distinguishes count imbalance from conversation-weight imbalance.

The disagg orchestrator's ConversationRouter additionally logs a
conversation->server census at most once per 60s.

No collectives and no new sync points; all fields are log-only. These
signals were used to diagnose a 3.4x per-rank queue skew under
near-uniform per-rank conversation counts (see PR NVIDIA#16294).

Signed-off-by: Lance Liao <108499334+lancelly@users.noreply.github.com>
@QiJune
QiJune requested a review from YihuiLu512 July 15, 2026 09:22
Comment thread tensorrt_llm/_torch/pyexecutor/scheduler/adp_router.py

@YihuiLu512 YihuiLu512 left a comment

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.

LGTM

lancelly added a commit to lancelly/TensorRT-LLM that referenced this pull request Jul 23, 2026
…scheduler queues

Diagnosing attention-DP load imbalance today requires reconstructing
state from per-request metrics. Add per-rank queueing and routing
fields to the existing print_iter_log iteration line:

  num_active = 14, num_queued = 12, num_fetched = 3, num_convs = 438

- num_queued: CONTEXT_INIT requests with no prefill progress --
  requests that have never entered a batch -- sampled at the iteration
  boundary (after this iteration's completions, before the next
  fetch). Counted directly instead of derived from active - scheduled,
  which mixes epochs (completions leave active_requests before the
  line prints; dummy padding is scheduled but never active).
- num_fetched: new requests the ADP router assigned to this rank
  during this iteration (delta of the cumulative fetch counter).
- num_convs: live conversations pinned to this rank by
  ConversationAwareADPRouter, maintained as O(1) incremental counters
  on bind/rebind/LRU-eviction and exposed via
  ADPRouter.num_pinned_conversations() (None for routers without
  pinning). Reading per-rank conversation counts next to queue depth
  distinguishes count imbalance from conversation-weight imbalance.

No collectives and no new sync points; all fields are log-only. These
signals were used to diagnose a 3.4x per-rank queue skew under
near-uniform per-rank conversation counts (see PR NVIDIA#16294).

Signed-off-by: Lance Liao <108499334+lancelly@users.noreply.github.com>
lancelly added a commit to lancelly/TensorRT-LLM that referenced this pull request Jul 23, 2026
…scheduler queues

Diagnosing attention-DP load imbalance today requires reconstructing
state from per-request metrics. Add per-rank routing and scheduling
fields to the existing print_iter_log iteration line:

  num_active = 14, num_fetched = 3, num_dummy = 1, num_unscheduled = 5, num_convs = 438

- num_fetched: new requests the ADP router assigned to this rank
  during this iteration (delta of the cumulative fetch counter).
- num_dummy: attention-DP pad dummies in this iteration's scheduled
  batch (0/1 per rank, padded in when the rank would otherwise run an
  empty batch). num_scheduled_requests counts the pad, so subtract
  num_dummy to recover the real scheduled count.
- num_unscheduled: active requests not placed in this iteration's
  batch (len(active_requests) - scheduled batch_size). Sampled at
  schedule time, so the pad cancels in both terms and it never mixes
  epochs the way active - num_scheduled would (num_scheduled printed on
  this line is the previous iteration's).
- num_convs: live conversations pinned to this rank by
  ConversationAwareADPRouter, maintained as O(1) incremental counters
  on bind/rebind/LRU-eviction and exposed via
  ADPRouter.num_pinned_conversations() (None for routers without
  pinning). Reading per-rank conversation counts next to queue depth
  distinguishes count imbalance from conversation-weight imbalance.

No collectives and no new sync points; all fields are log-only. These
signals were used to diagnose a 3.4x per-rank queue skew under
near-uniform per-rank conversation counts (see PR NVIDIA#16294).

Signed-off-by: Lance Liao <108499334+lancelly@users.noreply.github.com>

@QiJune QiJune left a comment

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.

LGTM. The deterministic tie-break can create some cross-batch affinity skew for sparse or bursty traffic, as noted in the discussion, but this is non-blocking for the high-concurrency workload targeted by this change.

@lancelly
lancelly merged commit 93efd33 into NVIDIA:main Jul 23, 2026
11 checks passed
lancelly added a commit to lancelly/TensorRT-LLM that referenced this pull request Jul 23, 2026
…ration log

Diagnosing attention-DP load imbalance today requires reconstructing
state from per-request metrics. Add per-rank routing and scheduling
fields to the existing print_iter_log iteration line:

  num_active = 14, num_fetched = 3, num_dummy = 1, num_unscheduled = 5

- num_fetched: new requests the ADP router assigned to this rank
  during this iteration (delta of the cumulative fetch counter).
- num_dummy: attention-DP pad dummies in this iteration's scheduled
  batch (0/1 per rank, padded in when the rank would otherwise run an
  empty batch). num_scheduled_requests counts the pad, so subtract
  num_dummy to recover the real scheduled count.
- num_unscheduled: active requests not placed in this iteration's
  batch (len(active_requests) - scheduled batch_size). Sampled at
  schedule time, so the pad cancels in both terms and it never mixes
  epochs the way active - num_scheduled would (the num_scheduled
  printed on this line is the previous iteration's).

num_dummy and num_unscheduled are captured at schedule time and so lag
one iteration behind num_active/num_fetched, consistent with
num_scheduled_requests.

No collectives and no new sync points; all fields are log-only. These
signals surfaced a 1.8-3.4x per-rank queue-depth skew on an agentic
multi-turn workload, motivating the least_queued placement option in
NVIDIA#16294.

Signed-off-by: Lance Liao <108499334+lancelly@users.noreply.github.com>
lancelly added a commit to lancelly/TensorRT-LLM that referenced this pull request Jul 23, 2026
…ration log

Diagnosing attention-DP load imbalance today requires reconstructing
state from per-request metrics. Add per-rank routing and scheduling
fields to the existing print_iter_log iteration line:

  num_active = 14, num_fetched = 3, num_dummy = 1, num_unscheduled = 5

- num_fetched: new requests the ADP router assigned to this rank
  during this iteration (delta of the cumulative fetch counter).
- num_dummy: attention-DP pad dummies in this iteration's scheduled
  batch (0/1 per rank, padded in when the rank would otherwise run an
  empty batch). num_scheduled_requests counts the pad, so subtract
  num_dummy to recover the real scheduled count.
- num_unscheduled: active requests not placed in this iteration's
  batch (len(active_requests) - scheduled batch_size). Sampled at
  schedule time, so the pad cancels in both terms and it never mixes
  epochs the way active - num_scheduled would (the num_scheduled
  printed on this line is the previous iteration's).

num_dummy and num_unscheduled are captured at schedule time and so lag
one iteration behind num_active/num_fetched, consistent with
num_scheduled_requests.

No collectives and no new sync points; all fields are log-only. These
signals surfaced a 1.8-3.4x per-rank queue-depth skew on an agentic
multi-turn workload, motivating the least_queued placement option in
NVIDIA#16294.

Signed-off-by: Lance Liao <108499334+lancelly@users.noreply.github.com>
hhzhang16 added a commit to hhzhang16/TensorRT-LLM that referenced this pull request Jul 23, 2026
…nnahz/dep-1083-port-flashinfer-stable-va-lifecycle-for-native-all-reduce

* 'main' of https://github.com/NVIDIA/TensorRT-LLM: (83 commits)
  [None][feat] Bind SourceIdentity to checkpoint artifacts (NVIDIA#16159)
  [None][infra] Waive 4 failed cases for main in pre-merge 49550 (NVIDIA#16798)
  [None][fix] Make FlashInfer sampling op wrappers opaque to Dynamo (NVIDIA#16732)
  [None][feat] top-k: route decode to CuTe DSL GVR top-k in e2e (NVIDIA#16420)
  [None][feat] Default GLM-5 to the Python KV-cache transceiver (NVIDIA#16524)
  [None][chore] Add NVTX ranges to per-iteration ADP sync points in PyExecutor (NVIDIA#16422)
  [https://nvbugs/6426850][test] Unwaive Qwen3.5 397B NVFP4 ADP4 TRTLLM test (NVIDIA#16348)
  [https://nvbugs/6445456][fix] Restore inplace ops for functionalization v2 (NVIDIA#16410)
  [None][infra] Waive 1 failed cases for main in pre-merge 49229 (NVIDIA#16786)
  [None][fix] Load DeepSeek V4 mixed-precision NVFP4 checkpoints (NVIDIA#16433)
  [None][feat] ADP conversation router: configurable least-queued placement for new conversations (NVIDIA#16294)
  [None][infra] Waive 1 failed cases for main in pre-merge 49424 (NVIDIA#16780)
  [None][infra] Waive 1 failed cases for main in pre-merge 49424 (NVIDIA#16781)
  [TRTLLMINF-188][infra] Require approval for PerfSanity wildcard runs (NVIDIA#16777)
  [TRTLLM-13969][feat] Support MiniMax M3 for Disaggregated Serving (NVIDIA#16017)
  [NVIDIA#11932][fix] Filter CUTLASS MoE GEMM tile configs by device shared memory on SM121 (NVIDIA#12704)
  [None][chore] Remove attention backend test waivers (NVIDIA#16723)
  [TRTLLM-14540][perf] Skip fp32 state round-trip in FlashInfer GDN pre… (NVIDIA#16703)
  [TRTLLM-13694][feat] Add IBDB recipe provenance and refresh configs (NVIDIA#16254)
  [None][infra] Preview/bump/main (NVIDIA#16758)
  ...

Signed-off-by: Hannah Zhang <hannahz@nvidia.com>
yuanjingx87 pushed a commit to yuanjingx87/TensorRT-LLM that referenced this pull request Jul 26, 2026
…ment for new conversations (NVIDIA#16294)

Signed-off-by: Lance Liao <108499334+lancelly@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

api-compatible Accepted LLM API contract change that is backwards-compatible

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants