引言:为什么大模型推理需要专门的框架

当你向ChatGPT提问时,背后的推理系统每秒需要处理数百万次的矩阵乘法运算。与传统的神经网络推理不同,大语言模型的推理具有独特的性能特征:自回归生成导致每个请求的输出长度不可预测,KV缓存的动态增长使得内存管理成为核心挑战,而预填充解码两个阶段截然不同的计算模式,更是要求系统设计者在延迟和吞吐量之间进行精细权衡。

传统的深度学习推理框架如ONNX Runtime或TensorFlow Serving,虽然在小模型上表现优异,但在面对大模型推理的独特需求时,往往力不从心。这催生了专门的大模型推理框架——vLLM、TensorRT-LLM、llama.cpp等,它们各自以不同的设计哲学,试图解决同一个问题:如何在有限的硬件资源上,以最低的成本、最快的速度,服务尽可能多的用户

本文将深入解析这三大主流框架的技术架构,揭示它们在内存管理、批处理策略、算子优化等核心维度上的技术博弈,帮助你理解为什么2024-2025年见证了这些框架的快速演进,以及如何根据你的业务场景做出正确选择。

第一章:大模型推理的核心挑战

1.1 自回归生成的性能困境

大语言模型的推理过程可以分解为两个截然不同的阶段:预填充(Prefill)解码(Decode)

flowchart TD
    A[用户请求] --> B[预填充阶段]
    B --> |处理完整提示词| C[计算KV缓存]
    C --> D[解码阶段]
    D --> |逐词生成| E{是否结束?}
    E --> |否| F[更新KV缓存]
    F --> D
    E --> |是| G[返回完整响应]
    
    style B fill:#e1f5fe
    style D fill:#fff3e0

预填充阶段一次性处理整个提示词,计算密集型,可以充分利用GPU的并行计算能力。而解码阶段则完全不同——每生成一个token,都需要加载整个模型的权重和所有的KV缓存,只为计算一个新token。这种内存带宽受限的特性,使得解码阶段成为推理速度的瓶颈。

根据清华大学2025年发布的《A Survey of LLM Inference Systems》综述论文,一个70B参数的模型在生成时,每秒需要从显存读取约140GB的数据(假设bf16精度),而解码阶段每次仅产生约32字节的输出。这种极端的计算强度不平衡,是传统推理框架难以高效处理大模型推理的根本原因。

1.2 KV缓存的内存管理噩梦

KV缓存是大模型推理的核心优化技术。它缓存了注意力机制中的Key和Value矩阵,避免在生成每个新token时重新计算之前所有token的表示。然而,这也带来了一个棘手的问题:KV缓存的大小是动态增长的,且无法预先确定

考虑一个服务100个并发请求的系统,每个请求可能生成1到1000个token不等。传统方法是预先为每个请求分配最大可能长度的内存,但这导致了严重的内存碎片化内部碎片问题。根据vLLM团队的测量,在静态内存分配策略下,实际内存利用率可能低至20-30%。

1.3 批处理的两难抉择

批处理是提升GPU利用率的有效手段。然而,大模型推理的批处理面临独特的挑战:

  • 静态批处理:等待一批请求全部完成才开始下一批,导致GPU空闲等待,吞吐量低
  • 请求长度差异:不同请求的输出长度差异巨大,短请求完成后,为其分配的资源被浪费
  • 首token延迟:用户期望快速看到第一个输出,但传统批处理可能导致长时间等待

这些挑战构成了大模型推理框架设计的核心约束条件。接下来,我们将看到三大主流框架如何以不同的技术路径应对这些挑战。

第二章:vLLM——内存管理的革命者

2.1 PagedAttention:将操作系统的智慧引入GPU

vLLM的核心创新是PagedAttention算法,它将操作系统中虚拟内存管理的分页思想引入了GPU内存管理。这一设计从根本上解决了KV缓存的内存碎片化问题。

