Vol. 14 · LLM Foundations

LLM Internals: KV Cache & Generation

An in-depth analysis of the mechanics of inference: how exactly KV-cache works and why O(n²) without it, prefill vs decode phases, GPU memory arithmetic, GQA/MQA/PagedAttention, prompt caching at the API level (Anthropic + OpenAI), sampling from logits to token, speculative decoding, and the main case - “mother washed the frame” through LLM step by step.

Retrieval answer

An in-depth analysis of the mechanics of inference: how exactly KV-cache works and why O(n²) without it, prefill vs decode phases, GPU memory arithmetic, GQA/MQA/PagedAttention, prompt caching at the API level (Anthropic + OpenAI), sampling from logits to token, speculative decoding, and the main case - “mother washed the frame” through LLM step by step.

01

KV-Cache: mechanics and why without it O(n²)

4 cards
01KV-CacheWhy is autoregressive generation without KV-cache catastrophically slow?2 visuals1 source note

Decoder models generate one token at a time. Without optimization, each step requires a complete recalculation of attention for ALL previous tokens. 200 response tokens = 200 × N² operations. KV-cache is a solution that turns this into linear cost.

Decode workbenchReuse the past instead of projecting it again.

Add output tokens, then compare cached and uncached decode.

Decode mode
Sequence
K projection
V projection
Current queryq₄Attention read
This step
Cumulative K/V projections
Reused slots

KV cache keeps prior keys and values. The new query still reads the growing sequence, but old K/V projections are not recomputed.
Source-complete notespractical effect

practical effect

  • 10-100× decode phase acceleration
  • price: GPU memory - cache grows with length
  • cache is stored per-layer, per-head
02KV-CacheWhat is stored in KV-cache: anatomy1 source note

KV-cache is not a “query cache”, it is a specific data structure: two tensors K and V for each layer, each head, each token. Q is NOT put into the cache - only Q of the new token is needed for the next step.

Source-complete notescache structure
cache structuretext
# Cache form for one model:
kv_cache.shape = [
  2, #K and V (two tensors)
  num_layers, #32 for Llama-3 8B
  num_kv_heads, #8 (GQA) or 32 (MHA)
  seq_len, # current length (growing!)
  d_head #128 = 4096 / 32
]

# Q is NOT cached because:
# Q is only needed to calculate the current step
# q_i = W_Q t_i - only for new token i
# K and V are ALWAYS needed with each new token

# At each decode step:
kv_cache.K[layer][head].append(k_new)
kv_cache.V[layer][head].append(v_new)
# seq_len increases by 1 → cache grows
03KV-CacheCausal Mask and KV-cache: why Query should not be stored1 visual

Causal mask in the decoder-only model provides a key property: when generating token t_i, attention weights to t_i do not affect t₀..t_{i-1} - they have already been generated. This makes caching K and V correct.

Visual model · Process flowFollow the sequence behind Causal Mask and KV-cache: why Query should not be stored and locate where work or state changes.
Complete view · 5 layers
04KV-CacheKV-cache and context length: what breaks at 128K2 source notes

As the context window grows, KV-cache grows linearly. At 128K tokens, the cache becomes huge - more than the weights of the model itself. This is what makes long-context inference so expensive.

Source-complete notescache growth at different lengths · why GQA saves the day
cache growth at different lengthstext
# KV-cache size formula (fp16):
kv_bytes = 2 × L × H_kv × S × d_h × 2

# Llama-3 8B: L=32, H_kv=8 (GQA), d_h=128
S= 4,096: 2 × 32 × 8 × 4096 × 128 × 2 = 537 MB
S= 32,768: 2 × 32 × 8 × 32768 × 128 × 2 = 4.3 GB
S=128,000: 2 × 32 × 8 × 128,000 × 128 × 2= 16.8 GB
                                     ↑ MORE models (8GB)

