LLM 中的 Paged Attention

---
title: "LLM 中的 Paged Attention"
author: "Amit Shekhar"
source_url: "https://outcomeschool.com/blog/paged-attention-in-llms"
published_at: "2026-03-29T00:00:00.000Z"
fetched_at: "2026-07-01T23:07:49Z"
updated_at: "2026-07-02T01:44:36Z"
language: "zh"
review_status: "draft"
---

# LLM 中的 Paged Attention

![Paged Attention in LLMs](https://outcomeschool.com/static/images/blog/paged-attention-in-llms.png)

在这篇文章里,我们会学习 **Paged Attention**。这是一种解决 KV Cache 内存浪费问题的技术,可以让 LLM 同时服务多得多的用户。

我们会先快速回顾 [KV Cache](https://outcomeschool.com/blog/kv-cache-in-llms),理解它带来的内存问题;再通过一个例子看看传统内存分配方式如何浪费空间;最后一步步看 Paged Attention 如何借用计算机管理内存的思路来解决这个问题。

我是 **Amit Shekhar**,[Outcome School](https://outcomeschool.com) 创始人。我教过并辅导过很多开发者,他们靠自己的努力拿到了高薪技术岗位;我也帮助过许多科技公司解决各自独特的问题,并创建过很多被顶级公司使用的开源库。我热衷于通过开源、博客和视频分享知识。

我在 Outcome School 教 [AI and Machine Learning](https://outcomeschool.com/program/ai-and-machine-learning)。

我们开始吧。

## 快速回顾:KV Cache

当 LLM 生成文本时,它一次预测一个 token。token 是一小段文本。它可以是一个词、词的一部分,甚至可以是单个字符。

在每一步,模型都会为新的 token 计算一个 Key 和一个 Value,并且需要所有之前 token 的 Key 和 Value。

如果没有 KV Cache,模型每一步都要为所有之前的 token 重新计算 Key 和 Value,这会浪费大量计算。KV Cache 的做法是:每个 token 的 Key 和 Value 计算出来以后就保存起来,后续步骤可以直接复用。

KV Cache 让文本生成快了很多。但它也有一个取舍:必须用内存来保存所有这些 Key 和 Value。

接下来,我们看看这会带来什么内存问题。

## 问题:KV Cache 中的内存浪费

当用户向 LLM 发送请求时,系统需要为这个请求的 KV Cache 预留内存。但挑战在于:**系统事先不知道回复会有多长**。

用户可能问一个简单问题,最后只生成 20 个 token;也可能问一个复杂问题,最后生成 2,000 个 token。系统无法提前知道结果。

在传统做法里,系统会为每个请求预留一大块连续内存,里面所有位置都挨在一起,并且足够容纳最大可能的回复长度。也就是说,即使实际回复最后只有 50 个 token,系统也可能按 2,048 个 token 预留内存。

我们用一个类比来理解。

### 酒店类比

想象一家酒店,客人入住时并不知道自己会住几晚。有些人只住 1 晚,有些人会住 30 晚。

**传统做法:** 客人入住时,酒店会在同一层连续预留 30 间房,以防这个客人真的住 30 晚。即使客人最后只住 2 晚,这 30 间房也会全部保持预留状态,不能分给其他人。

现在想象有 10 位客人入住。酒店会连续预留 30 × 10 = 300 间房。但如果大多数客人只住几晚,几百间房就会空着,白白浪费。

这正是传统做法中 KV Cache 内存会发生的情况。

**浪费体现在两个方面:**

1. **内部浪费:** 内存被预留了,但从未真正使用。如果一个请求只生成 50 个 token,却按 2,048 个 token 预留了内存,那么剩下 1,998 个 token 的空间就被浪费了。
2. **外部浪费:** 因为内存必须以一大块连续空间来分配,散落在各处的小块空闲内存就用不上;哪怕这些小块加起来已经足够服务一个新请求,也无法使用。

这种内存浪费是一个严重问题。大量预留内存实际上从未被用到。

因为内存有限,这种浪费意味着系统同一时间能服务的用户更少。如果系统能更高效地使用内存,就可以同时处理多得多的请求。

这就是 Paged Attention 要解决的问题。

## 什么是 Paged Attention?

**Paged Attention** 是一种更高效管理 KV Cache 内存的技术。它会把内存拆成小的固定大小块,这些块叫作**页(page)**。这些页在内存中不需要挨在一起。

“Paged”这个词来自操作系统里的一个概念。操作系统要为计算机上运行的所有程序管理内存。

操作系统不会给每个程序一整块连续内存,而是把内存拆成固定大小的小块,叫作**页(page)**。每个程序按需获得若干页,这些页可以分散在内存的任何位置。操作系统会用**页表(page table)**记录每个页在哪里;页表就是一张简单列表,把程序的每个页映射到它在内存中的实际位置。

Paged Attention 把同样的思路用到了 KV Cache 上。

我们回到酒店类比,看看它是怎么工作的。

### 酒店类比:分页做法

**分页做法:** 酒店不再为每位客人连续预留 30 间房,而是**按需一间一间给房**。客人入住时,先得到 1 间房。需要再住一晚时,再拿到另一间有空的房。它不必挨着第一间房。酒店会维护一张列表,记录哪些房间属于哪位客人。

这样,如果客人只住 2 晚,就只会用 2 间房。剩下的房间可以给其他客人使用。没有浪费。

如果 10 位客人入住,每个人都只拿到自己真正需要的房间。酒店就能用同样数量的房间服务多得多的客人。

这就是 Paged Attention 处理 KV Cache 的方式。

**给你一个小提示**

无论你在哪个技术领域工作,都应该熟悉这些主题:

- LLM
- RAG
- MCP
- Agent
- Fine-tuning
- Quantization

我们把它们整理进了一个视频:

[AI Engineering Explained: LLM, RAG, MCP, Agent, Fine-Tuning, and Quantization](https://www.youtube.com/watch?v=lnfWvX66FUk)

不用现在停下来去看——先收藏,等有时间再看。未来的你会感谢现在的你。

现在,我们回到主题。

## Paged Attention 如何工作

在 Paged Attention 中,KV Cache 内存会被拆成固定大小的小块。每个块可以保存固定数量 token 的 Key 和 Value。比如,如果块大小是 4,每个块就能保存 4 个 token 的 Key 和 Value。

我们来看一个例子。

假设用户发送了一个请求,模型正在生成回复:**“I love teaching AI and Machine Learning at Outcome School”(我喜欢在 Outcome School 教 AI 和机器学习)**。

### 没有 Paged Attention(传统做法)

系统会预先为这个请求预留一整块内存,比如 16 个 token 的空间:

```text
Memory: [__ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __]
         Reserved for this request (16 slots)
```

随着模型生成 token,它会一个个填入这些位置:

```text
Memory: [I  love  teaching  AI  and  Machine  Learning  at  Outcome  School  __  __  __  __  __  __]
         Used: 10 tokens                                                      Wasted: 6 slots
```

剩下 6 个位置已经被预留,但永远不会使用,也就是浪费的内存。

### 使用 Paged Attention

系统只在需要时,按每块 4 个 token 的小块来分配内存:

**第 1 步:** 模型开始生成。系统从内存中任意可用的位置分配 **Block 1**:

```text
Block 1: [I  love  teaching  AI]
```

**第 2 步:** Block 1 已经填满。系统分配 **Block 2**。它不需要挨着 Block 1:

```text
Block 1: [I  love  teaching  AI]
Block 2: [and  Machine  Learning  at]
```

**第 3 步:** Block 2 已经填满。系统分配 **Block 3**:

```text
Block 1: [I  love  teaching  AI]
Block 2: [and  Machine  Learning  at]
Block 3: [Outcome  School  __  __]
```

Block 3 里只浪费了 2 个位置,而传统做法会浪费 6 个位置。而且,系统没有提前预留最后用不上的内存。

### Block Table

但如果这些块分散在内存各处,模型怎么找到它们?

系统会用一张 **块表(block table)** 跟踪哪些块属于哪个请求,就像操作系统使用页表(page table)一样。

```text
Block Table for Request 1:
  Block 0 → Location 5 in memory
  Block 1 → Location 12 in memory
  Block 2 → Location 3 in memory
```

这些块按顺序编号(0、1、2),每个编号都会指向它在内存中的实际位置。当模型需要读取之前某个 token 的 Key 和 Value 时,就通过块表找到正确的块。

这就是为什么即使块分散在内存各处,模型仍然可以访问任何之前 token 的 Key 和 Value。

如果想端到端学习 Paged Attention、KV Cache、vLLM 和推理基础设施,可以看看 Outcome School 的 [AI and Machine Learning Program](https://outcomeschool.com/program/ai-and-machine-learning)。

## 为什么 Paged Attention 如此有效

Paged Attention 解决了前面讨论过的两类内存浪费:

1. **内部浪费几乎被消除。** 内存只会按需逐块分配。唯一的浪费出现在最后一个块里,因为最后一个块不一定总能完全填满。在我们的例子里,最后一个块只浪费了 4 个位置里的 2 个,而传统做法会浪费 16 个位置里的 6 个。
2. **外部浪费被消除。** 因为这些块不需要彼此相邻,所以内存中任何位置的空闲块都可以使用。不会再有用不上的碎片空间。

结果是:Paged Attention 可以更高效地使用内存。这意味着在同样的内存容量下,系统可以同时服务明显更多的请求。

## 请求之间的内存共享

Paged Attention 还带来了一个重要优化:**内存共享**。

假设两个用户问了同一个问题。两个请求的输入 token(也就是问题)是相同的。使用 Paged Attention 时,这两个请求可以共享输入 token 对应的同一批块,因为这些 token 的 Key 和 Value 完全相同。

系统不用存两份副本,只需要存一份,然后让两个请求在各自的 block table 里指向同一批块。这样能进一步节省内存。

这在下面这些场景里尤其有用:

- **并行采样(Parallel sampling):** 有时我们希望模型针对同一个问题生成多个不同回复,再从中挑选最好的一个。由于问题对所有回复都是一样的,输入块可以在所有回复之间共享。
- **束搜索(Beam search):** 有时模型会同时探索多个可能的补全,寻找最好的那个。同样,共享输入可以只保存一次,并在所有并行序列之间复用。

在这些场景中,内存共享会显著降低所需的总内存。

[SGLang](https://outcomeschool.com/blog/how-does-sglang-work) 把共享相同前缀的思路进一步推进:它用基数树(radix tree)组织共享文本,从而更精确地匹配共享前缀。

Paged Attention 是流行的高吞吐服务引擎 vLLM 背后的核心思路。我们有一篇详细介绍 [vLLM](https://outcomeschool.com/blog/how-does-vllm-work) 的文章,解释了它如何工作。

现在,我们已经理解了 Paged Attention:它借用了操作系统里的分页思想,高效管理 KV Cache 内存,消除浪费,并让系统同时服务更多用户。

在下一篇文章里,我们会学习 **[Continuous Batching](https://outcomeschool.com/blog/continuous-batching-in-llms)**。它会和 Paged Attention 配合,在任何旧请求完成的瞬间把新请求加入 batch,让 GPU 保持忙碌。

准备 AI 工程面试可以看这里:[AI Engineering Interview Questions](https://github.com/amitshekhariitbhu/ai-engineering-interview-questions)

这次就到这里。

谢谢

**Amit Shekhar**
[Outcome School](https://outcomeschool.com) 创始人