feat(server): separate model placement and load balancing - #720
Merged
davide221 merged 2 commits intoSep 10, 2026
Conversation
Graffioh
force-pushed
the
codex/primary-capacity-routing
branch
3 times, most recently
from
September 9, 2026 10:49
3e29d81 to
133474c
Compare
Graffioh
marked this pull request as ready for review
September 9, 2026 13:08
Contributor
There was a problem hiding this comment.
All reported issues were addressed across 22 files
Reply with feedback, questions, or to request a fix.
Re-trigger cubic
Graffioh
force-pushed
the
codex/primary-capacity-routing
branch
from
September 9, 2026 13:48
133474c to
b11e146
Compare
Contributor
There was a problem hiding this comment.
All reported issues were addressed across 4 files (changes from recent commits).
Reply with feedback, questions, or to request a fix.
Re-trigger cubic
Graffioh
force-pushed
the
codex/primary-capacity-routing
branch
3 times, most recently
from
September 10, 2026 11:37
de1e6e9 to
6efec67
Compare
Contributor
There was a problem hiding this comment.
All reported issues were addressed across 10 files (changes from recent commits).
Tip: Review your code locally with the cubic CLI to iterate faster.
Re-trigger cubic
Graffioh
force-pushed
the
codex/primary-capacity-routing
branch
from
September 10, 2026 11:51
6efec67 to
9cba62c
Compare
Graffioh
force-pushed
the
codex/primary-capacity-routing
branch
from
September 10, 2026 11:53
9cba62c to
dd2f449
Compare
6 tasks
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.
This PR lets one
dflash_serverprocess serve several models through one HTTP address. You choose where each model loads, which model gets requests first, and whether requests may fall back to another model when the preferred model is busy.For example, Qwen can stay on the R9700 and DeepSeek4 on Strix Halo. Changing the primary GPU reverses request priority while keeping both model placements unchanged.
Request behavior
--routing-queue-limit. A full waiting queue returns HTTP 503.The generation request's
modelfield does not select or pin a model. Omitted names,auto, configured names, and other client aliases all follow the operator's priority. The response identifies the model that actually answered. This applies to Chat Completions, Messages, and Responses.Fallback happens before response headers or prefill. Each attempt renders and tokenizes the original request with the selected model's own template, tokenizer, and defaults. Validation errors and backend failures other than admission-capacity rejection terminate the request without fallback.
Launch options
Each
--model <path>starts a model block. Model-specific options following it apply to that model until the next--model.--model <path>--load-balancing-primary-gpu <backend:gpu>--load-balancing--routing-queue-limit <N>The old
--primary-gpu,--load-balancing-next-model, and--next-modelspellings are rejected.Example: Qwen on R9700, DeepSeek4 on Strix Halo
This example assumes R9700 is
hip:0and Strix Halo iship:1. Replace the paths and device IDs with those on the host.Here Qwen can hold up to four active reservations, and DS4 one. KV pressure can trigger fallback before all four Qwen slots are occupied. Change only the primary flag to
--load-balancing-primary-gpu hip:1to try DS4 first. Remove--load-balancingto load and serve only that selected primary.Ownership and observability
The listener reuses the existing model loaders and workers. Each model owns its tokenizer, defaults, backend, and scheduler. A listener reservation lasts through engine retirement and output draining, so a disconnect cannot expose capacity while GPU work is still running. The scheduler owns actual KV admission. GPU draft top-K and CUDA sampling scratch are owned by each worker thread and released on their allocation device when the worker exits. Native single-request workers finish active requests during SIGTERM, including terminal response events; genuine client disconnects still cancel generation, and routing waiters receive 503.
/v1/modelslists the loaded models./propsand/status/jsonexpose their placement, priority order, capacity, in-flight reservations, and waiting counts. In multi-model serving, token counting requires an explicit model name and uses that model's tokenizer without fallback.Limits
Waiting is in memory, without a server queue deadline or FIFO guarantee. Capacity release wakes waiters; a 250 ms retry also observes engine capacity changes, disconnects, and shutdown. Slow readers can retain reservations while output drains.
This change selects a model before generation. It does not migrate active streams, suspend requests to SSD, or recover universally from GPU OOM. Admission protects the prompt and rolling decode headroom; later cache exhaustion keeps the existing error/retirement behavior. Cross-model continuation would require text replay because KV/recurrent states are incompatible.
Environment settings remain process-wide. With balancing enabled, startup rejects unsupported shared-policy combinations, including KVFlash/Spark CLI controls, compression, remote drafts, and target splitting. With balancing disabled, the selected primary retains single-model CLI features; unused blocks do not apply environment policy. No throughput or latency improvement is claimed.
Validation
[DONE]after SIGTERM. Their complete outputs match the clean pre-PR reference exactly; the prior head stopped at 104 and 101 generated tokens respectively.The server was rebuilt with the clean PR dependencies for both
gfx1201andgfx1151. Native NVIDIA execution passed on DGX GB10 in CI; all 10 local sampler checks also passed using a disposable HIP adaptation. Tests use the repository-converted GGUF DFlash2 draft because the existing safetensors loader does not load its selector.Usage and detailed boundaries: MODEL_LOAD_BALANCING.md. The loader is adapted from commit
63151ff8, preserved behind luce_box#103 and luce_box#105.