# GPT-4 levels (96 layers, 128 heads, d_h=128, MHA):
S=128,000: 2 × 96 × 128 × 128,000 × 128 × 2= ~640 GB
          ← requires several A100 only for KV-cache!

why GQA saves the day

  • GQA: H_kv=8 instead of 32 → 4× smaller cache
  • MQA: H_kv=1 → 32× smaller cache
  • compromise: slightly worse quality vs MHA
02

Prefill vs Decode: two different worlds

3 cards
05PhasesPrefill and Decode: fundamentally different bottlenecks1 visual1 source note

LLM inference - two stages with opposite load characteristics. Prefill - matmul-bound: processes all prompt tokens in parallel, GPU is busy. Decode - memory-bound: each step reads the entire KV-cache from memory, the GPU is almost idle. Understanding the difference means optimizing correctly.

Visual model · Process flowFollow the sequence behind Prefill and Decode: fundamentally different bottlenecks and locate where work or state changes.
Complete view · 9 layers
Source-complete notesBottleneck-type optimizations

Bottleneck-type optimizations

  • TTFT → shorten prompt / prompt caching
  • TPS → reduce KV-cache (GQA/MQA)
  • continuous batching → decode GPU utilization increases
06PhasesChunked Prefill: don't freeze decode1 source note

Problem: a long prefill (2K+ tokens) blocks the GPU and delays TTFT for other users in the batch. Chunked prefill splits the prefill into parts, interspersed with decode - improves the uniformity of latency.

Source-complete notesmechanics
mechanicstext
# Without chunked prefill:
User A prefill: [────────────────── 2000 tokens ──]
User B decode: [waiting]
                  ← B is blocked for the entire time prefill A

# With chunked prefill (chunk=256):
User A chunk 1: [──256──]
User B token 1: [─1─]
User A chunk 2: [──256──]
User B token 2: [─1─]
...
← A finishes a little later, but B doesn't freeze
← latency tail (p99) improves significantly

# Implementation: vLLM 0.4+, TensorRT-LLM
07PhasesContinuous Batching vs Static Batching1 source note

Static batching: requests are grouped by N and wait for the entire batch to complete. The problem is that the longest request in the batch makes everyone wait. Continuous batching: requests enter and exit the batch dynamically at each decode step.

Source-complete notestable
StaticContinuous
Batch formationtimes in N requestseach decode step
New request includedwaiting for the next batchright away
GPU utilizationlow at different lengthshigh
Throughput2–3× lessmaximum
Implementationjustdifficult (KV scheduling)
Who usesold systemsvLLM, TGI, TRT-LLM
03

Memory Math: GQA, MQA, PagedAttention

3 cards
08MemoryMHA → GQA → MQA: evolution of heads to save cache1 visual1 source note

Multi-Head Attention keeps separate K and V for each head - maximum quality, maximum KV-cache. GQA and MQA - progressive reduction in the number of K/V goals while maintaining the number of Q goals. Llama-3, Mistral, Gemma use GQA.

Visual model · Process flowFollow the sequence behind MHA → GQA → MQA: evolution of heads to save cache and locate where work or state changes.
Complete view · 11 layers
Source-complete notesin production

in production

  • Llama-3 8B: GQA (32Q / 8KV) → 2024 standard
  • Mistral 7B: GQA (32Q / 8KV)
  • MQA → niche, GQA displaces
09MemoryPagedAttention (vLLM): virtual memory for KV2 source notes

The problem with traditional KV-cache: it is allocated as a contiguous block under max_seq_len. With a response of 512 tokens, a prompt of 100 tokens - 80% of the memory is idle. PagedAttention stores KV in continuous pages of ~16 tokens, allocating on demand.

Source-complete notesmechanics pages · bonus: sharing pages
mechanics pagestext
# Traditional KV-cache:
kv[req_1] = allocate(max_seq_len=2048) ← reserve everything at once
kv[req_2] = allocate(max_seq_len=2048) ← 2048 more, although 100 are needed
← 90% of GPU memory is fragmented with empty blocks