flowchart LR
    subgraph 传统方法
        A1[请求1<br/>预留1000 tokens] 
        A2[请求2<br/>预留1000 tokens]
        A3[请求3<br/>预留1000 tokens]
        A4[实际使用<br/>约300 tokens<br/>浪费70%]
    end
    
    subgraph PagedAttention
        B1[Block 1<br/>16 tokens]
        B2[Block 2<br/>16 tokens]
        B3[Block 3<br/>16 tokens]
        B4[...按需分配<br/>零浪费]
    end
    
    A4 -.->|对比| B4
    
    style A4 fill:#ffcdd2
    style B4 fill:#c8e6c9

PagedAttention将KV缓存划分为固定大小的块(Block),每个块存储16个token的Key和Value向量(默认配置)。当模型需要存储新的KV缓存时,从全局的块池(Block Pool) 中按需分配,而不是预先分配连续的大块内存。

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

  1. 消除内部碎片:只有实际使用的块才被分配,浪费仅限于最后一个不完整块(最多15个token的存储)
  2. 支持内存共享:多个请求可以共享相同的KV缓存块,这对于前缀缓存至关重要
  3. 灵活的抢占机制:当内存不足时,可以精确地驱逐特定请求的块,而不是整体OOM

2.2 连续批处理:让GPU永不停歇

vLLM的另一个核心创新是连续批处理(Continuous Batching),也称为迭代级调度。与传统的静态批处理不同,连续批处理在每个解码迭代后都会重新调度请求队列。

gantt
    title 连续批处理 vs 静态批处理
    dateFormat mm:ss
    
    section 静态批处理
    请求A处理 :a1, 00:00, 10s
    请求B处理 :b1, 00:00, 15s
    请求C处理 :c1, 00:00, 8s
    GPU空闲等待 :crit, 00:08, 2s
    新批次 :n1, 00:15, 10s
    
    section 连续批处理  
    请求A处理 :a2, 00:00, 10s
    请求B处理 :b2, 00:00, 15s
    请求C处理 :c2, 00:00, 8s
    请求D(新加入) :d2, 00:08, 12s
    请求E(新加入) :e2, 00:10, 10s

其工作原理如下:

  1. 每个解码迭代开始时,调度器检查是否有请求已完成或新请求到达
  2. 将完成的请求从运行队列移除,释放其KV缓存块
  3. 将新请求加入运行队列(如果内存允许)
  4. 执行前向传播,生成所有运行请求的下一个token

这种设计使得GPU几乎不会空闲等待。根据vLLM论文的实验数据,相比静态批处理,连续批处理可以将吞吐量提升2-10倍,具体取决于请求长度的分布。

2.3 选择性批处理:解决变长序列的融合难题

连续批处理面临一个技术挑战:不同请求的序列长度不同,如何将它们批处理为一个张量?传统的批处理要求所有序列长度相同,这需要填充(Padding),浪费计算资源。

vLLM采用**选择性批处理(Selective Batching)**策略:将注意力层和非注意力层分开处理。非注意力层(如FFN、LayerNorm)可以轻松处理变长序列(将所有序列拼接成一个长序列),而注意力层则通过PagedAttention的特殊实现,在不填充的情况下处理变长序列。

# 选择性批处理的简化示意
# 非注意力层:直接处理拼接后的序列
concatenated_hidden = torch.cat([seq1, seq2, seq3], dim=0)
output = ffn(concatenated_hidden)  # 无需填充

# 注意力层:通过块表索引访问KV缓存
# 每个序列有自己的块表,指向全局块池中的块
attention_output = paged_attention(
    query, key_cache, value_cache, 
    block_tables=[block_table_1, block_table_2, block_table_3]
)

2.4 vLLM的架构全景

vLLM V1引擎的核心架构由以下组件构成:

flowchart TD
    subgraph LLM引擎
        A[处理器<br/>Tokenizer & 预处理]
        B[调度器<br/>FCFS/Priority]
        C[KV缓存管理器<br/>块池 & 分配器]
        D[模型执行器<br/>Worker & Forward Pass]
        E[输出处理器<br/>Detokenize & 后处理]
    end
    
    F[请求队列] --> A
    A --> B
    B --> |调度决策| C
    C --> |块分配| D
    D --> |前向传播| E
    E --> G[响应输出]
    
    C --> H[全局块池<br/>Block Pool]
    
    style C fill:#e8f5e9
    style D fill:#fff8e1

