frontproxy: intelligent per-shared-GPU model-swap queue (batch, then swap)
Builds on the cross-engine clean-swap eviction: instead of two engines on one
shared card ever running forwards concurrently (→ VRAM contention → OOM →
disk-thrash), the front now serializes model OWNERSHIP of a shared GPU while
batching to avoid per-request thrash.
New GpuSwapGate (frontproxy/reqqueue.py), one per shared-GPU group (keyed by the
co-located engines' CODERAI_ENGINE_GPUS selector, created only when an engine has
a sibling on its card):
* A request for the model that currently OWNS the GPU runs immediately — a swap
isn't needed (a lone stream never stalls). Concurrency stays capped downstream
by the existing per-model FrontQueue.
* A request for a DIFFERENT model queues. The owner keeps being served up to
`cap` requests (server.gpu_swap_batch, default 10) while another model waits,
then — once the owner is fully idle (never mid-request) — the GPU SWAPS to the
waiting model (which evicts + loads), serves it, and round-robins BACK if the
original has requests queued. No thrash (batch), no starvation (cap).
Wired into all four dispatch paths (broker, broker-stream, direct stream with
keepalive, direct non-stream) for every GPU-inference kind (text/image/video):
acquire the swap slot before the per-model queue, release in the finalizer;
cancelling a pending acquire (client disconnect) drops the waiter with no leak.
The text-stream path emits keepalives while waiting out a swap so the client
doesn't time out.
Scheduler validated by async unit tests: cap engages at exactly N with a
competitor waiting; a lone same-model stream runs unbounded; round-robin
alternates; cancelled waiters leak no slot.
Co-Authored-By:
Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RdMufYvtTbtGDWsiZVoXce
Showing
Please
register
or
sign in
to comment