vLLM 架构概述
1. vLLM 是什么
vLLM 是一个高吞吐量、低延迟的 LLM 推理引擎。它的核心目标是在 GPU 显存有限的约束下,最大化并发请求的处理能力。
传统推理引擎为每个请求预分配一块连续的 KV cache 显存(按最大序列长度),导致严重的内部碎片——当一个请求实际只生成 200 token 但预留了 8192 个位置时,剩余 7992 个位置的显存完全浪费。在大规模服务场景(数百并发请求、序列长度差异极大、大量共享 system prompt)中,这种浪费意味着 GPU 显存利用率可能不到 30%。
vLLM 通过 PagedAttention 解决这个根本问题。
2. 核心创新:PagedAttention
PagedAttention 将 KV cache 划分为固定大小的 block(页),类似操作系统的虚拟内存分页:
传统引擎: 请求A [████████░░░░░░░░░░░░] ← 按 max_seq_len 预分配,大量浪费
请求B [████████████████░░░░] ← 每个请求独立分配,无法共享
vLLM: 物理 block 池: [B0][B1][B2][B3][B4][B5][B6][B7][B8]...
请求A 的 block_table: [B0, B3, B7] ← 按需分配
请求B 的 block_table: [B0, B3, B1, B5, B8] ← 前缀 B0,B3 共享!
三个关键收益:
| 收益 | 机制 |
|---|---|
| 零内部碎片 | block 按需分配,用多少占多少 |
| Prefix 共享 | 多个请求的公共前缀(如 system prompt)指向同一物理 block,引用计数管理 |
| 灵活调度 | 物理内存非连续,block 可任意分配和回收 |
PagedAttention 的 “block table” 是纯软件抽象——kernel 中就是一个
int32数组做完block_table[block_idx]查表 + 手工地址计算。操作系统级的虚拟内存类比仅停留在概念层面,不依赖 GPU 硬件 MMU。
3. 整体架构
vLLM V1 引擎采用分层架构:
┌──────────────────────────────────────────────────────────┐
│ API 层 (entrypoints/) │
│ ├─ OpenAI 兼容 API Server (chat/completions, /models...)│
│ └─ Python LLM 类 (离线批量推理) │
├──────────────────────────────────────────────────────────┤
│ Engine 层 (v1/engine/) │
│ ├─ LLMEngine / AsyncLLM │
│ ├─ EngineCore (核心协调器) │
│ └─ EngineCoreClient (进程间通信) │
├──────────────────────────────────────────────────────────┤
│ Scheduler 层 (v1/core/sched/) │
│ ├─ Scheduler: continuous batching 调度 │
│ ├─ KVCacheManager: block 分配/回收/prefix cache │
│ ├─ KVCacheCoordinator: 多 attention type 协调 │
│ └─ BlockPool: 物理 block 池管理 │
├──────────────────────────────────────────────────────────┤
│ Worker 层 (v1/worker/) │
│ ├─ GPUWorker: 设备管理 + 模型持有 │
│ └─ GPUModelRunner: 输入构建 + 模型执行 + 采样 │
├──────────────────────────────────────────────────────────┤
│ Model 层 (model_executor/) │
│ ├─ 模型实现 (models/): Llama, Qwen, Mistral... │
│ ├─ Attention 层: PagedAttention + FlashAttention 后端 │
│ ├─ 量化层 (quantization/): AWQ, FP8, GPTQ... │
│ └─ 模型加载器 (model_loader/): safetensors, GGUF... │
├──────────────────────────────────────────────────────────┤
│ Kernel 层 (csrc/) │
│ ├─ PagedAttention CUDA kernel (V1 + V2) │
│ ├─ KV cache 读写 kernel (reshape_and_cache) │
│ └─ Triton attention kernel (decode/prefill/unified) │
└──────────────────────────────────────────────────────────┘
4. 一次推理请求的完整生命周期
┌──────────┐ ┌──────────────┐ ┌─────────┐ ┌──────────┐ ┌───────────┐
│ 初始化 │───→│ 请求提交 │───→│ 调度 │───→│ 模型执行 │───→│ 采样+输出 │
│ (一次) │ │ (每个请求) │ │ (每step)│ │ (每step) │ │ (每step) │
└──────────┘ └──────────────┘ └─────────┘ └──────────┘ └───────────┘
初始化阶段(启动时执行一次):
1. 配置解析 → 创建 Executor/Worker → 加载模型
2. 显存 Profiling → 计算 KV cache 配置
3. 分配 KV cache tensor → 创建 BlockPool
4. CUDA graph 捕获 / 模型预热
推理循环(每个 step):
1. Scheduler 调度:分配 token 预算 + KV cache block
2. 模型执行:构建输入 → Attention → forward → logits
3. 采样:logits processors / penalties → greedy 或 top-k/top-p
4. 更新状态:追加 token、检查停止、释放已完成请求
5. 输出处理:detokenize → RequestOutput → 返回客户端
5. 关键子系统
5.1 KV Cache 内存管理
PagedAttention 中详述的 KV cache 管理子系统是整个引擎的基石:
BlockPool (物理 block 池)
├─ FreeKVCacheBlockQueue ← 双向空闲链表 (O(1) 分配/释放)
├─ BlockHashToBlockMap ← Prefix cache 哈希表
└─ KVCacheBlock × N ← 每个 block 有 ref_cnt (引用计数) + block_hash
KVCacheCoordinator
├─ NoPrefixCache: 禁用缓存
├─ Unitary: 单一 attention type → 直接委托
└─ Hybrid: 多种 attention type → 固定点迭代协调
SingleTypeKVCacheManager
├─ FullAttentionManager
├─ SlidingWindowManager ← 只保留窗口内的 block
├─ ChunkedLocalAttentionManager
├─ SinkFullAttentionManager ← sink block 永久 pin
├─ CrossAttentionManager
└─ MambaManager ← SSM state cache
5.2 Continuous Batching
与传统 “每 batch 等待所有请求完成才进入下一 batch” 不同,vLLM 的 scheduler 每个 step 都会重新调度:
Step 1: [ReqA(prefill: 100 tokens), ReqB(decode: 1 token)]
Step 2: [ReqA(decode: 1 token), ReqB(decode: 1 token), ReqC(prefill: 50 tokens)]
Step 3: [ReqA(decode: 1 token), ReqC(decode: 1 token)] ← ReqB 已完成
Step 4: [ReqA(decode: 1 token), ReqC(decode: 1 token), ReqD(prefill: 200 tokens)]
请求可以在任意 step 动态加入和退出,GPU 始终以最高效率运行。
5.3 模型加载系统
模型加载 中详述的可插拔加载架构支持 9 种权重格式、10+ 种量化方法、自动 TP 分片。核心流程:
Loader 选择 → 架构解析 (ModelRegistry) → 实例化 nn.Module → 权重加载 (TP 分片) → 量化后处理
5.4 多进程架构
┌─────────────────────────────────────────┐
│ Frontend Process (API Server / LLM) │
│ ├─ Tokenizer / InputProcessor │
│ └─ OutputProcessor / Detokenizer │
├─────────────────────────────────────────┤
│ EngineCore Process (×1 per DP group) │
│ ZMQ 通信 │
│ ├─ Scheduler │
│ └─ EngineCore.step() loop │
├─────────────────────────────────────────┤
│ Worker Processes (× num_gpus) │
│ 消息队列通信 │
│ ├─ GPUModelRunner │
│ └─ GPUWorker │
└─────────────────────────────────────────┘
- 单 GPU 模式:所有组件在同一进程内(
InprocClient) - 多 GPU 模式:EngineCore 在独立进程,Workers 在各自进程(
SyncMPClient/AsyncMPClient) - 通信方式:Frontend↔EngineCore 用 ZMQ,EngineCore↔Workers 用消息队列
6. Attention Backend 体系
| Backend | 文件 | 场景 | 特点 |
|---|---|---|---|
| FlashAttention | flash_attn.py | 默认主路径 | 原生 block_table 支持、cascade attention、FA3 AOT 调度 |
| Triton | triton_attn.py | ALiBi/SWA/FP8 | 纯 Triton、支持 block sparsity |
| FlashInfer | flashinfer 后端 | 高性能场景 | 第三方 FlashInfer 库 |
| FlexAttention | flex_attention 后端 | PyTorch 原生 | 灵活的 attention pattern |
| ROCm | rocm_attn | AMD GPU | ROCm 实现 |
| CPU | cpu_attn | CPU 后端 | 无 GPU 场景 |
Backend 选择由 selector.py:52 根据 head_size、dtype、block_size、use_mla 等自动决定。
7. 代码导航
各目录的详细职责、构建系统、C++/CUDA/Rust 代码组织见 代码结构分析。
8. 系列文档索引
| 文档 | 内容 |
|---|---|
| 代码结构分析 | 目录结构、构建系统、C++/CUDA/Rust 代码组织、CI 与测试 |
| 初始化流程分析 | Engine 启动序列:配置解析 → Executor/Worker → 模型加载 → 显存 Profiling → KV cache 分配 → Scheduler |
| 模型加载流程分析 | 模型 Loader 体系、架构解析、权重迭代器、TP 分片 weight_loader、量化后处理 |
| 推理流程分析 | Step 循环:请求提交 → 调度 → 模型执行 → Attention → 采样 → 输出处理 → KV cache 更新 |
| 算子注册与分发 | Python ↔ C++/CUDA/Triton 的桥梁:三种注册机制、attention 算子的完整分发路线 |
| FlashAttention 实现分析 | vLLM 默认 attention 后端:版本选择、forward 流程、cascade attention、DCP、与 PagedAttention 集成 |
| PagedAttention 实现分析 | Block Table 机制、KV Cache 管理、CUDA/Triton kernel 实现、纯软件 vs GPU 硬件、为何传统引擎没有此机制 |