跳到主要内容
AI大模型推理过程与优化技术实战 | 极客日志
Python AI 大前端 算法
AI大模型推理过程与优化技术实战 大模型推理可分为 Prefill 与 Decoding 两个阶段:前者负责输入编码、QKV 生成和 KV Cache 建立,后者基于缓存逐 token 生成结果。文章进一步梳理了 FlashAttention、vLLM/PagedAttention、Continuous Batching、量化压缩以及张量并行和流水线并行等优化手段,并给出 vLLM 推理与量化并行的 Python 实战示例,帮助理解大模型推理在性能与资源上的工程实现思路。
DevOpsTeam 发布于 2025/2/5 0 浏览一、AI 大模型推理过程概述
近年来,随着算力提升和算法演进,大模型已经成为人工智能领域最重要的技术方向之一。围绕 Transformer 架构的大模型推理,本质上就是把输入文本转成模型可处理的表示,再借助注意力机制逐步生成输出。
推理过程通常分成两个阶段:Prefill 和 Decoding 。前者负责把整段输入一次性编码进模型,并建立上下文缓存;后者则在缓存的基础上,按 token 逐步生成结果。理解这两个阶段,基本就抓住了大模型推理的主线。
1.1 Transformer 架构基础
Transformer 自 2017 年提出后,几乎重塑了 NLP 的技术栈。它和 RNN 最大的不同,在于不再依赖逐步递推,而是通过注意力机制直接建模序列中任意位置之间的关系,因此在长距离依赖和并行计算方面都更有优势。
Transformer 的几个核心组件包括:
编码器 :将输入序列转换为高维向量表示。
解码器 :基于上下文信息生成输出序列。
位置编码 :为没有天然顺序感的向量补充位置信息。
多头注意力 :让模型从多个角度同时关注不同特征。
1.2 注意力机制的重要性
注意力机制是 Transformer 能够'理解上下文'的关键。它不会平均对待所有输入,而是为更相关的部分分配更高权重。对大模型来说,这种选择性关注能力非常重要,因为它直接决定了模型在长文本、复杂问答和多轮对话中的表现。
1.3 推理流程详解
1.3.1 Prefill 阶段
Prefill 阶段是推理的起点。系统接收到输入文本后,会先完成分词、向量化、Embedding 查表,再生成 Q、K、V 张量,并把 K、V 写入缓存。这个阶段的特点很明显:计算量大,但并行度高 。
Prefill 的典型流程如下:
解析输入文本并做必要预处理
将 token 映射为向量表示
叠加位置信息
计算 QKV
建立 KV Cache,供后续解码复用
因为整段输入可以同时参与计算,所以 Prefill 很适合跑在 GPU 上做批量并行处理。这也是大模型服务在高并发场景下还能保持吞吐的基础。
1.3.2 Decoding 阶段
Decoding 阶段负责'一个 token 一个 token 地生成结果'。模型会利用已有输入和 KV Cache,计算当前步最可能输出的下一个 token,再把这个 token 追加回上下文中,进入下一轮推理。
Decoding 的核心步骤可以概括为:
根据当前 token 生成查询向量 Q。
与缓存中的 K、V 计算注意力。
融合上下文信息,得到新的隐藏表示。
通过采样或贪心策略选择下一个 token。
这个阶段最需要关注的就是递归性。每生成一个 token,都要更新缓存并继续下一轮计算。也正因为如此,Decoding 往往比 Prefill 更容易成为推理性能的瓶颈。
二、Prefill 阶段详解
Prefill 阶段可以理解为'给模型做上下文准备'。它不直接产出最终答案,但决定了后续生成是否准确、是否连贯。
2.1 输入理解与初始化 用户请求进来后,系统首先要做的是理解输入意图,而不是急着往模型里塞文本。比如'告诉我天气'和'今天会下雨吗'看起来都在问天气,但意图和表达方式并不完全相同。前者更偏命令式,后者更偏查询式。
数据预处理 在进入模型之前,原始文本通常会经历一些基本清洗:去除无关符号、统一格式、必要时做分词或词形归一化。这里的目标不是'把文本变简单',而是让后续表示更稳定,减少噪声对模型的干扰。
2.2 用户输入向量化 文本要先变成模型能处理的数字表示。常见做法是使用词嵌入,把 token 映射到固定维度的向量空间里。语义相近的词,在向量空间中的距离也会更近,这对模型捕捉上下文关系很有帮助。
2.2.1 词汇映射 词嵌入的价值在于,它把离散符号变成了可计算的连续向量。这样一来,模型不再只是'记住词',而是可以学习词与词之间更细粒度的关系。
2.2.2 序列编码 仅有词级表示还不够,模型还必须知道每个词在序列中的位置。因此,序列编码和位置建模就变得很关键。RNN、LSTM 曾经是常见方案,但在大模型里,Transformer 由于并行性更强、长距离建模能力更好,已经成为主流。
2.3 Embedding 层处理
2.3.1 嵌入表查找 Embedding 层本质上就是一次查表操作:输入 token id,输出对应向量。这里的查表不是简单映射,而是把离散 ID 转成模型真正参与计算的稠密表示。
2.3.2 位置编码添加 如果没有位置编码,模型只能知道'有哪些词',却不知道'词的顺序'。常见做法是将位置编码加到词向量上,让模型同时保留词义信息和位置信息。这个设计很朴素,但非常有效。
2.4 自注意力计算
2.4.1 注意力权重计算 自注意力的核心,就是计算序列中任意两个位置之间的相关性。做法通常是先通过线性变换得到 Q、K、V,再计算 Q 和 K 的相似度,经过 softmax 后得到权重,最后对 V 加权求和。
$$\text{Attention}(Q, K, V) = \text{softmax}\left(\frac{QK^T}{\sqrt{d_k}}\right)V$$
2.4.2 多头机制应用 多头注意力会并行计算多个注意力子空间。这样做的好处很直接:模型可以从不同角度理解同一段输入,既能关注局部细节,也能捕捉全局语义。多个头的输出最后再拼接融合,完成一次完整的自注意力计算。
三、Decoding 阶段详解
3.1 Decoding 阶段关键步骤 Decoding 阶段的任务很明确:根据已有上下文,预测下一个最可能的 token。由于是逐 token 生成,它天然带有递归特征。
利用当前 Q 与 KV Cache 计算注意力权重
将权重与 V 融合,得到上下文表示
经过前馈网络,生成输出向量
通过采样或确定性策略选出下一个 token
3.2 Decoding 过程详解 Decoding 的难点,不在于'能不能生成',而在于'能不能既快又稳'。如果每一步都重复计算历史上下文,性能会迅速下降。因此,KV Cache 几乎是大模型推理里绕不开的优化手段。
KV Cache 的思路很实在:把前面算过的 K 和 V 保存下来,后续生成时直接复用,避免重复计算。这对长文本尤其重要,越长的上下文,收益越明显。
除了 KV Cache,推测解码(speculative decoding) 也是一种很有代表性的优化思路。它会先让小模型快速提出候选 token,再由大模型验证或修正。这样能在尽量不损失质量的前提下,把生成速度往前推一大截。
四、大模型推理优化技术
4.1 计算优化
4.1.1 FlashAttention FlashAttention 的核心目标很明确:减少高带宽内存(HBM)的访问次数。它不是单纯把注意力算得更快,而是把内存访问模式也一起优化了。
分块处理 :把长序列拆成多个小块分别计算。
只保留必要中间结果 :避免把完整注意力矩阵长期放在显存里。
这样做的直接收益很明显:显存占用更低,访问更少,整体吞吐更高,而且对模型效果的影响很小。
4.1.2 vLLM vLLM 在推理侧广受关注,核心就在于它对 KV Cache 的管理方式做得非常高效。它采用的 PagedAttention 思路,借鉴了操作系统的分页机制,把 KV 缓存拆成固定大小的块,再通过块表完成逻辑地址到物理地址的映射。
提升显存利用率
缓解碎片化问题
支持更长上下文的推理
对于长文本生成或高并发服务来说,这种优化非常实用。
4.2 内存优化
4.2.1 Continuous Batching Continuous Batching 不是传统意义上的'攒一批一起算',而是把请求拆到更细的阶段里动态拼批。新请求来了,不必老老实实等上一批完全结束,而是可以在合适的阶段插入当前批次中继续执行。
这类调度优化看起来没有模型结构那么'显眼',但在真实服务里往往更能决定体验。
4.2.2 PagedAttention PagedAttention 解决的是 KV Cache 的碎片化存储问题。传统连续分配在长序列和高并发场景下很容易浪费显存,而分页式管理能更灵活地复用空间。
把 KV Cache 切分成固定大小的 pages
每个 page 存放若干 token 的 K/V 张量
用 block table 建立逻辑页与物理页的映射
按需分配与回收空间
这类设计在长上下文推理里尤其重要,能显著提高资源利用率。
4.3 量化压缩 量化的目标,是用更低精度表示模型参数和激活值,从而减少存储和计算开销。最常见的做法是把 FP32 量化为 INT8,甚至进一步压到 INT4。
$$X_{int} = \text{clip}\left(\left\lfloor\frac{X}{scale}\right\rfloor + zero_point, -128, 127\right)$$
其中,$X$ 是原始浮点值,$scale$ 是缩放因子,$zero_point$ 是零点偏移。
当然,量化也会带来精度损失,所以实际工程里常常会结合混合精度、动态量化或知识蒸馏来尽量把损失压下去。
4.4 并行策略
4.4.1 张量并行(Tensor Parallelism, TP) 张量并行的思路是把大矩阵拆到多个设备上共同计算,尤其适合权重矩阵很大的场景。它能缓解单卡显存压力,也能提升矩阵计算吞吐。
它的代价也很明确:通信开销会增加,工程实现复杂度也更高。因此,TP 通常更适合配合高带宽互联环境一起使用。
4.4.2 流水线并行(Pipeline Parallelism, PP) 流水线并行把模型不同层切到不同设备上,像工厂流水线一样逐段处理。它的优势是显而易见的:单卡要承载的参数更少,整体模型规模可以继续往上扩。
但流水线并行也有自己的问题,尤其是阶段之间的依赖和调度。如果切分不合理,很容易出现某些 GPU 忙不过来、某些 GPU 在等数据的情况。
在真实系统里,很多大模型会采用混合并行:把张量并行、流水线并行和数据并行结合起来,尽量在吞吐、延迟和显存占用之间找到一个平衡点。
五、代码实战样例
5.1 vLLM 推理示例 下面这段示例展示了如何使用 vLLM 进行大模型推理。重点不在于语法本身,而在于它的使用方式:先初始化模型,再构造 prompt 和采样参数,最后统一发起生成请求。
from vllm import LLM, SamplingParams
import os
os.environ['CUDA_VISIBLE_DEVICES' ] = '0'
model_path = "/path/to/your/model"
llm = LLM(
model=model_path,
trust_remote_code=True ,
tokenizer=model_path,
tokenizer_mode='slow' ,
tensor_parallel_size=1
)
prompts = [
"Hello, my name is" ,
"The president of the United States is" ,
"The capital of France is" ,
"The future of AI is" ,
]
sampling_params = SamplingParams(
temperature=0.8 ,
top_p=0.95 ,
max_tokens=100
)
outputs = llm.generate(prompts, sampling_params)
for output in outputs:
prompt = output.prompt
generated_text = output.outputs.text
print (f"Prompt: {prompt!r} , Generated text: {generated_text!r} " )
trust_remote_code=True 适用于需要加载自定义模型代码的场景。
tokenizer_mode='slow' 通常更稳妥,但速度不如 fast 模式。
SamplingParams 里的 temperature 和 top_p 共同决定生成文本的随机性和收敛程度。
如果你在服务端做批量推理,vLLM 的优势会更明显,因为它对 KV Cache 和批处理做了专门优化。
5.2 推理性能优化实践 下面这个示例演示了'量化 + 并行 + 关闭梯度'这一类常见优化思路。虽然代码本身比较简化,但它表达的工程思路是对的:把计算负担尽量往前压,把推理路径尽量收紧。
import torch
import torch.nn as nn
from transformers import AutoModel, AutoTokenizer
from optimum.onnxruntime import ORTQuantizer
model_name = "EleutherAI/gpt-j-6B"
tokenizer = AutoTokenizer.from_pretrained(model_name)
model = AutoModel.from_pretrained(model_name)
quantizer = ORTQuantizer.from_pretrained(model)
quantized_model = quantizer.quantize(save_directory="quantized_gptj" )
quantized_model = AutoModel.from_pretrained("quantized_gptj" )
if torch.cuda.device_count() > 1 :
model = nn.DataParallel(model)
input_text = "Hello, how are you?"
input_ids = tokenizer.encode(input_text, return_tensors="pt" )
with torch.no_grad():
output = model(input_ids)
output_text = tokenizer.decode(output)
print (output_text)
量化 :把模型参数压到更低精度,减少显存和算力消耗。
并行 :在多 GPU 环境下分担计算压力。
推理模式 :使用 torch.no_grad() 关闭梯度计算,减少额外开销。
需要说明的是,真实业务中还会进一步考虑模型类型、输出格式和后处理逻辑,尤其是生成类模型,不能简单把张量直接拿去 decode,通常还要先经过 token id 的整理和截断。
六、结语 大模型推理并不只是'把输入喂给模型、等它吐出答案'这么简单。Prefill、Decoding、KV Cache、FlashAttention、PagedAttention、量化、并行策略,这些环节彼此配合,才构成了今天高性能推理系统的核心。
如果你要真正把大模型落到生产环境,最值得关注的往往不是某一个单点技巧,而是整条链路的协同:算得快、存得下、调度得动、生成得稳。把这几件事同时做好,推理系统才算真正能用、好用。
相关免费在线工具 加密/解密文本 使用加密算法(如AES、TripleDES、Rabbit或RC4)加密和解密文本明文。 在线工具,加密/解密文本在线工具,online
RSA密钥对生成器 生成新的随机RSA私钥和公钥pem证书。 在线工具,RSA密钥对生成器在线工具,online
Mermaid 预览与可视化编辑 基于 Mermaid.js 实时预览流程图、时序图等图表,支持源码编辑与即时渲染。 在线工具,Mermaid 预览与可视化编辑在线工具,online
随机西班牙地址生成器 随机生成西班牙地址(支持马德里、加泰罗尼亚、安达卢西亚、瓦伦西亚筛选),支持数量快捷选择、显示全部与下载。 在线工具,随机西班牙地址生成器在线工具,online
Gemini 图片去水印 基于开源反向 Alpha 混合算法去除 Gemini/Nano Banana 图片水印,支持批量处理与下载。 在线工具,Gemini 图片去水印在线工具,online
curl 转代码 解析常见 curl 参数并生成 fetch、axios、PHP curl 或 Python requests 示例代码。 在线工具,curl 转代码在线工具,online