feat(router): add per-worker PD Prefill admission - #1961
Conversation
|
Caution The consumer version of Gemini Code Assist on GitHub has been sunset. All code review activity has officially ceased. |
|
Important Review skippedDraft detected. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Organization UI Review profile: ASSERTIVE Plan: Pro Plus Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
dbbf675 to
9b65970
Compare
9b65970 to
9d915f3
Compare
9d915f3 to
aae5ff1
Compare
fd361b0 to
1a99f49
Compare
Signed-off-by: Jun Liu <jun.c.liu@rakuten.com>
f66e0a2 to
868f326
Compare
Description
PD and EPD routing has no way to bound how many Prefill requests one SMG process
assigns to a single Prefill worker. When a Prefill worker is saturated, SMG keeps
dispatching to it and the extra requests queue inside the inference engine, where
SMG can neither observe nor bound their wait.
This PR adds an optional per-worker Prefill in-flight limit and a bounded,
Router-wide FIFO admission queue in front of it.
Behavior
Options
--prefill-max-inflight-requests-per-worker-1--prefill-queue-size0disables waiting.100when enabled--prefill-queue-timeout-secs60when enabledA positive per-worker limit enables admission and the queue. Queue options
without a positive limit are rejected at startup, as is combining admission with
--priority-scheduler-enabledor a non-PD/EPD routing mode.Accounting
parallel samples requested through
ndo not multiply slots: every backendsub-request of one client request shares the same reservation.
or is cancelled. It is not held for the Decode phase.
admission is disabled, remain one unit per backend sub-request.
--dp-aware, everyregistered rank is a separate worker and gets its own limit.
Selection and queueing
state, filters workers that are already at the limit, and only then runs the
Prefill policy. Candidate filtering, policy selection, and slot reservation run
under one lock, so a stateful policy such as
cache_awarenever commits arouting decision that then fails to reserve capacity.
consistent_hashing,X-SMG-Target-Workerstays strict: the request waitsfor that worker instead of moving to another one.
registered, removed, replaced, or changes health state.
moves from open to half-open does so lazily on its next state check and emits
no registry event, so recovery would otherwise be invisible to a waiting
request. Only the head polls, so the rest of the queue stays asleep.
Errors
429withpd_prefill_queue_full.429withpd_prefill_queue_timeout.503availability error and is not queued.Scope
Decode scheduling stays with the inference engine.
EPD.
rejected candidate no longer briefly inflates Decode load.
/v1/responseshandlers now wait for the backend request tostart before they return. They previously returned
200and an SSE streamimmediately, which would have turned an admission
429into a200followedby an SSE
errorevent. Any failure to start the backend request now reachesthe client as its real HTTP status.
Metrics
smg_pd_prefill_admission_inflightworkersmg_pd_prefill_admission_queuedsmg_pd_prefill_admission_wait_secondssmg_pd_prefill_admission_rejections_totalreasonThese measure SMG admission only. Engine-side queue metrics are unchanged.
Test Plan
Run against this branch:
cargo fmt --all -- --checkcargo clippy --all-targets --all-features -- -D warningscargo check -p smg -p smg-golang -p smg-pythoncargo test -p smg --libcargo test -p smg --test routing_testspytest bindings/python/testson a Python 3.9 abi3 wheel built from this commitNew unit tests cover strict FIFO order, no queue bypass, queue full, queue
timeout, cancellation cleanup, re-selection without worker binding, one slot per
client request, zero-size queue rejection, release visibility after a drop, and
the availability path. Configuration tests cover the startup validation rules.
End-to-end run
Started the router from the built wheel against two mock workers: a Prefill
worker with a 3 s generation delay and an immediate Decode worker.
With
--prefill-max-inflight-requests-per-worker 1 --prefill-queue-size 1 --prefill-queue-timeout-secs 2and three overlapping requests:200429pd_prefill_queue_timeoutafter 2.0 s429pd_prefill_queue_fullWith
--prefill-max-inflight-requests-per-worker 1 --prefill-queue-size 4 --prefill-queue-timeout-secs 30and three overlapping requests: all returned200, finished in arrival order, and took 9 s in total for three 3 s Prefills.A sample taken while they were in flight reported
smg_pd_prefill_admission_inflight = 1andsmg_pd_prefill_admission_queued = 2;the two queued requests waited 8.1 s in total.
Startup validation, each rejected with its own message:
--priority-scheduler-enabled--prefill-queue-sizewithout a positive per-worker limitWith no admission options the router starts and serves a PD request as before,
and with a per-worker limit above the offered load it serves the same request.
Checklist