Why Your GPU Idles During LLM Inference: Static vs Dynamic vs Continuous Batching

This article explains why GPUs underutilize during LLM inference and compares static, dynamic, and continuous batching strategies, detailing their trade-offs, the role of KV cache, iteration-level scheduling, and chunked prefill to optimize throughput for variable-length outputs.

AI Architecture Hub
AI Architecture Hub
AI Architecture Hub
Why Your GPU Idles During LLM Inference: Static vs Dynamic vs Continuous Batching

Why Batching Exists

Modern GPUs like the A100 deliver ~312 TFLOPS of BF16 compute but only ~2 TB/s memory bandwidth. Decoding is entirely memory-bound: reading model weights dominates latency, leaving compute units idle. Batching amortizes the weight-read cost across multiple sequences — weights are loaded once and reused for all sequences in a forward pass.

Throughput rises sharply with batch size until a knee point where the workload shifts from memory-bound to compute-bound. Below the knee, batching is nearly free; above it, each additional sequence costs compute time. The knee varies by model, GPU, and sequence length, so measure on your hardware.

Throughput vs batch size curve showing knee point
Throughput vs batch size curve showing knee point

What Breaks for LLMs

Traditional batching works for classifiers/embeddings because: one forward pass yields the full answer, rows are independent, and per-row cost is known upfront. Autoregressive LLMs break all three:

One forward pass produces one token, not the answer (e.g., 400 tokens = 400 passes).

Rows depend on their own history via KV cache written each pass.

Cost is unknown until the model emits a stop token (could be 12 or 4000 tokens).

Padding only equalizes input width, not the time a request occupies the GPU. A fixed batch runs at the speed of its slowest member.

Padding does not solve variable output length problem
Padding does not solve variable output length problem

Static Batching

Collect a fixed set of requests, run together, return all when the last finishes. Fast finishers wait for the slowest, wasting GPU slots and increasing user latency. Waste grows with output-length variance. Anyscale measured OPT-13B on 40GB A100: increasing output-length disparity dropped static batching to ~81 tokens/sec, while continuous batching maintained an order of magnitude higher throughput.

Static batching timeline showing idle slots
Static batching timeline showing idle slots
Anyscale benchmark: static vs continuous batching throughput
Anyscale benchmark: static vs continuous batching throughput

Static batching remains suitable for fixed-output tasks (classification, embedding, scoring) where every request finishes almost simultaneously.

In vLLM, configure static batching by passing the entire workload to llm.generate at once, setting a max_tokens ceiling, and keeping prompt sizes similar so each sequence finishes at nearly the same time.

Dynamic Batching

Adds a timer: batch fires when size limit reached or window expires. Reduces queue wait for early arrivals but still holds the batch until all members finish. The slow-member problem persists. Dynamic batching makes one decision per batch then hands off to the engine — fine for fixed-output models (e.g., Triton).

Dynamic batching timeline
Dynamic batching timeline

Continuous Batching

Scheduler runs one iteration, reclaims control, and decides again. When a sequence emits its final token it leaves the batch; waiting requests fill the slot next iteration. Batch composition changes every iteration — iteration-level scheduling. No slot waits for the slowest sequence, keeping GPU saturated even with highly variable output lengths.

Continuous batching timeline
Continuous batching timeline

Limitation is memory, not compute. Each active sequence holds a growing KV cache; the cache pool (not math) determines how many sequences fit. On a 40GB A100 with a 13B model, only a few long sequences fit. When cache pool exhausts, the scheduler evicts a running request and recomputes its prefill later — effectively doing the same prefill twice.

Chunked Prefill

Continuous batching introduces stalls: a new request with a long prompt (e.g., 32K tokens) monopolizes an iteration for prefill, blocking all active decoding. Chunked prefill splits the prompt into fixed-size token chunks (e.g., 2K tokens) scheduled across multiple iterations, extending the KV cache incrementally. Attention remains correct because later chunks attend to earlier chunks' KV entries. First token arrives after the last chunk.

Monolithic prefill blocking decoders
Monolithic prefill blocking decoders
Chunked prefill splitting prompt across iterations
Chunked prefill splitting prompt across iterations

Prefill is compute-intensive, decode is memory-intensive; mixing both in a batch utilizes both parts of the chip.

Compute vs memory utilization in mixed batch
Compute vs memory utilization in mixed batch

Smaller chunks give scheduler more decode opportunities, reducing inter-token latency (ITL) spikes.

Larger chunks process new prompts more efficiently, usually improving time-to-first-token (TTFT), but active decoders wait longer between tokens.

Too-small chunks may lower GPU utilization and increase attention overhead because later chunks must re-read KV entries created by earlier chunks.

Chunked prefill is enabled by default in vLLM V1 via --max-num-batched-tokens limiting tokens per iteration. SGLang uses --chunked-prefill-size (-1 disables).

Conclusion

The three strategies differ only in when they fix the batch, each suiting different workload shapes. For real-time traffic with variable output lengths, continuous batching is the only strategy that sustains performance, and every mainstream engine now provides it by default.

Summary comparison of three batching strategies
Summary comparison of three batching strategies
Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

vLLMLLM InferenceGPU utilizationcontinuous batchingSGLangdynamic batchingbatchingKV cachechunked prefillstatic batching
AI Architecture Hub
Written by

AI Architecture Hub

Focused on sharing high-quality AI content and practical implementation, helping people learn with fewer missteps and become stronger through AI.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.