# PagedAttention:
page_size = 16 # tokens per page

req_1 ← [page_4, page_7, page_12] ← not physically adjacent
req_2 ← [page_1, page_9]
req_3 ← [page_2, page_5, page_11] ← allocated as they grow

# block_table stores the mapping of logical → physical pages
# GPU core vLLM can perform attention on non-adjacent blocks

Result:
  memory waste: 30–40% (naive) → < 4% (PagedAttention)
  throughput: +2–4× with the same GPU

bonus: sharing pages

  • common system prompt → same page for all requests
  • copy-on-write with branching (beam search)
  • vLLM, TGI, SGLang use PagedAttention
10MemorySliding Window Attention: limit cache growth2 source notes

An alternative approach: do not store KV for all past tokens - only for the last W. Each token sees only a window from the W previous ones. Mistral 7B uses SWA with W=4096. The cache stops growing after W tokens.

Source-complete notestradeoff · applies
tradeofftext
Full KV-cache:
  attention(q_i, K[0..i], V[0..i]) ← all tokens
  maximum quality
  memory: O(seq_len) → grows without limit

Sliding Window (W=4096):
  attention(q_i, K[i-W..i], V[i-W..i]) ← window only
  quality: good for local dependencies
  memory: O(W) → constant after W tokens!

SWA problem:
  token outside window = "forgotten"
  distant dependencies (beginning → end of text) are lost

Hybrid: some layers full attention,
        part of the SWA (Mistral Mixtral) layers

applies

  • Mistral 7B: W=4096 + full for multiple layers
  • bad for tasks with long dependencies
  • Longformer: SWA + global tokens (hybrid)
04

Prompt Caching: KV-cache at the API level

3 cards
11Prompt CachePrompt Caching: reuse prefill between requests1 visual1 source note

A regular KV-cache lives inside a single request. Prompt Caching is a KV-cache between requests at the API level. If many requests have the same prefix (system prompt + RAG documents), the API provider stores them in KV-cache and does not recalculate them. Savings: up to 90% prefill cost and 85% TTFT latency.

Visual model · ComparisonContrast the alternatives in Prompt Caching: reuse prefill between requests under the same frame.
Complete view · 10 layers
Source-complete noteswhen caching is especially effective

when caching is especially effective

  • long system prompt (>1024 tokens)
  • RAG with fixed documents
  • few-shot examples in the prompt
  • unique documents in each request - the cache will not help
12Prompt CacheAnthropic: cache_control API2 source notes

Anthropic requires explicit marking via cache_control. You decide which blocks to cache. Minimum 1024 tokens per cached block. TTL - 5 minutes (extends with each cache hit).

Source-complete notesrequest structure · Pricing (Claude 3.5 Sonnet)
request structuresql
messages = client.messages.create(
  model = "claude-sonnet-4-6",
  system = [
    {
      "type": "text",
      "text": system_prompt, ← static prompt
      "cache_control": {"type": "ephemeral"}
    }
  ],
  messages = [
    {"role": "user", "content": [
      {"type": "text", "text": rag_context,
       "cache_control": {"type": "ephemeral"}},
      {"type": "text", "text": user_query} ← not cacheable
    ]}
  ]
)

# Check the result:
usage = messages.usage
usage.cache_read_input_tokens # how many from cache
usage.cache_creation_input_tokens # how many are written to the cache
usage.input_tokens # regular (not cached)

Pricing (Claude 3.5 Sonnet)

  • cache_write: 125% of input price
  • cache_read: 10% of input price (90% discount)
  • pays off for >2 requests with one prefix
13Prompt CacheOpenAI: automatic prefix caching2 source notes

OpenAI (gpt-4o, gpt-4o-mini from Oct 2024) enables caching automatically - no markup is needed. The cache is activated at a prefix of 1024 tokens and a granularity of 128 tokens. TTL - 5-10 minutes.

