advanced27 min studyLesson 702 in Engineering

A KV block table maps logical token ranges to a managed device pool

Translate token positions into block slots, quantify tail slack, and distinguish application-managed KV paging from operating-system pages or automatic host swapping.

On this page

What you’ll understand

  • Calculate logical block and offset for a token index.
  • Count fixed-size KV blocks and final-block slack for a request.
  • Explain pool, table, and kernel responsibilities without equating them to OS demand paging.

A growing request need not own one physically contiguous region large enough for its eventual output. A serving runtime can divide its KV state into fixed-token blocks and provide attention kernels with a table mapping each logical block to physical storage. This indirection makes allocation and sharing more flexible, but the table is part of a specialized runtime contract. It does not mean the operating system will automatically swap attention state to host memory whenever a request exceeds the device's available capacity.

Separate logical order from physical placement

Let a block hold a fixed number of token positions across the relevant cache layout. A token's zero-based logical index determines a block number and an offset within that block. A per-request table then supplies the corresponding physical pool identifier, so consecutive logical blocks can live far apart in the device pool. Attention kernels must follow this mapping while preserving the original sequence order and valid token lengths. Reordering physical addresses does not permit changing causal positions or interpreting uninitialized tail slots as real cached tokens.

The original PagedAttention work applies the analogy of virtual-memory pages to application-managed attention storage. The analogy explains indirection, fixed allocation units, and sharing; it is not an identity between GPU KV blocks and OS virtual pages. A KV block can span many hardware pages and tensors, and its token capacity is a serving configuration choice. Host offload, device transfer, and preemption need explicit mechanisms. The kernel and scheduler must agree on block-table representation, head layout, dtype, and lifetime for the indirection to be correct.

j=⌊iB⌋,o=i mod B,p=table⁡[j]j=\left\lfloor\frac{i}{B}\right\rfloor,\qquad o=i\bmod B,\qquad p=\operatorname{table}[j]
i is a zero-based token-position index, B a positive integer token capacity per logical block, j the logical block index, o its slot offset, and p a physical pool identifier. These are indices, not byte addresses or OS page numbers; layout-specific addressing still converts p and o into tensor locations.↔ Scroll wide equations horizontally.

Fixed blocks remove one fragmentation problem, not every overhead

With interchangeable equal-size blocks, a request can use any available pool entries without requiring one large contiguous region inside that pool. Its final block may still have unused token slots, and block tables, reference counts, hashes, alignment, and per-layer layouts consume additional memory. An allocator can reserve a large device tensor for the pool even while many application blocks are idle, so framework allocated bytes can remain high after request completion. Measure pool occupancy separately from the amount of device memory reserved to hold the entire pool.

A smaller block reduces worst-case tail waste but increases table entries and may make transfers or kernel access less efficient. A larger block can reduce metadata overhead while wasting more space for many short requests. The best size depends on measured sequence lengths and kernel behavior rather than a universal percentage rule. Cached full prefixes can also leave zero-reference blocks holding reusable content until reclaimed. Such blocks occupy physical pool slots, yet their contents may be evictable; distinguish them from actively referenced blocks when counting admission headroom.

NB(T)=⌈TB⌉,S(T)=BNB(T)−T,0≤S(T)<BN_B(T)=\left\lceil\frac{T}{B}\right\rceil,\qquad S(T)=B N_B(T)-T,\qquad 0\le S(T)<B
For a positive integer unshared retained length T and positive integer block size B, N_B is the allocated block count and S is final-block slack in token slots. Zero-length requests require a separately declared policy. The bound excludes preallocation, speculative reserves, metadata, and shared-prefix accounting.↔ Scroll wide equations horizontally.

Allocation and reclamation must preserve table validity

Allocate a new pool block before publishing a table entry that kernels can use, initialize the required state, and retain ownership until outstanding accesses finish. A stale table entry after a physical block has been recycled can silently read another request's KV values rather than produce a clean allocation error. Coordinate table updates, launches, completion events, and cleanup so reclamation occurs at a safe boundary. The vLLM 0.9.1 prefix-cache design distinguishes the block pool, free queue, cached-block mapping, and per-request block lists; those roles illustrate why free and unreferenced are operational states with explicit transitions.

