Video wird geladen...

Video konnte nicht geladen werden

Zur Startseite

I built an interactive simulator that shows why LLM inference capacity is hard. Batching, queues, KV cache, GPU decode, priority tiers - all coupled. Change one knob and the bottleneck moves.

25,217 Aufrufe • vor 4 Monaten •via X (Twitter)

23 Kommentare

Profilbild von Khushboo Verma
Khushboo Vermavor 4 Monaten

The core problem: GPUs hate serving one request at a time. Decode is memory-bandwidth-bound, every forward pass streams the whole model's weights from memory to produce... one token. Serve requests sequentially and your $40k GPU idles between tokens.

Profilbild von Khushboo Verma
Khushboo Vermavor 4 Monaten

The fix: batching. One forward pass = one next token for EVERY sequence in the batch. 16 requests, one pass, 16 tokens. The weight reads are shared, so step cost grows much slower than batch size. Throughput is almost free. Almost.

Profilbild von Khushboo Verma
Khushboo Vermavor 4 Monaten

But requests finish at different lengths. Static batching strands empty slots until the longest sequence finishes, wasted bandwidth every step. Continuous batching backfills each slot the moment it frees, between decode steps. Utilization goes from ~60% to ~95%.

Profilbild von Khushboo Verma
Khushboo Vermavor 4 Monaten

And priority tiers make it worse. Strict priority is great for enterprise traffic and starves free-tier users forever under load. Real schedulers bound starvation: weighted fair queueing, max-wait promotion, reserved slots.

Profilbild von Khushboo Verma
Khushboo Vermavor 4 Monaten

The part nobody tells you: the bottleneck doesn't stay put. Long prompts? Prefill steals decode time → inter-token latency spikes Long outputs? Decode-bound → queues explode Small KV cache? Memory blocks admissions while GPUs sit idle Few CPU workers? GPUs starve

Profilbild von Khushboo Verma
Khushboo Vermavor 4 Monaten

So I built a simulator where you can watch all of this happen. ⚙️ Tune request rate, token distributions, GPUs, batch size, wait deadline, tier mix, SLOs, see throughput, TTFT, p99 and a live "current bottleneck" banner respond instantly.

Profilbild von Khushboo Verma
Khushboo Vermavor 4 Monaten

7 one-click failure scenarios included: - decode saturation - prefill storm - CPU starvation - batching tradeoff - tier starvation - KV cache crunch Each one teaches a different capacity lesson in ~10 seconds. Try now! 👀

Profilbild von PsudoMike 🇨🇦
PsudoMike 🇨🇦vor 4 Monaten

KV cache fragmentation is what actually surprises engineers the first time. You've got headroom in theory, but contiguous memory requirements choke it. Spent two weeks tuning batch sizes before realizing the bottleneck was cache eviction, not GPU utilization.

Profilbild von Khushboo Verma
Khushboo Vermavor 4 Monaten

Yeah, complex systems

Profilbild von Harnoor Singh
Harnoor Singhvor 4 Monaten

That’s a great explanation!

Profilbild von Khushboo Verma
Khushboo Vermavor 4 Monaten

glad you liked it :)

Profilbild von Shivay Lamba
Shivay Lambavor 4 Monaten

great visuals!

Profilbild von Khushboo Verma
Khushboo Vermavor 4 Monaten

Thanks, so far, haven't had much luck in video generation using AI models, this one turned out nice

Profilbild von David Uche
David Uchevor 4 Monaten

Nice stuff

Profilbild von Khushboo Verma
Khushboo Vermavor 4 Monaten

Thanks 🙏

Profilbild von NoiselessTrading
NoiselessTradingvor 4 Monaten

Insanely well done,! 🙌 The interactive simulator + failure scenarios make LLM serving concepts finally click. Super valuable tool!”

Profilbild von Khushboo Verma
Khushboo Vermavor 4 Monaten

Thanks :)

Profilbild von Aniket Maurya
Aniket Mauryavor 4 Monaten

great explaination!

Profilbild von Khushboo Verma
Khushboo Vermavor 4 Monaten

Thank you :)

Profilbild von PsudoMike 🇨🇦
PsudoMike 🇨🇦vor 4 Monaten

Seen this in payments. Optimize auth latency and now settlement throughput is the ceiling. Fix settlement, reconciliation piles up. Every component looks fine in isolation. You only see the coupling when one part starts to scale and the others don't follow.

Profilbild von PsudoMike 🇨🇦
PsudoMike 🇨🇦vor 4 Monaten

The KV cache piece is what gets people. Adding more GPUs sounds like the fix but long sequences fill KV memory fast. You end up memory bound before you're ever compute bound. What latency targets are you modeling at different request rates?

Profilbild von Gaurav Nardia
Gaurav Nardiavor 4 Monaten

Khushboo, I DMed you something. Can you please check? I think it's in the request tab.

Profilbild von Ishwar | Infrastructure Systems
Ishwar | Infrastructure Systemsvor 4 Monaten

The moving bottleneck aspect is underrated. A lot of engineering intuition assumes "find bottleneck -> optimize bottleneck." In serving systems, fixing one bottleneck often just reveals the next one.

Ähnliche Videos

