vLLM vs llama.cpp: Huge Context Efficiency Differences on Qwen3.5-4B AWQ

Posted by SageQuestN@reddit | LocalLLaMA | View on Reddit | 8 comments

Hey folks, I’ve been testing Qwen3.5-4B AWQ / Q4_K_M on a single RTX 3060, and the difference between vLLM and llama.cpp is crazy when it comes to handling large contexts. Thought I’d share the numbers because it’s not obvious until you dig in.

Setup

Model: Qwen3.5-4B AWQ / Q4_K_M

GPU: RTX 3060 (12 GB)

vLLM version: latest stable

Context goal: 100k–250k tokens

vLLM flags: --enable-prefix-caching --max_seq_len 110k

Observations

vLLM

KV memory allocated: \~3.23 GB

Max tokens it can handle: \~23k

Reason:

Allocates KV cache for all layers (32 layers)

Adds padding layers, CUDA graph pool, and prefill overhead (\~50% extra memory)

Even with prefix caching, the effective token limit is much lower than theoretical

Result: huge drop compared to model’s native capacity (\~250k tokens)

llama.cpp

KV memory tight: \~16 KB per token for attention layers only

Total memory usage (model + KV + workspace) for 250k tokens: \~10.8 GB ✅

Supports huge context without crashing

Reason:

Only stores KV for attention layers, FFNs are recomputed

Minimal padding/overhead

Efficient checkpoint/recompute strategy

Quick Math

Model architecture (simplified for attention KV):

Layers: 32

KV heads: 4

Head dim: 256

dtype: fp16 → 2 bytes

KV per token: 2 × 32 × 4 × 256 × 2 = 64 KB

vLLM (\~3.23 GB): \~23k tokens max

llama.cpp (attention-only, recompute FFNs): \~16 KB per token → 250k tokens feasible

Takeaways

vLLM is amazing for async scheduling, prefix caching, and small/medium context (\~20–50k tokens).

llama.cpp is far more efficient for ultra-long contexts (>100k tokens) thanks to attention-only KV and recompute strategies.

Hybrid architectures like Qwen3.5 DeltaNet make vLLM’s “full KV per layer” approach painfully inefficient.

On a single RTX 3060, you can push 250k tokens with llama.cpp, but vLLM crashes at \~23k.