Skip to content
The Daily Triptych152 / 365
PagedAttention memory path

Tokens fill logical KV blocks; a block table maps them onto non-contiguous physical blocks that attention reads back.

II · THE IDEA · ARTIFICIAL INTELLIGENCE

Paged Attention for Efficient Memory Management

systems/inference · KV cache management · PagedAttention · OS virtual memory paging

▶ Listen · narrated

When many requests share a GPU, memory reserved for attention caches often sits idle in fragments. Treating those caches like paged virtual memory lets a server pack far more of them in.

At a glance

What it is
Attention over a KV cache stored in non-contiguous fixed-size blocks
OS parallel
Logical pages mapped to physical frames, with a block table between them
Main waste
Fragmentation from reserving contiguous space per sequence up front
Side benefit
Blocks can be shared across sequences that reuse the same prefix

Think of the model’s memory for past tokens as a notebook that grows with every new word. The old habit was to tear out a huge fixed stack of pages for each conversation at the start, even if the chat might end quickly. Most of those pages stayed blank, and when a chat finished the gap left behind often did not fit the next conversation.

PagedAttention rules the notebook differently. Everyone shares one pile of identical small sheets. As a conversation needs room, it takes another sheet from the pile. Sheets for one chat need not sit next to each other. A simple contents list says which physical sheets belong to which chat and in which order. When the model must reread the past, it follows that list.

If two chats start with the same prompt, they can share the same sheets until their replies differ. Only then does a sheet get copied. The result is less blank paper sitting idle and more conversations fitting into the same desk.

Look closer

  1. Logical blocks, physical frames

    Each sequence sees a tidy list of logical KV blocks as its cache grows token by token. Those logical blocks are mapped, through a block table, onto physical blocks carved from a GPU memory pool. Neighbouring logical blocks need not sit next to each other in device memory. The attention kernel follows the mapping at read time, so the model never requires one long contiguous slab per request.

  2. Where the waste used to hide

    Older serving designs often reserved a contiguous KV region sized for the maximum possible sequence length. Short prompts and early decoding steps left most of that reservation empty; once a request finished, the hole it left was often the wrong shape for the next arrival. Fixed-size blocks shrink internal waste inside a sequence and let the allocator fill gaps that would otherwise stay stranded between requests.

  3. Sharing is a pointer change

    When two outputs fork from the same prompt, or when beam candidates share a prefix, the corresponding physical blocks can be referenced more than once instead of copied. Reference counts track how many sequences still need a block; only when the count drops to zero does the block return to the free pool. Copy-on-write handles the moment a shared path diverges.

The story

Autoregressive serving has a memory problem that is easy to understate. For every active sequence the model must retain keys and values for every layer and every past token, because the next attention step will read them again. That KV cache often dominates GPU memory once batch size or context length rises, and it grows unevenly: one request may finish in a few dozen tokens while another runs toward the context limit.

A natural first design is to give each sequence a contiguous buffer large enough for the worst case. That is simple for the attention kernel, which can then stride through memory in a predictable way. It is also expensive. Most of the buffer sits empty for most of the request’s life. When the request ends, the free region is a single large hole only if nothing else is packed beside it; under load, free memory becomes a patchwork that will not fit the next full reservation even when the total free bytes would suffice. External fragmentation and internal fragmentation arrive together.

PagedAttention borrows the virtual-memory idea that operating systems have used for decades. Memory is divided into blocks of fixed size. A sequence’s KV cache is a list of logical block indices. A block table maps each logical index to a physical block in a central pool. When a new token is generated, the system writes its keys and values into the next slot of the current block, or allocates another physical block if the current one is full. The blocks that belong to one sequence may be scattered anywhere in the pool.

The attention computation must change to match. Instead of assuming one contiguous key and value tensor per sequence, the kernel walks the block table and gathers the relevant physical blocks. From the model’s point of view the history is still ordered; only the layout underneath is non-contiguous. That indirection is the cost of the scheme, paid so that the allocator can treat memory as a bag of interchangeable frames rather than a set of rigid per-request slabs.

Because allocation is block-grained, a sequence only holds memory for tokens it has actually produced, plus at most one partially filled block. When a request completes, its blocks return to the free list individually and can be reused by any other request. The same mechanism supports sharing: if several sequences begin from an identical prompt, they can point at the same physical blocks for that prefix. Divergence is handled by copy-on-write on the first block that differs. Parallel sampling and beam search become cheaper in memory for the same reason.

The practical effect on a busy server is higher packing density. More concurrent sequences fit in the same GPU memory, or the same concurrency leaves headroom for longer contexts. Throughput gains come less from faster arithmetic than from wasting fewer bytes on empty reservations and unusable holes. The idea is deliberately ordinary systems engineering applied to a structure that serving stacks had been treating as a single growable array.

Why it mattered then

As large language models moved from single-user demos into multi-tenant serving, the KV cache became the binding constraint on batch size. Pre-allocating contiguous space for every sequence was workable when few requests shared a device and contexts were short; it scaled poorly once operators tried to keep GPUs busy with many parallel generations. Fragmentation meant that measured free memory overstated how many new requests could actually start. PagedAttention addressed that gap with a familiar OS pattern, so serving systems could raise concurrency without waiting for larger devices or shorter prompts.

Why it matters now

Production inference still lives or dies by how densely the KV cache can be packed. Context windows keep growing, multi-turn chat keeps state alive longer, and techniques such as prefix reuse and speculative decoding multiply the value of block-level sharing. Any scheduler that admits dynamic batching benefits from memory that can be sliced and recombined without leaving stranded holes. The same block-table idea also clarifies capacity planning: operators reason in blocks and reference counts rather than in opaque per-request reservations, which makes memory behaviour more predictable under mixed workloads.

The surprising detail

The central trick is not a new attention formula but a layout change plus a kernel willing to chase a block table. Once KV memory is paged, sharing a prompt prefix across many outputs is mostly bookkeeping—reference counts and copy-on-write—rather than a separate model feature. Memory that used to be duplicated per beam or per sample can collapse to a single physical copy until paths diverge.

What is disputed

The original PagedAttention paper reports large gains in throughput and batch size for its serving system, but the exact improvement depends on workload mix, block size, model shape and how aggressive the baseline allocator was. Treat the mechanism as well-specified; treat any single speed-up figure as tied to that evaluation setup.

Remember this

PagedAttention stores the KV cache in fixed-size blocks mapped like virtual memory, so serving avoids contiguous pre-allocation waste and can share prefixes by reference.

Test yourself

A serving stack pre-allocates one contiguous KV buffer per request at the maximum sequence length. Under PagedAttention the same requests use fixed-size blocks from a shared pool. Give two distinct reasons the paged design can admit more concurrent sequences on the same GPU.

Go deeper

Image: Original diagram, The Daily Triptych. Licence: Original work. Source.

← Back to day 152