Source-complete notesdifferences from Anthropic · practice
differences from Anthropictext
OpenAI - automatically:
  ✓ No cache_control markup needed
  ✓ The API itself determines matching prefixes
  ✓ 50% discount on cached tokens (input)
  ? There is no explicit control - you don’t know what is cached

# Check in response:
response.usage.prompt_tokens_details
  → {"cached_tokens": 1920, "audio_tokens": 0}

Anthropic - explicit markup:
  ✓ Full control over which block to cache
  ✓ 90% discount (vs 50% for OpenAI) → more aggressive
  ! We need to rebuild the prompt structure
  ! Minimum 1024 tokens per block

Advice: both providers - install static first,
dynamic (query) to the end. It works for both.

practice

  • OpenAI - easier to get started, no code changes
  • Anthropic - more savings with correct markings
  • both: block order is critical - static first
05

Sampling: from logits to final token

4 cards
14SamplingFull pipeline sampling: logits → temperature → top-k → top-p → sample2 visuals1 source note

After forward pass, the model returns a vector of logits: one number for each token in the dictionary (128K for GPT-4). From these raw scores, you need to select one token. The chain of operations is deterministic, except for the final sample.

Distribution workbenchTemperature reshapes. Top-p trims.

Change both controls and inspect which tokens remain eligible.

This view stops before the random draw. It isolates the two decisions that shape the candidate distribution.
Visual model · ComparisonContrast the alternatives in Full pipeline sampling: logits → temperature → top-k → top-p → sample under the same frame.
Complete view · 13 layers
Source-complete notestypical settings

typical settings

  • code/factual: T=0, greedy (reproducible)
  • chat: T=0.7, top_p=0.9
  • creative: T=1.0–1.2, top_p=0.95
  • T>1.5 → incoherent text
15SamplingTemperature: physical intuition1 source note

The name "temperature" comes from thermodynamics. At high temperatures, molecules move randomly (high entropy). When low, it is orderly (low entropy). Similarly, temperature controls the entropy of the tokens' probability distribution.

Source-complete notesdistributional effect
distributional effecttext
# Initial logits: [8.41, 6.23, 5.87, 4.12]

T=0.3 (cold, “confident”):
  scaled: [28.0, 20.8, 19.6, 13.7]
  softmax: [0.993, 0.004, 0.002, 0.001]
  ← almost always "cat"

T=1.0 (neutral, “raw distribution”):
  scaled: [8.41, 6.23, 5.87, 4.12]
  softmax: [0.617, 0.083, 0.058, 0.011]
  ← sometimes other options

T=2.0 (hot, “chaotic”):
  scaled: [4.21, 3.12, 2.93, 2.06]
  softmax: [0.342, 0.189, 0.158, 0.071]
  ← often unexpected tokens

# T→0: argmax (deterministic)
# T→∞: uniform (everything is equally likely)
16SamplingGreedy vs Beam Search vs Sampling2 source notes

Three fundamentally different strategies for choosing the next token. Greedy is fast, Beam is high-quality for NMT, Sampling is diverse for generative tasks.

Source-complete notestable · when what
StrategyLogicPlusMinus
Greedyargmax at each stepfast, deterministiclocal optima
Beam (B=4)store B best waysglobally better greedy4x more expensive, repeats
Samplingrandom from distributionvariety, creativeunstable
Top-p samplingnucleus + chancebalance of quality and diff.no

when what

  • translation/summarization: Beam B=4
  • chat/creative: top-p sampling
  • structured output: greedy (T=0)
17SamplingRepetition Penalty & Logit Biases1 source note

LLM without additional mer tend to repeat tokens - especially at high temperatures. Repetition penalty reduces the probability of tokens that have already been encountered in the context. Logit bias allows you to force specific tokens to be strengthened or banned.

Source-complete notesmechanics
mechanicspython
Repetition penalty (θ = 1.3):
  if token_id in context:
    logit[token_id] = logit[token_id] / 1.3if > 0
    logit[token_id] = logit[token_id] * 1.3if < 0
  # 1.0 = no penalty, 1.3 = moderate, 2.0 = aggressive