调度器是整个系统的核心。它维护三个队列:

  • waiting:等待处理的请求
  • running:正在解码的请求
  • swapped:被换出到CPU内存的请求(当GPU内存不足时)

调度策略支持两种模式:

  1. FCFS(先来先服务):默认策略,公平但可能不够高效
  2. Priority(优先级):高优先级请求优先服务,适用于SLA敏感的场景

KV缓存管理器维护一个全局的块池,通常包含数十万个块(取决于显存大小和块大小)。每个块的状态(空闲/已分配)、引用计数、以及关联的请求ID都被精确跟踪。

2.5 高级特性:前缀缓存与投机解码

vLLM还实现了多项高级优化技术:

**前缀缓存(Prefix Caching)**是处理多轮对话或系统提示词的关键优化。当多个请求共享相同的前缀时,前缀缓存可以重用已计算的KV缓存,避免重复计算。其实现原理是对每个块计算哈希值,存储在全局哈希表中,当新请求到达时,检查其前缀是否已在缓存中。

sequenceDiagram
    participant R1 as 请求1
    participant Cache as KV缓存
    participant R2 as 请求2
    
    R1->>Cache: 处理前缀 "你是AI助手..."
    Cache->>Cache: 计算哈希 H1, H2, H3
    Cache->>Cache: 存储KV块
    
    R2->>Cache: 处理前缀 "你是AI助手..."
    Cache->>Cache: 计算哈希 H1, H2, H3
    Cache->>Cache: 命中缓存!
    Cache-->>R2: 直接复用KV块
    Note over R2,Cache: 省略前缀的预填充计算

**投机解码(Speculative Decoding)**是另一种加速技术。其核心思想是使用一个小型草稿模型预测接下来的K个token,然后用目标模型一次性验证这K个预测。如果预测正确,一次前向传播就能生成多个token;如果预测失败,也只损失一次验证的开销。vLLM支持多种草稿策略,包括n-gram、EAGLE和Medusa。

第三章:TensorRT-LLM——硬件优化的极致追求

3.1 NVIDIA的原生优化哲学

与vLLM的通用性设计不同,TensorRT-LLM代表了另一种哲学:深度绑定硬件,榨取每一滴性能。作为NVIDIA官方推出的推理框架,TensorRT-LLM能够充分利用NVIDIA GPU的所有硬件特性。

TensorRT-LLM的核心优势在于:

  1. 算子融合:将多个小算子合并为一个大算子,减少内存访问和内核启动开销
  2. 精度优化:支持FP8、INT8、INT4等多种量化格式,以及混合精度计算
  3. 图优化:分析计算图,消除冗余计算,优化内存布局
  4. 特定架构优化:针对H100、A100等不同GPU架构进行定制优化

3.2 模型编译:用时间换性能

TensorRT-LLM采用**提前编译(AOT, Ahead-of-Time)**策略。在部署模型之前,需要将模型编译成TensorRT引擎,这个过程可能需要几分钟到几小时不等。

flowchart LR
    A[HuggingFace<br/>模型权重] --> B[TensorRT-LLM<br/>编译器]
    B --> |优化Pass| C[TensorRT引擎<br/>.plan文件]
    C --> D[推理服务]
    
    B --> E[算子融合]
    B --> F[精度校准]
    B --> G[内存规划]
    B --> H[CUDA Graph<br/>捕获]
    
    style C fill:#c8e6c9

编译过程包括:

  • 层融合:将Linear-Bias-ReLU等连续操作合并为单一内核
  • 精度校准:确定每层的最优精度,平衡精度和性能
  • 内存规划:静态分配所有中间张量的内存位置
  • CUDA Graph捕获:将计算图录制为可重放的CUDA Graph

这种策略的代价是灵活性降低:更换模型或修改配置都需要重新编译。但其优势是在推理时几乎零开销——所有优化决策都已预先完成。

3.3 Paged KV Cache:学习vLLM的智慧

TensorRT-LLM也实现了类似PagedAttention的Paged KV Cache机制,但其实现更加底层和优化。关键差异包括:

  1. 块大小可配置:可以根据模型特性和硬件调整块大小
  2. 与FlashAttention深度集成:块访问模式针对FlashAttention进行了优化
  3. 异步块分配:在后台线程中预分配块,减少关键路径延迟