Continuous batching in LLMs, clearly explained: (a popular LLM interview question; bookmark this) In traditional ML inference, a batch is a matrix. Every input is padded to the same length, one forward pass runs, and every row finishes at the same moment. LLM decoding does not work that way. One forward pass produces one token per sequence, so a request needs as many passes as it has output tokens, and nobody knows that count until the model emits a stop token. Under static batching, membership is fixed when the batch starts. A request that finishes in 30 tokens holds its slot until the slowest request in the same batch finishes at 400. The GPU keeps paying the full weight read for a batch that is mostly empty. Loading model weights out of HBM costs the same whether four slots are producing tokens or one. Continuous batching moves the decision boundary. Instead of scheduling once per batch, the scheduler runs a single forward pass, gets control back, and decides again. A finished request leaves at the next iteration boundary, and a queued request takes its slot right there. No slot stays reserved for work that is already done. Anyscale benchmarked both OPT-13B on a single A100. With uniform generation lengths, the two policies came out about level (as expected), and as output length variance rose, static batching fell to around 81 tokens per second while vLLM reached 23x the throughput of naive Hugging Face serving. Variance drives the entire gap. Production traffic mixes 30-token replies with 400-token ones, which is exactly the condition static batching handles worst. None of this alters the model. vLLM, SGLang, TGI, and TensorRT-LLM all run it by default, and NVIDIA ships the same mechanism under the name in-flight batching. The animation below runs both policies on the same 16 requests and the same 4 slots, stepping in lockstep. The only difference is when a new request is allowed in. To dive deeper into continuous batching specifically, I wrote a full breakdown of the scheduler underneath it. It covers what happens between two forward passes, how tokens get handed out against a fixed budget, why the scheduler needs no separate path for prefill and decode, and what preemption costs you when the KV cache fills up mid-generation. Read it below.

Avi Chawla

16,140 Aufrufe • vor 2 Monaten

Researchers made LLM inference 14x faster and 90% cheaper. The video below depicts the speed up in action. Providers discount cached input tokens by as much as 90% because a cache hit skips prefill compute entirely. For stable system prompts and tool definitions, hit rates of 60 to 85% are achievable, which makes it the highest-leverage inference optimization. But the cost saving only works when the cached text is an exact, byte-for-byte prefix of the new request. If you change one character anywhere before it, the entire cached region is missed. Three common request patterns produce full cache misses: - A query that needs documents A and B together can't reuse B's standalone cache, because those KV entries were computed without A in front of them. - The same three documents retrieved in a different order produce a full cache miss, even though nothing about the documents changed. - In multi-turn conversations, every new turn invalidates whatever was cached beyond the stable prefix. Alibaba's production data did a study on this and found that just 10% of cached KV blocks serve 77% of all cache hits. So most of what gets cached sits in storage and is never used a single time. And the root cause is that KV entries are position-dependent. Each token's KV encodes attention to everything before it, so a cached block is only valid in the exact context it was computed in. There's a second, less discussed problem as well. Cache management runs inside the inference engine's process. Moving KV tensors between GPU, CPU, and disk competes with inference for the same resources. This is why Google's TurboQuant compresses KV caches to 3 bits with no accuracy loss and still causes a 20%+ slowdown when it runs in-process. Fixing both problems means restructuring where caching lives. Cache management moves into its own process, the engine only exchanges block IDs over shared GPU memory, and heavy data movement runs across GPU, CPU, disk, and remote storage in parallel. Non-prefix reuse gets handled by selectively recomputing only the small set of tokens that attend across document boundaries. LMCache is the open-source project (10k+ stars) that implements this exact architecture, and it plugs into vLLM, SGLang, and TensorRT-LLM. The selective recomputation part is implemented in its CacheBlend technique, which makes cached docs in any order and combination, with 2-4x faster multi-document processing. On H200s running Qwen3-235B with 50 concurrent users, LMCache's multiprocess mode delivers 14x faster time-to-first-token and 4x faster decoding compared to in-process caching. GitHub repo: (don't forget to star 🌟) My co-founder wrote a full breakdown of KV cache management. It covers the disaggregated architecture behind the 14x speed up, how CacheBlend preserves generation quality while skipping recomputation, and how to turn every document in a knowledge base into a reusable cached asset. Read it below.

Avi Chawla

30,717 Aufrufe • vor 3 Monaten

i spent 3 hours finding the sweet spot for hermes 4.3 36B on a single RTX 3090. saving you the trouble, anon. the model is 21.8GB at Q4_K_M. that leaves 2.2GB free on 24GB VRAM. not much room for KV cache. here's what actually happened: 4K: 35.3 tok/s 8K: 35.2 tok/s 16K: 34.8 tok/s 32K: 34.6 tok/s 64K: 6.4 tok/s 128K: 1.9 tok/s flat from 4K to 32K. then it falls off a cliff at 64K. the trick is quantized KV cache. without it you OOM at 16K. with quantized KV cache you get 32K at full speed. all 64 layers on GPU. at 64K something weird happens. ngl 99 (all layers on GPU) = 3.96 tok/s. the KV cache silently spills to CPU. drop to ngl 55 and speed jumps to 6.37. drop to ngl 48 and it gets worse again (3.46). there's an offload sweet spot where you free just enough VRAM for the cache without losing too much compute to PCIe transfers. 128K works at ngl 32 but you're at 1.95 tok/s. half the model on CPU. usable for batch work, not for interactive. the sweet spot command: llama-server -m hermes-4.3-36b-Q4_K_M.gguf -ngl 99 -c 32768 --cache-type-k q4_0 --cache-type-v q4_0 32K context. 34.6 tok/s. all on GPU. this is where dense 36B lives on 24GB. for comparison, qwen 3.5 (35B MoE, 3B active) holds 112 tok/s from 4K all the way to 262K on the same GPU. no speed drop. same total params, completely different architecture. hybrid linear attention means flat context scaling. dense pays for every token in the KV cache. code and quality comparison coming next. fast vs slow generation side by side in the videos below.

Sudo su

52,268 Aufrufe • vor 7 Monaten