Logit bias:
  # force deny token
  logit_bias = {token_id_of_swear: -100} ← = -

  # force the token to be strengthened
  logit_bias = {token_id_of_yes: +10} ← ≈ 20000× more likely

# OpenAI API: logit_bias parameter
# Usage: guardrail for banned words
# or force structured output
06

Generation Optimizations: speculative, quantization

3 cards
18OptimizationSpeculative Decoding: a small model generates, a large one verifies1 visual1 source note

The main bottleneck of the decode phase is memory-bound: the GPU is idle waiting for data. Speculative decoding uses this time: a small “draft” model generates K tokens, a large model verifies them in ONE forward pass. Accepted tokens are free. Acceleration 2–3×.

Visual model · Process flowFollow the sequence behind Speculative Decoding: a small model generates, a large one verifies and locate where work or state changes.
Complete view · 9 layers
Source-complete noteswhen to use

when to use

  • latency is critical, draft and target are one family
  • self-hosting: vLLM supports speculative decoding
  • low temperature → higher acceptance rate
  • when T>1.2: draft is often rejected → no profit
19OptimizationQuantization: fewer bits - less memory2 source notes

Model parameters are stored in fp16 (2 bytes) or fp32 (4 bytes). Quantization reduces to int8 (1 byte) or int4 (0.5 byte). Llama-3 70B in fp16 = 140GB, int4 = 35GB - fits on two A100 40GB.

Source-complete notesformats and tradeoff · practice
formats and tradeofftext
# Size of Llama-3 70B in different formats:
fp32: 280 GB ← unrealistic
fp16: 140 GB ← training
bf16: 140 GB ← training (better fp16 for large numbers)
int8: 70 GB ← almost no quality loss (LLM.int8)
int4: 35 GB ← GPTQ/AWQ: slight loss of quality
int3: 27 GB ← noticeable loss
int2: 18 GB ← significant loss

# KV-cache can also be quantized:
fp16 → int8: KV-cache 2x smaller
  ← saves GPU memory for larger batches
  ← slight drift on long sequences

practice

  • int4 (GPTQ/AWQ): deploy 70B on 2×A40
  • int8 (bitsandbytes): safe for production
  • int4 KV-cache: carefully eval before deployment
20OptimizationFlash Attention: O(n) memory instead of O(n²)2 source notes

The standard implementation of attention materializes a matrix S = QKᵀ of size n×n in HBM - with n=8192 this is 512MB for only one matrix. Flash Attention calculates attention by tile, never materializing the full matrix.

Source-complete noteskey idea · applies
key ideatex
# Standard attention (slow, lots of memory):
S = Q @ K.T / sqrt(d_k) # [n × n] in HBM - expensive!
A = softmax(S) # [n × n] in HBM
O=A@V#[n×d] in HBM
Memory: O(n²)

# Flash Attention (Dao et al. 2022):
# Tile algorithm: Q, K, V blocks are loaded into SRAM
# (fast GPU memory), softmax is calculated incrementally
#S never fully materializes
Memory: O(n) ← linear! only SRAM tiles

Result:
  Speed: 2–4x faster on A100
  Memory: 5–20× less
  Numerically identical to standard attention

applies

  • all modern libraries: vLLM, HuggingFace
  • critical for long-context (>8K tokens)
  • FlashAttention-3 (2024): optimized for H100
07

Token Embeddings vs Text Embeddings: Don't be confused!

2 cards
21EmbeddingsToken Embeddings (within LLM) vs Text Embeddings (for RAG) - different things1 visual1 source note

One of the most common conceptual failures: mixing token embeddings (a table inside GPT, transforms ID→vector) and text embeddings (output of an encoder model of type text-embedding-3, representing all text as one vector for search). These are fundamentally different objects with different properties.