3.4 Inflight Batching:NVIDIA的连续批处理

TensorRT-LLM实现了名为Inflight Batching的连续批处理机制。其核心特点是:

  • 动态形状处理:支持变长序列的无缝批处理
  • 上下文与生成混合:可以在同一批次中处理预填充和解码请求
  • 自动负载均衡:根据请求长度动态调整批次组成
flowchart TD
    subgraph 迭代1
        A1[请求A: Prefill] 
        B1[请求B: Decode]
        C1[请求C: Decode]
    end
    
    subgraph 迭代2
        A2[请求A: Decode]
        B2[请求B: 完成!]
        C2[请求C: Decode]
        D2[请求D: Prefill<br/>新加入]
    end
    
    subgraph 迭代3
        A3[请求A: Decode]
        C3[请求C: Decode]
        D3[请求D: Decode]
        E3[请求E: Prefill<br/>新加入]
    end
    
    迭代1 --> 迭代2 --> 迭代3

3.5 性能实测:TensorRT-LLM的优势场景

根据BentoML在2024年的基准测试,TensorRT-LLM在以下场景中表现突出:

场景 模型 vLLM TensorRT-LLM 优势
低延迟(<100ms TTFT) Llama-3-70B Q4 85ms 62ms 27%更快
高吞吐 Llama-3-8B 4741 T/s 5452 T/s 15%更高
长上下文 Llama-3-8B 128K 较慢 2.72x更快 显著优势
超大规模(100+并发) Llama-3-70B 稳定 略优 边际优势

TensorRT-LLM在低延迟长上下文场景中具有明显优势,这得益于其深度优化的内核和内存访问模式。然而,在中等规模的生产环境中,vLLM的性能已经足够好,而其易用性和灵活性更具吸引力。

第四章:llama.cpp——跨平台的极简主义

4.1 CPU优先的设计哲学

llama.cpp的设计哲学与vLLM和TensorRT-LLM截然不同。它的目标是:让大模型推理可以在任何硬件上运行——从高端服务器到树莓派,从NVIDIA GPU到苹果M系列芯片。

这种哲学体现在几个关键设计决策上:

  1. 纯C++实现:无Python依赖,启动快,内存占用小
  2. 量化优先:支持GGUF格式的多种量化方案,从Q4_0到Q8_0
  3. CPU优先:核心优化针对CPU架构,GPU支持作为加速选项
  4. 零依赖:除了标准C++库,不需要任何外部依赖

4.2 GGUF格式:量化艺术的巅峰

llama.cpp引入了GGUF格式,这是一种专门为大模型推理设计的文件格式。GGUF的创新之处在于:

flowchart LR
    subgraph GGUF文件结构
        A[文件头<br/>元数据]
        B[词表<br/>Tokenizer]
        C[张量信息表<br/>名称/类型/偏移]
        D[量化权重<br/>Q4_0/Q5_1/KQ...]
    end
    
    A --> B --> C --> D
    
    subgraph 量化方案
        E[Q4_0: 4-bit<br/>无缩放因子]
        F[Q5_1: 5-bit<br/>带缩放因子]
        G[Q8_0: 8-bit<br/>高精度]
        H[K-Quants: 混合精度]
    end

K-Quants是llama.cpp的最新创新,它对不同层采用不同的量化策略:

  • 关键层(如注意力输出层)使用较高精度(Q6_K)
  • 不敏感层使用较低精度(Q4_K)
  • 这种混合策略在几乎不损失模型质量的情况下,实现了更小的模型体积

4.3 CPU推理的深度优化

llama.cpp对CPU推理进行了极致优化,包括:

SIMD向量化:针对不同CPU架构使用SIMD指令

  • x86: AVX2, AVX-512
  • ARM: NEON
  • Apple Silicon: ARM NEON + AMX(矩阵扩展)

内存访问优化

  • 缓存友好的权重布局
  • 预取和循环展开
  • 减少缓存未命中

多线程并行

  • 层间并行:不同层在不同线程上计算
  • 注意力头并行:多个注意力头并行计算
  • 批处理并行:多个序列并行处理
