PagedAttention 对比传统 KV 缓存:vLLM 如何重塑 LLM 推理的 GPU 显存管理
- 作者

- 姓名
- Nino
- 职业
- Senior Tech Editor
在大语言模型(LLM)推理的过程中,生成的每一个 Token 都在悄无声息地消耗 GPU 显存。在高性能服务领域,显存往往是比计算能力更紧缺的瓶颈。传统的 Key-Value (KV) 缓存实现方式存在严重的资源浪费——大量显存被预分配却未被使用,导致系统无法承载更高的并发请求。
vLLM 及其核心创新 PagedAttention 的出现,彻底改变了 AI 基础设施的格局。它借鉴了操作系统中存在了数法十年的“分页”思想,解决了显存碎片化问题。在 n1n.ai,我们看到开发者在追求低延迟和高吞吐量之间不断权衡;深入理解 PagedAttention 是优化 AI 部署的第一步。本文将深度解析其工作原理,以及它为何能实现比传统方案高出 24 倍的吞吐量。
什么是 KV 缓存?为什么它至关重要?
要理解解决方案,首先要理解问题本身。像 Llama 3 或 DeepSeek-V3 这样的模型是自回归的。这意味着为了生成第 个 Token,模型需要之前所有 个 Token 的上下文信息。
如果没有缓存,模型在每一步生成时都必须重新计算前面所有 Token 的 Key 和 Value 张量。这将导致 的计算复杂度,使得实时生成变得不可能。为了解决这个问题,我们使用 KV 缓存:我们将之前计算好的 Key 和 Value 张量存储在 GPU 显存(VRAM)中。后续步骤只需计算新 Token 的 KV 值,并与缓存的值进行注意力计算(Attention)。
然而,这个缓存的体积非常庞大。以 Llama-2 7B 模型为例,我们可以粗略计算其显存占用:
# KV 缓存大小粗略估算
num_layers = 32
num_heads = 32
head_dim = 128
seq_len = 2048
batch_size = 8
dtype_bytes = 2 # float16 (半精度)
kv_cache_bytes = (
2 * num_layers * num_heads * head_dim * seq_len * batch_size * dtype_bytes
)
print(f"KV 缓存占用: {kv_cache_bytes / 1e9:.2f} GB")
# 输出: KV 缓存占用: 8.59 GB
仅仅是 8 个并发用户在 2k 上下文长度下,就吃掉了 8.6 GB 的显存。如果你正在使用像 n1n.ai 这样的顶级 API 聚合器,这些底层优化已经在后台为你处理好了,但对于自建基础设施的团队来说,这正是挑战的开始。
痛点:传统 KV 缓存与显存碎片化
在传统的框架(如 HuggingFace Transformers)中,KV 缓存是作为连续内存块分配的。如果你设置 max_seq_len 为 2048,系统会在请求开始的那一刻,为这 2048 个 Token 预留空间。
这导致了三种类型的碎片:
- 内部碎片 (Internal Fragmentation):如果用户的请求只生成了 50 个 Token,但你预留了 2048 个位置,剩下的 1998 个位置就被浪费了。
- 预留碎片 (Reservation Fragmentation):即使模型最终可能会用到这些空间,但在生成的早期阶段,这些显存一直处于闲置状态。
- 外部碎片 (External Fragmentation):由于分配是连续的且长度不一,GPU 显存会变成像“瑞士奶酪”一样,充斥着细小的、无法利用的空隙。
在实际操作中,这意味着你的 GPU 可能显示已使用 80% 的显存,但其中只有 30-40% 真正存储了有用的数据。这种低效直接限制了 Batch Size(批处理大小),导致排队时间变长,成本飙升。
灵感来源:操作系统虚拟内存
vLLM 团队(Kwon 等人,2023)意识到,2023 年的 LLM 显存管理方式非常类似于 20 世纪 60 年代的计算机内存管理。解决方案也如出一辙:分页 (Paging)。
在操作系统中,物理内存被划分为固定大小的“帧”(Frames),进程的虚拟地址空间被划分为“页”(Pages)。操作系统维护一个页表来将虚拟页映射到物理帧。这些帧在物理上不需要是连续的。
vLLM 将这一概念引入了 KV 缓存。KV 缓存不再是一个巨大的连续块,而是被划分为一个个 Block(块)(例如,每块存储 16 个 Token 的 KV 值)。
PagedAttention 的工作原理
PagedAttention 允许 KV 张量存储在非连续的物理显存中。其算法逻辑如下:
- 逻辑块:将一个序列的 KV 缓存划分为逻辑块。
- 块表 (Block Table):建立映射关系,记录每个逻辑块在 GPU 物理显存中的实际位置。
- 按需分配:当模型生成 Token 时,只有当当前物理块存满后,才会分配一个新的物理块。
| 概念 | 操作系统虚拟内存 | PagedAttention |
|---|---|---|
| 内存单元 | 页 (Page) | KV 块 (Block) |
| 地址空间 | 虚拟地址 | Token 索引 |
| 映射方式 | 页表 (Page Table) | 块表 (Block Table) |
| 存储介质 | 物理内存 (RAM) | GPU 显存 (VRAM) |
实现逻辑代码示例
以下是一个简化的 PagedKVManager 概念模型,展示了如何不依赖连续空间进行分配:
from dataclasses import dataclass, field
from typing import List, Optional
BLOCK_SIZE = 16 # 每个块包含 16 个 token
@dataclass
class KVBlock:
block_id: int
token_count: int = 0
class PagedKVManager:
def __init__(self, total_blocks: int):
# 初始化空闲块池
self.free_blocks = list(range(total_blocks))
self.blocks = {i: KVBlock(block_id=i) for i in range(total_blocks)}
def allocate_block(self) -> Optional[int]:
if not self.free_blocks: return None
return self.free_blocks.pop()
def append_token(self, seq_block_table: List[int]) -> bool:
# 如果最后一个块已满或尚无块,则分配新块
if not seq_block_table or self.blocks[seq_block_table[-1]].token_count == BLOCK_SIZE:
new_id = self.allocate_block()
if new_id is None: return False # 显存不足 (OOM)
seq_block_table.append(new_id)
self.blocks[seq_block_table[-1]].token_count += 1
return True
吞吐量提升:数据说明一切
通过消除几乎所有的显存碎片,vLLM 可以在同一个 Batch 中塞进更多的序列。根据原始论文的基准测试,vLLM 实现了:
- 与 HuggingFace Transformers 相比,吞吐量提升 2-4 倍。
- 在长序列和高并发场景下,吞吐量提升高达 24 倍。
当你使用 n1n.ai 时,你就在间接享受这些高效架构带来的红利。无论你是在调用 Claude 3.5 Sonnet 还是 OpenAI o3,底层的推理引擎往往都采用了类似的内存管理机制,以确保你的 API 请求能以极速响应。
隐藏的“超能力”:前缀缓存 (Prefix Caching)
PagedAttention 还实现了一个巨大的优化:写时复制 (Copy-on-Write)。如果你有 100 个请求都在使用同一个冗长的系统提示词(例如 RAG 系统中的长上下文),PagedAttention 允许这 100 个请求共享同一组物理显存块。
只有当某个请求开始生成不同的 Token 时,才会进行内存复制。这对于现代 AI 智能体(Agents)来说至关重要,能将公共前缀的显存占用降至近乎为零。
权衡与局限性
虽然 PagedAttention 是革命性的,但它也有其成本:
- 内核复杂性:标准的 FlashAttention 算子不支持分页内存。vLLM 团队必须编写自定义的 CUDA 内核,以便在非连续的显存块上执行注意力计算。
- 管理开销:在 CPU 端维护块表会带来微小的计算开销,但在 GPU 的巨大收益面前,这通常可以忽略不计。
- 计算密集型 vs 显存密集型:如果你的模型已经是计算饱和的(例如在小 Batch 下运行超大模型),PagedAttention 的边际收益会递减。
总结与核心要点
- 传统 KV 缓存 极其浪费,因为它要求连续的预分配。
- PagedAttention 将 GPU 显存视为虚拟内存,将其划分为灵活的块。
- 显存利用率 从约 60% 提升至 95% 以上,从而支持更大的 Batch Size。
- 吞吐量 显著提升,降低了每个 Token 的推理成本。
对于希望避开这些底层优化难题的开发者,n1n.ai 提供了一个统一的 API 接口,聚合了市场上最快、最高效的模型。
立即在 n1n.ai 获取免费 API 密钥。