Visual model · Formula mapConnect the quantities and operations that determine Token Embeddings (within LLM) vs Text Embeddings (for RAG) - different things.
Source-complete notesselection rule

selection rule

  • RAG/search → text-embedding-3 / bge-m3
  • fine-tuning models → token embeddings (inside)
  • never use token embeddings from LLM for retrieval
22EmbeddingsNiche case: hidden states LLM as embedding1 source note

Sometimes LLM hidden states are used as text embeddings - through prompt engineering. It works (LLM-Embedder, E5-mistral), but is niche: expensive (high inference), slow, justified only when maximum semantics is needed.

Source-complete noteswhen it makes sense
when it makes sensetext
# E5-mistral: prompt engineering for retrieval
prompt = f"Instruct: Given a query, find relevant documents.\n
Query: {query}"
embedding = llm_model.last_hidden_state(prompt)[-1]
← take the last hidden state (pool)

# When justified:
✓ the task requires deep understanding (code, science)
✓ has a GPU, latency < 1s is acceptable
✓ bi-encoder embedding is not enough

# Why standard text-embedding is better in 99% of cases:
✗ LLM inference: 100–500ms vs 5–20ms for bi-encoder
✗ cost 10–50× higher
✗ bge-m3 on MTEB is often no worse than LLM-embedded
08

End-to-End: “mom washed the frame” via GPT

2 cards
23End-to-EndEach step: from “continue the text: mom washed the frame” to the first response token1 visual

End-to-end parsing of one inference call. Let's take Llama-3 8B - specific numbers, specific forms of tensors. Task: continue the sentence.

Visual model · Formula mapConnect the quantities and operations that determine Each step: from “continue the text: mom washed the frame” to the first response token.
24End-to-EndPerformance Numbers: Llama-3 8B on A100 80GB2 source notes

Specific numbers help calibrate expectations and explain in interviews why this or that optimization is important. Latency and throughput depend on batch size, length and accuracy.

Source-complete notesindicative metrics · GPU memory budget
indicative metricstext
# Llama-3 8B, fp16, A100 80GB SXM, vLLM

Prefill (compute-bound):
  1024 prompt tokens: TTFT ≈ 30 ms
  4096 prompt tokens: TTFT ≈ 120 ms
  16K prompt token: TTFT ≈ 900 ms ← O(n²) hits

Decode (memory-bound):
  batch=1: TPS ≈ 80 tok/s
  batch=8: TPS ≈ 220 tok/s ← batching helps
  batch=32: TPS ≈ 400 tok/s ← saturates HBM bandwidth

Memory:
  Model weights: ~16 GB (fp16)
  KV-cache @ 4K × batch=8: ~4.3 GB
  Activations: ~1–2 GB
  Total A100 80GB: fits with a margin

With optimizations:
  int4 (AWQ): 4 GB model, batch×2
  Speculative: latency 2–3× lower
  Prompt cache: TTFT 5–10× lower on hit

GPU memory budget

  • A100 80GB: 70B fp16 + KV-cache (batch=4)
  • A100 40GB: 8B fp16 + KV-cache (batch=16)
  • 4×A100: 70B + large batch or long context

No dead end

Keep moving through the map.

Continue in sequence, switch to a related guide, or return to the seven-track learning map.

Discovery graph / next reads

Continue through New Runtime

Open the graph
  1. 01learning trackLlm FoundationsOpen the complete learning track.
  2. 02related materialFrom a Neuron to an LLMContinue with another guide in this learning track.
  3. 03related materialLLMs in Plain EnglishContinue with another guide in this learning track.
  4. 04related materialLLM Internals: From Token to Logit to AnswerContinue with another guide in this learning track.
  5. 05related materialWhat a Prompt Is and Why a Question Becomes an AnswerContinue with another guide in this learning track.

These links are also published in this page’s JSON twin and as typed edges in DiscoveryGraph v1.

Who read this page?Machine requests, hidden until opened

Loading the privacy-safe route aggregate…

Open the JSON contract