// llama.cpp的注意力计算简化示意
void attention_forward(
    const float* query,    // [n_heads, head_dim]
    const float* key_cache,   // [n_layers, n_ctx, n_heads, head_dim]
    const float* value_cache, // [n_layers, n_ctx, n_heads, head_dim]
    float* output,
    int n_heads, int head_dim, int n_ctx
) {
    #pragma omp parallel for  // 多线程并行
    for (int h = 0; h < n_heads; h++) {
        // SIMD优化的注意力计算
        float* scores = alloca(n_ctx * sizeof(float));
        for (int t = 0; t < n_ctx; t++) {
            scores[t] = dot_product_simd(
                &query[h * head_dim],
                &key_cache[t * n_heads * head_dim + h * head_dim],
                head_dim
            );
        }
        softmax_inplace(scores, n_ctx);
        // 加权求和
        weighted_sum_simd(value_cache, scores, output, ...);
    }
}

4.4 GPU后端:CUDA、Metal、Vulkan

虽然CPU是llama.cpp的核心,但它也支持多种GPU后端:

后端 平台 特点
CUDA NVIDIA GPU 最成熟的GPU支持,性能接近原生
Metal Apple Silicon 充分利用统一内存架构,零拷贝
Vulkan 跨平台 支持AMD、Intel等GPU
SYCL Intel GPU 针对Intel架构优化
HIP AMD ROCm AMD GPU原生支持

Apple Silicon的Metal后端是一个特别值得关注的优化。由于M系列芯片采用统一内存架构,CPU和GPU共享同一块物理内存,llama.cpp可以:

  • 零拷贝在CPU和GPU之间传递数据
  • 动态决定哪些层在CPU上计算,哪些在GPU上计算
  • 支持"部分卸载":模型太大时,只将部分层放入GPU内存

4.5 llama.cpp的独特价值

llama.cpp的核心价值在于其普适性。当你的约束条件是:

  • 没有NVIDIA GPU:llama.cpp是唯一的选择
  • 内存有限:4-bit量化让70B模型可以在16GB内存中运行
  • 需要快速原型验证:无需编译,下载即用
  • 边缘设备部署:从手机到嵌入式设备都能运行

第五章:三大框架的技术博弈全景

5.1 设计哲学对比

维度 vLLM TensorRT-LLM llama.cpp
核心目标 高吞吐服务 极致性能 普适运行
硬件绑定 CUDA/ROCm NVIDIA CUDA 跨平台
内存管理 PagedAttention Paged KV Cache 静态分配
批处理策略 连续批处理 Inflight Batching 静态/动态
优化深度 算法层面 硬件层面 编译层面
易用性 极高
灵活性

5.2 性能特征分析

根据清华大学综述论文的分析,三大框架的性能特征可以总结为:

radar-beta
    title 推理框架性能雷达图
    
    axis 吞吐量["吞吐量"], 延迟["首Token延迟"], 内存效率["内存效率"], 易用性["易用性"], 硬件兼容["硬件兼容"], 模型支持["模型支持"]
    
    curve{vLLM}: 9, 7, 9, 9, 6, 9
    curve{TensorRT-LLM}: 9, 9, 8, 5, 3, 7
    curve{llama.cpp}: 5, 6, 7, 10, 10, 8

吞吐量:vLLM和TensorRT-LLM在高并发场景下吞吐量接近,都远超llama.cpp

首Token延迟:TensorRT-LLM在短提示词场景下延迟最低,得益于其优化的预填充内核

内存效率:vLLM的PagedAttention提供了最佳的内存利用率

易用性:llama.cpp几乎零配置即可运行,vLLM次之,TensorRT-LLM需要编译步骤

硬件兼容性:llama.cpp支持最广泛的硬件,vLLM支持CUDA和ROCm,TensorRT-LLM仅支持NVIDIA

模型支持:vLLM支持最广泛的模型架构(包括MoE、多模态等)

5.3 适用场景指南

基于以上分析,我们可以给出场景化的选择建议:

