2、vLLM架构解析:整体架构图、请求调度器、KV Cache管理器、PagedAttention机制、Worker与模型并行
好,咱们进入正题。上一章我们聊了vLLM为什么能火,这一章我们直接拆开它的「引擎盖」,看看里面到底是怎么转的。
我个人习惯,学一个系统先看整体架构图。你想想看,没有全局视角,直接扎进细节很容易迷路。所以咱们先从这张图开始。
vLLM 核心架构概览
这张图我画得比较简洁,但核心链路都在了。从上到下,用户请求进来,经过调度器、缓存管理器,最后落到GPU上执行。咱们一个一个拆。
2.1 请求调度器:排队还是插队?
请求调度器,说白了就是决定「下一个该谁上GPU跑」。vLLM用的是连续批处理(Continuous Batching)策略,跟传统的一次性批处理完全不同。
传统做法是:攒够一批请求,一起跑完,再等下一批。这中间有大量GPU空闲时间。vLLM的做法是:只要有请求完成,立刻把新请求塞进去,GPU一刻都不闲着。
我的经验:我在部署一个70B模型时,传统批处理的GPU利用率只有40%左右。换成vLLM的连续批处理后,直接飙到85%以上。你想想看,这差距有多大。
调度器的核心逻辑其实就两个问题:
- 什么时候调度?—— 只要有请求完成或新请求到达,就触发调度
- 调度谁?—— 默认FIFO,但支持优先级队列
嗯,这里要注意:调度器不是简单的「先来后到」。它会考虑当前KV Cache的剩余空间,如果某个请求需要的Cache太多,可能会被暂时搁置。
2.2 KV Cache管理器:内存的「精算师」
KV Cache是什么?简单说,就是Transformer推理时,把之前算过的Key和Value缓存下来,避免重复计算。但问题是,每个请求的KV Cache大小都不一样,而且会随着生成过程动态增长。
传统做法是预分配一块固定大小的内存。这导致两个问题:
- 预分配太大,浪费显存
- 预分配太小,请求跑到一半内存不够
vLLM的KV Cache管理器,核心思路就是按需分配、动态扩展。它把显存切成很多小块(Block),每个请求用多少就分配多少。
关键参数:
| 参数名 | 默认值 | 说明 |
|---|---|---|
| block_size | 16 | 每个Block存储的token数量 |
| gpu_memory_utilization | 0.9 | GPU显存用于KV Cache的比例 |
| max_num_seqs | 256 | 最大并发请求数 |
我曾经踩过一个坑:把gpu_memory_utilization设成0.95,结果模型权重加载完就OOM了。后来发现,这个值不是越高越好,你得给模型权重和中间激活留够空间。
2.3 PagedAttention机制:虚拟内存的「借尸还魂」
PagedAttention,这是vLLM最核心的创新。名字听着高大上,其实原理很简单——把操作系统的虚拟内存思想搬到了Attention计算中。
你想想看,操作系统怎么管理内存的?把物理内存切成4KB的页,每个进程有自己的页表。PagedAttention也一样:
- 把KV Cache切成固定大小的Block(相当于「页」)
- 每个请求维护一个Block Table(相当于「页表」)
- 物理上不连续的Block,通过Block Table映射成连续的逻辑空间
这样做的好处太明显了:
- 零碎片 —— 再也不用担心内存碎片问题了
- 共享Cache —— 多个请求可以共享相同的KV Block(比如beam search场景)
- 按需分配 —— 生成多少token,就分配多少Block
注意:PagedAttention虽然好,但也不是银弹。Block太小会导致页表过大,Block太大会造成内部碎片。我个人习惯,block_size设为16或32,具体看模型和显存大小。
2.4 Worker与模型并行:多卡协同作战
当模型大到一张卡装不下时,就需要模型并行。vLLM支持两种方式:
| 并行方式 | 原理 | 适用场景 |
|---|---|---|
| Tensor Parallelism (TP) | 把一层网络切成多份,每张卡算一部分 | 单层计算量大的模型(如LLaMA) |
| Pipeline Parallelism (PP) | 把多层网络分成多段,每张卡算一段 | 层数非常深的模型 |
vLLM的Worker,就是每个GPU上跑的那个进程。它负责:
- 加载模型权重(自己那部分)
- 执行前向计算
- 管理本地的KV Cache
- 与其他Worker通信(通过NCCL)
我记得有一次调试一个8卡TP的场景,发现某个Worker的显存占用特别高。查了半天,原来是负载不均衡——某些层的计算量天然比其他层大。后来我手动调整了切分策略,才把显存占用拉平。
调优建议:如果你用TP,tensor_parallel_size最好设成2的幂次(2、4、8)。NCCL对2的幂次通信有优化,性能能提升10%-15%。
2.5 小结:架构设计的「哲学」
回过头来看,vLLM的架构设计其实就三个核心思想:
- 不要浪费 —— 连续批处理让GPU一直忙,PagedAttention让显存不碎片
- 按需分配 —— 需要多少资源,就分配多少,不预占
- 分层解耦 —— 调度器、Cache管理器、Worker各司其职,互不干扰
说白了,vLLM就是把操作系统的那套内存管理思想,完美移植到了大模型推理中。你想想看,这思路是不是很巧妙?
下一章我们聊具体的部署配置,到时候我会手把手教你搭一个生产环境。今天就先到这里。