Repository navigation
feat(router): add a KV-capacity-aware decode worker-selection policy - #18224
Draft
john-liu-dev wants to merge 1 commit into
Draft
john-liu-dev wants to merge 1 commit into
john-liu-dev wants to merge 1 commit into
Conversation
The default decode cost D + W*N has no notion of a rank's KV capacity. With a large W a rank can be booked past what it holds while other ranks have room; with a small W request counts drift apart across ranks. No single W balances both. Add dynamo-kv-capacity-aware, an opt-in builtin worker-selection policy selected through --router-policy-config: - A rank fits when decode_cost_blocks (booked blocks plus this request's) is at most capacity_fraction x its capacity. - Among fitting ranks, fewest active requests first (count_priority), then D + W*N. Ties are uniform, as in the default picker. - When no rank fits, the rank with the smallest decode_cost_blocks. Selection never waits or fails on a non-empty candidate list. - Capacity is the rank's advertised total_kv_blocks (WorkerInfo). The capacity_blocks parameter covers ranks that do not report it. With neither, the rank is not filtered and a warning is logged once per rank. - Preferred-taint multipliers scale the cost among fitting ranks only; the fallback ignores them. capacity_fraction: null with count_priority: false selects exactly like the default plain-decode cost. No new dependencies. Tests: 37 boundary vectors checked against an independent reference implementation, random-state invariants, seeded reproducibility, selection through the host policy, capacity-source precedence, YAML resolution and parameter validation. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: Yuehua Liu <liujohn@nvidia.com>
john-liu-dev
temporarily deployed
to
external_collaborator
November 5, 2026 16:47 — with
GitHub Actions
Inactive
john-liu-dev
temporarily deployed
to
external_collaborator
November 5, 2026 16:47 — with
GitHub Actions
Inactive
Contributor
|
👋 Hi john-liu-dev! Thank you for contributing to ai-dynamo/dynamo. Just a reminder: The 🚀 |
This branch was previously deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Overview
Under data-parallel attention, the default decode cost
D + W·Nignores each rank's KV capacity: a rank can be booked past what it holds while others have room, and no singleWbalances both request counts and KV blocks. This PR addsdynamo-kv-capacity-aware, an opt-in builtin worker-selection policy for decode pools, selected through--router-policy-config. It places a decode request only on a rank the request fits on, judged by the rank's advertisedtotal_kv_blocks, preferring fewer active requests and thenD + W·N; when no rank fits, it picks the rank with the smallest resulting footprint instead of waiting.Key Changes
About 300 lines of core logic: 296 in the new
kv_capacity_aware.rsand 2 inlib.rs, excluding tests, comments and blank lines. They cover the selection rule, the picker, and the parameters, types and registration. No router-core change and no new dependencies.kv_capacity_aware.rs: the new picker.decode_cost_blocks ≤ capacity_fraction × capacity.WorkerInfo::total_kv_blocks, orcapacity_blockswhen a rank does not report it.decode_cost_blocks.lib.rs: registersdynamo-kv-capacity-awarein the custom catalog. Default routing is unchanged.docs/fern/pages/developer-guide/knowledge-base/modular-components/router/configuration-and-tuning.md: pending.Scope and compatibility:
decode_cost_blocksis 0 on every rank, so the policy degrades to fewest requests.--router-track-output-blocks.capacity_blocksis set.Parameters and an example
All parameters are optional; an unknown key fails startup.
capacity_fraction1.0nulldisables the filtercount_prioritytruedecode_active_request_weight0WinD + W·N. The--router-decode-active-request-weightflag does not set itcapacity_blockstotal_kv_blocksValidation
D + W·ND + W·Ndecode_cost_blocks; never errors or waitscapacity_fraction: null,count_priority: falseD + W·N, random among tiestotal_kv_blocks, or 0capacity_blocks; with neither, not filtered, one warning per rankKey tests and the regression each catches:
boundary_vectors_match_the_reference_tie_sets(37 cases: at capacity, all over, unknown capacity, taints): any change in the tie set, the fallback or the warned ranks.degenerate_parameters_tie_exactly_like_the_default_cost: drift from the default's tie set with the filter and count priority off.never_fails_and_prefers_fitting_ranks: a failed pick, or a non-fitting rank beating a fitting one.capacity_is_total_kv_blocks_then_the_parameter:capacity_blocksoverriding an advertisedtotal_kv_blocks, or a reported 0 used as a capacity.resolves_alongside_the_decode_weight_flag: the policy ignored or rejected alongside the deprecated decode-weight flag.Not run yet (draft):
mainrejects custom policies, so this needs the replay support in feat(router): port published routing policies as worker-selection plugins #15450 or a separate harness.kv_capacity_awarecases inlib/router-plugins/builtin/benches/default_selection.rs, against the default decode policy.Issues and Ongoing Work
capacity_fraction; it never waits or rejects.active_decode_blocks()and a queueing decode busy threshold. This PR reads the same row, but counts the incoming request and only picks the rank.--active-decode-blocks-threshold. Selection skips a worker past them and returns an overload error when none remains. This PR filters per request and never rejects.max_kv_cache_tokensoverride, an active-request decode cost and ISL rank pools. This PR offers a similar guard, a fallback capacity and request ordering as an opt-in plugin that never rejects.worker_capacity().mainnow exposes that capacity throughWorkerInfo, which this PR reads.TODO(rank-aware-kv-capacity)onmain:total_kv_blocksmay be an aggregate or representative-rank estimate, so this PR only steers with it.Pull Request Checklist
/pr-checklistskill.