3、基础概念:LLM推理流程、批处理、吞吐量、延迟、显存管理

3.1 LLM推理的核心流程:从输入到输出的完整链路

理解vLLM之前,必须先在大脑中建立LLM推理的基本流水线。一次完整的推理请求,并非简单地把文本塞进模型然后得到结果,而是经历多个阶段。以自回归生成模型(如Llama、Qwen)为例,推理过程可拆解为以下四个核心阶段:

  1. 输入预处理(Preprocessing):原始文本通过分词器(Tokenizer)转换为token ID序列,并填充(Padding)或截断(Truncation)到模型要求的长度。
  2. 模型前向计算(Prefill / 预填充):将输入token序列一次性送入Transformer,并行计算所有位置的Key/Value(KV)缓存。此阶段计算密集,GPU利用率高。
  3. 自回归解码(Decode / 逐token生成):模型逐个生成新token。每生成一个token,将其追加到序列末尾,并利用上一步的KV缓存进行增量计算。此阶段内存带宽受限,GPU利用率低。
  4. 输出后处理(Postprocessing):对生成的token序列进行解码,应用停止条件(如遇到EOS token或达到最大长度),返回最终文本。

下图展示了这一核心流程,并标注了每个阶段的关键特征:

① 输入预处理 文本 → Token ID 填充/截断 ② Prefill 并行计算所有位置 生成完整KV缓存 ③ Decode 逐token增量生成 利用KV缓存 ④ 后处理 停止条件判断 Token → 文本 阶段特征对比: Prefill:计算密集(Compute-bound) GPU算力利用率高,适合并行优化 Decode:内存带宽密集(Memory-bound) 每次只生成1个token,KV缓存读取成为瓶颈 💡 关键点:Decode阶段是推理延迟的主要来源,也是vLLM优化KV缓存管理的核心战场。
理解要点:Prefill阶段处理所有输入token,Decode阶段逐token生成。两者计算特性完全不同,因此vLLM对这两个阶段采用不同的调度和优化策略。

3.2 批处理(Batching):提升吞吐量的核心手段

单个请求的推理效率很低,因为GPU在Decode阶段大部分时间处于“等待”状态。为了充分利用GPU资源,需要将多个请求合并成一批(Batch)同时处理。批处理的核心思想是:让GPU在同一个时间片内处理更多请求,从而提高硬件利用率。

传统静态批处理(Static Batching)存在明显缺陷:必须等待批次中最慢的请求完成才能释放资源,导致其他已完成请求的GPU资源被白白浪费。vLLM引入了连续批处理(Continuous Batching)机制,其核心逻辑如下:

  • 请求级调度:不再以“批次”为单位,而是以“请求”为单位进行调度。
  • 动态加入/退出:当一个请求生成完毕,立即从批次中移除,并让新请求加入,无需等待整个批次完成。
  • 迭代级调度:在每个Decode迭代中,动态决定哪些请求参与计算,哪些请求暂停等待。

下表对比了两种批处理方式的关键差异:

对比维度 静态批处理 连续批处理(vLLM)
调度粒度 批次(Batch) 单个请求(Request)
资源释放 等待最慢请求完成 请求完成立即释放
GPU利用率 存在明显空闲窗口 持续保持高利用率
新请求加入 需等待下一批次 可随时加入当前迭代
吞吐量影响 较低,受“木桶效应”限制 显著提升,可达2-3倍

3.3 吞吐量与延迟:一对需要权衡的指标

在评估LLM推理服务时,吞吐量(Throughput)和延迟(Latency)是最核心的两个性能指标,它们之间存在天然的矛盾关系。

吞吐量衡量系统在单位时间内能处理的请求数或生成的token数,常用指标包括:

  • Requests Per Second (RPS):每秒处理的请求数。
  • Tokens Per Second (TPS):每秒生成的token总数。

延迟衡量单个请求从发出到完全返回所花费的时间,通常细分为:

  • 首token延迟(TTFT, Time To First Token):从请求发出到收到第一个输出token的时间。用户感知最明显。
  • 每token生成时间(TPOT, Time Per Output Token):生成每个输出token的平均耗时。
  • 端到端延迟(E2E Latency):整个请求从开始到结束的总时间。