flowchart TD
    A[选择推理框架] --> B{是否有NVIDIA GPU?}
    B --> |否| C[llama.cpp<br/>唯一选择]
    B --> |是| D{是否需要极致性能?}
    D --> |是| E{是否接受编译延迟?}
    E --> |是| F[TensorRT-LLM<br/>最佳性能]
    E --> |否| G[vLLM<br/>性能接近,更灵活]
    D --> |否| H{并发用户数?}
    H --> |<10| I[vLLM或llama.cpp<br/>都可以]
    H --> |>50| J[vLLM<br/>高吞吐优势]
    
    style C fill:#c8e6c9
    style F fill:#c8e6c9
    style G fill:#c8e6c9
    style J fill:#c8e6c9

选择vLLM当你需要

  • 高并发在线服务(100+ QPS)
  • 快速部署和迭代(无需编译)
  • 支持多种模型架构(MoE、多模态)
  • 灵活的硬件选择(NVIDIA、AMD)

选择TensorRT-LLM当你需要

  • 极致的延迟优化(<50ms TTFT)
  • 最大吞吐量(成本敏感的大规模部署)
  • 长上下文处理(128K+ tokens)
  • 对NVIDIA硬件的深度利用

选择llama.cpp当你需要

  • 在非NVIDIA硬件上运行
  • 本地推理或边缘部署
  • 快速原型验证
  • 最小化依赖和启动时间

第六章:未来演进方向

6.1 分离式架构:预填充与解码的解耦

一个新兴的趋势是分离式推理架构(Disaggregated Inference),即将预填充和解码分配到不同的计算节点。这种架构的优势在于:

  1. 资源优化:预填充节点可以配置更多计算资源,解码节点配置更多内存带宽
  2. 负载均衡:独立扩展预填充和解码能力
  3. 延迟控制:预填充节点专注于降低TTFT,解码节点专注于提升解码速度

vLLM已经在V1版本中支持这种架构,允许配置N个预填充实例和M个解码实例,KV缓存通过网络传输。

6.2 量化技术的深度融合

量化已经从推理优化技术演进到训练感知量化。最新的趋势包括:

  • INT4训练:直接使用4-bit精度进行训练,大幅降低训练成本
  • 混合精度量化:不同层使用不同精度,平衡精度和效率
  • 动态量化:根据输入动态调整精度,在关键位置保持高精度

6.3 推理-训练一体化

随着测试时计算(Test-Time Compute)的兴起,推理和训练的边界正在模糊。未来框架可能需要同时支持:

  • 推理时的在线学习
  • 强化学习推理(如o1模型的思维链)
  • 动态模型更新

结语:没有银弹,只有权衡

大模型推理框架的演进史,本质上是内存、计算、延迟、吞吐量四个维度上的权衡史。vLLM选择在内存管理上突破,TensorRT-LLM选择在硬件优化上深耕,llama.cpp选择在普适性上发力。

正如计算机科学的永恒真理:没有银弹。选择哪个框架,取决于你的业务约束和优化目标。但理解它们背后的技术博弈,能帮助你在面对复杂的生产环境时,做出更明智的决策。

当你在深夜调试推理服务,看着GPU利用率在30%到90%之间波动时,希望这篇文章能帮助你理解:这不只是配置问题,这是系统设计的哲学选择。而每一次选择,都在定义你的AI产品的用户体验边界。


参考文献

[1] Kwon et al., “Efficient Memory Management for Large Language Model Serving with PagedAttention”, SOSP 2023

[2] Pan & Li, “A Survey of LLM Inference Systems”, arXiv:2506.21901, 2025

[3] NVIDIA, “TensorRT-LLM: High-Performance Inference for Large Language Models”, 2024

[4] ggml-org, “llama.cpp: LLM Inference in C/C++”, GitHub Repository

[5] Yu et al., “Orca: A Distributed Serving System for Transformer-Based Generative Models”, OSDI 2022

[6] Dao et al., “FlashAttention: Fast and Memory-Efficient Exact Attention with IO-Awareness”, NeurIPS 2022

[7] Leviathan et al., “Fast Inference from Transformers via Speculative Decoding”, ICML 2023

[8] OpenAI, “How AI Training Scales: The Gradient Noise Scale”, 2018