The cache lab only models a bounded pool of reusable identities. Reset, explicitly set BOTH capacity C=4 and stride s=4, predict twelve hits among sixteen requests at t=0, then Play or Step. Reset and re-set BOTH C=3 and s=4; predict zero hits. Playback uses N=min(4096,16+floor(2t)); edits retain t and recompute from empty. There are no token positions, block tables, device addresses, live-reference pins, or kernel completion events. Its equal-size entries illustrate a capacity boundary without implementing safe KV allocation or OS paging.

Map one position and count the request's tail slack

A fictional request retains thirty-five tokens in blocks of sixteen token slots. Its logical block table is [7,2,9]. Map zero-based token index thirty-four, then calculate allocated slots and slack; ignore metadata and sharing.

  1. Logical block is floor(34/16)=2 and offset is 34 mod16=2. The table maps logical block two to physical pool block nine.

  2. The request needs ceil(35/16)=3 blocks, providing 3×16=48 token slots. Only thirty-five represent valid retained positions.

  3. Slack is 48−35=13 token slots in the final block. At 128 KiB per token slot in this hypothetical layout, capacity is six MiB, with 1.625 MiB of slack; physical IDs do not change those counts.

The result

Indirection preserves logical order across noncontiguous blocks, while the final block still has measurable internal slack.

Explore the model

Interactive lab

Interactive lab · cache

Equal-size entries provide a limited pool analogy

For EACH run Reset, set BOTH C and s, predict, then Play or Step. At t=0/N=16, (4,4) gives twelve hits and (3,4) gives zero. N=min(4096,16+floor(2t)); edits retain t/recompute from empty. No KV block table, token offset, live pin, device allocation, or host paging is implemented.

Equal-size entries provide a limited pool analogyA fully associative LRU cache starts empty and requests address (i·s) mod 16. Hits move an address to the newest position; misses evict the oldest when full. Playback starts with 16 requests and adds two per second, capped at 4096 explicitly simulated requests. This toy stream is not a processor-cache benchmark. Current readings: Hits / requests: 0 / 16; Hit rate: 0%; Address-stream period: 16 addresses. All parameters are adjustable with the labeled controls below.Fully associative LRU cache after 16 deterministic requests: 0 hits and 16 misses.Most recent 16 requestsaddress = i × 3 mod 160M3M6M9M12M15M2M5M8M11M14M1M4M7M10M13MCurrent cache order · oldest → newest471013Latest address 13 · miss: inserted as newestToy address stream · period 16 · starts empty
Cached addressMiss / evictionMost recent request
Hits / requests
0 / 16
Hit rate
0%
Address-stream period
16 addresses
t = 0 s

A fully associative LRU cache starts empty and requests address (i·s) mod 16. Hits move an address to the newest position; misses evict the oldest when full. Playback starts with 16 requests and adds two per second, capped at 4096 explicitly simulated requests. This toy stream is not a processor-cache benchmark. Parameter changes pause playback and recompute the model at the current elapsed time. Reset restores both parameters and returns time to zero. Playback starts paused. Adjust either parameter, then choose Play or Step.

Look forA block pool's capacity and mapping contract must be understood separately from OS memory management.

Check your understanding

What does a PagedAttention-style KV block table provide?

Try it yourself

For positive length T=65 and block size B=16, calculate block count and slack. Map zero-based position sixty-four to its logical block and slot. What remains unknown without the block table?

Take a moment to make a prediction or work it out on paper. Open a hint when you need one.

Give me a hint

Use ceiling division for capacity and floor/remainder for the position.

Compare with the solution

Five blocks provide eighty slots, so slack is 80−65=15. Position sixty-four is in logical block four at offset zero. The physical block identifier and layout-specific byte address remain unknown until the table and tensor layout are supplied.

Take it with you

  • Block tables preserve logical sequence order over noncontiguous physical KV storage.
  • Equal-size blocks avoid contiguous-allocation requirements inside the pool but retain tail slack and metadata.
  • Allocation and recycling need safe ownership and kernel-completion boundaries.

Read further

Original sources and deeper explanations to follow at your own pace.

Optional progress, saved in this browser when available. Revisit any lesson at any time.

Lesson not marked complete.