下图展示了批处理大小对吞吐量和延迟的影响关系:

批处理大小(Batch Size)→ 指标值 → 吞吐量(TPS) 延迟(ms) 最佳平衡区 batch=1 batch=16 batch=64
常见误区:盲目增大批处理大小虽然能提升吞吐量,但会线性增加显存占用(尤其是KV缓存),并导致单请求延迟显著上升。实际部署中需要根据业务需求(实时性要求 vs 成本效率)找到平衡点。

3.4 显存管理:LLM推理的最大瓶颈

LLM推理的显存消耗主要来自三部分:模型权重、激活值(Activations)和KV缓存。其中,KV缓存是动态增长且最容易被忽视的部分。以7B模型为例,每个token的KV缓存大小约为 2 × 层数 × 注意力头数 × 头维度 × 2字节,对于Llama-2-7B(32层,32头,128维),每个token约消耗 1MB 显存。当并发请求数达到100时,仅KV缓存就需要 100 × 序列长度 × 1MB,轻松超过10GB。

传统显存管理方式存在严重的碎片化问题:

  • 内部碎片:预分配的KV缓存块大小固定,但实际请求长度不一,导致部分块未被充分利用。
  • 外部碎片:不同请求的KV缓存块大小不同,频繁分配/释放导致显存出现大量不连续的空洞。

vLLM的核心创新——PagedAttention——借鉴操作系统虚拟内存的分页思想,将KV缓存划分为固定大小的块(Block),每个块可存储固定数量token的KV数据。通过块表(Block Table)将不连续的物理块映射为连续的虚拟空间,从而:

# PagedAttention 核心思想示意
# 物理块:Block 0, Block 1, Block 2, ...(不连续)
# 逻辑视图:Request A 的 KV 缓存 = Block 5 → Block 1 → Block 8(通过块表映射)

Block Table (Request A):
  Logical Block 0 → Physical Block 5
  Logical Block 1 → Physical Block 1
  Logical Block 2 → Physical Block 8

这种设计带来三个关键优势:

  1. 近乎零碎片:所有块大小一致,分配和释放不会产生碎片。
  2. 显存共享:多个请求可以共享相同的物理块(如并行采样时),进一步节省显存。
  3. 按需分配:只在需要时分配新块,避免预分配浪费。
量化对比:在相同硬件和负载下,vLLM通过PagedAttention可将显存利用率提升至接近90%,而传统静态分配方式通常只有40%-60%。这意味着同样的GPU可以服务更多并发请求,吞吐量提升2-4倍。

3.5 综合案例:一个典型推理请求的完整旅程

假设一个在线客服机器人收到用户消息“请帮我查询订单状态”,模型为Qwen-7B-Chat,部署在单张A10 GPU(24GB显存)上。整个推理过程如下:

  1. 请求到达:vLLM调度器将请求加入等待队列,分配一个序列ID。
  2. 预处理:分词器将文本转换为 [151644, 8948, 8832, ...] 等token ID序列,长度约15个token。
  3. Prefill阶段:15个token一次性输入模型,并行计算生成KV缓存,占用约15MB显存。此阶段耗时约20ms。
  4. Decode阶段:模型开始逐token生成回复。每生成一个token,vLLM通过PagedAttention分配新的KV缓存块。假设回复共120个token,总耗时约1.2秒(每token约10ms)。
  5. 动态调度:在Decode过程中,vLLM同时处理其他请求。当本请求生成完毕,立即释放其KV缓存块,供新请求使用。
  6. 返回结果:完整回复“您的订单已发货,预计3天内送达...”返回给用户,端到端延迟约1.3秒。

整个过程中,vLLM通过连续批处理同时服务了约20个类似请求,GPU利用率保持在85%以上,而传统静态批处理方式在相同负载下GPU利用率仅约50%。

实践建议:在部署vLLM时,可通过 --max-num-seqs 参数控制最大并发请求数,通过 --gpu-memory-utilization 控制显存使用比例(默认0.9),并根据实际业务延迟要求调整批处理策略。