!大模型LLM推理优化技术
先给你讲个真事儿。
去年十一月,我蹲在工位前,盯着GPU监控面板上那条缓慢爬升的绿线,心里想:“完了,这东西真要这么慢,老板下一个裁的就是我。” 你猜怎么着?用LLaMA-7B生成一段200字的回复,预填充阶段0.3秒挺爽,但到了逐字蹦的时候,一个字要50毫秒。200个字啊,硬生生等10秒——这体验,搁谁谁想用?
所以今天这篇,是我翻车几个月后,蹲在每一行日志前面抠出来的真实体会。觉得有用就留着,觉得我在吹,那您划走就成。
先说清楚推理到底在算啥
很多文章一上来就甩公式,看着头大。其实核心就两件事:预填充(Prefill) 和 解码(Decode)。
预填充像你点菜——把“今天天气怎么样”这行字一次性拆成token,然后GPU一口气并行算出中间状态。这时候算力拉满,爽得很。
解码呢?像你吃菜——一个字一个字嚼。每蹦一个字,都得依赖前面所有字的计算结果。这时候矩阵运算变成了向量运算,算力利用率直线掉。
你看,那个“又笨重又慢”的解码阶段,跟你点外卖等出餐一样难受。
FlashAttention——我见过最聪明的优化之一
第一次读到FlashAttention论文,标题平淡得像白开水。但看完它分块计算的思路,我当晚就在朋友圈写:“这人是个天才。”
传统注意力计算的问题是什么?复杂度O(n²)——序列长度翻倍,计算量翻四倍,中间结果还得频繁写回显存,本质上就是IO瓶颈。
FlashAttention的骚操作呢?把注意力计算拆成一块一块,每块在GPU共享内存里算完再合并,省掉了跟显存反复倒腾的时间。拿我亲测的数据:序列长度2048(主要是在prefill阶段),换了FlashAttention后,推理速度快了3.2倍。一样的显卡,一样的模型,什么都没动。
不过有坑:FlashAttention在显存小的卡上容易炸。我试过RTX 3060,分块参数调不好直接OOM。所以别盲目追新,先看看自己手头的硬件能不能撑住。
投机解码——好东西,但不是万能
投机解码我第一次看到,第一反应是:这不就是作弊嘛。用小模型先猜,大模型再校验。
我搭了个测试环境:草稿模型是大模型蒸馏出来的小模型(参数量大概是大模型的1/5),目标模型是LLaMA-13B,500条中文问答。结果呢?首token生成速度没变,但整体吞吐量提升了2.3倍。
它赌的是一个直觉:大多数情况下,小模型猜的词,大模型大概率会同意。只有当小模型押错了,才回退重来。
调优下来的经验值:草稿候选词条数量设在5到8个最划算。少于5收益太小,多于8容易频繁回退,反而更慢。
但如果你做的是法律文书、医疗病例这类垂直场景,小模型和大模型的知识差距会很大,投机接受率可能低到40%。这种情况下,老老实实跑大模型反而更快。
所以我的建议是:先跑一个profiling算算你场景下的接受率。低于70%,就别费劲了。
解码参数——真没你想得那么玄
说句得罪人的话:现在有些“调参大师”,搞的玄学都快赶上风水了。
温度系数、top-k、top-p,这三个参数我一句话给你讲明白:
温度是调节自信心的。温度低,模型就只敢选高概率的词,回答严谨但可能僵硬;温度高,模型的“想象力”放飞,但也容易胡说八道。
top-k和top-p是限制候选范围的。k=40意思是从概率最高的40个词里选;p=0.9意思是选词直到累计概率达到90%。
我自己写代码的时候temperature设0.1,写故事的时候设0.8。为什么?试了几百轮,就这个组合最顺手。
所以别听那些“温度0.7最完美”的鬼话。每个场景、每个模型都不一样,老老实实做A/B测试比什么都强。
主流模型到底差在哪
上次群里有人问:GPT-4和LLaMA-3,底层到底有什么区别?
我这么回答:基础架构基本一样,都是Transformer的变体。区别主要在三块:
第一是架构细节。GPT-4普遍被认为用了MoE(混合专家),LLaMA没有。MoE的好处是同样的计算量,模型的知识容量更大。
第二是训练数据。这是最核心的差异。GPT-4喂了什么数据?没人知道。但我知道的是,同样的推理优化技术,在不同数据上训练出来的模型上效果能差50%。
第三是对齐策略。RLHF做得好不好,直接决定了模型表现。我测过几个开源模型,基座模型能力差不多,但经过对齐后,对话能力能差十条街。
谁比谁强?分场景。代码生成我选GPT-4;中文创意写作,我觉得有些国产模型反而更好用。
五个优化方向——一篇真说不完
用一个简单的直觉出发:时间 ≈ 计算量 ÷ 算力。要缩短推理时间,要么把计算量降下来,要么把算力用得更充分,要么减少倒腾数据的开销,要么让硬件只干最有效的事,要么从算法上直接改算的方式。
方向一:减少计算量
量化、稀疏化、知识蒸馏都归在这。我跑过几个比赛,发现量化是最直接的手。FP16降到INT8,模型显存占用直接减半,在支持INT8加速的硬件上速度也能翻倍,而且现在不少模型量化后精度损失不到1%。
但坑来了。刚开始用PyTorch量化API,模型直接崩了,输出全是乱码。后来才明白,不同量化方法适合不同场景:GPTQ适合离线部署,AWQ在量化时会考虑激活值分布,对敏感场景更友好。
方向二:提升算力利用率
这个方向的技术最杂,从FlashAttention到各种并行策略都算。
我用A100测过张量并行(TP)和流水线并行(PP)。8卡A100,张量并行能把推理速度提升6.5倍,流水线并行只能做到4.2倍。但张量并行需要通信带宽,如果你用的是PCIe而不是NVLink互联,效果会差很多。
所以别盲信官方文档的加速比,实测才能说明问题。
方向三:访存优化
KV Cache是这个方向的重头戏。解码阶段每生成一个token,之前的key和value都要用到。如果不缓存,每次都得从头算。
用了PagedAttention(vLLM的核心技术)后,内存利用率从40%提升到了75%。说白了,就是给KV Cache加了分页管理,不再被内存碎片搞得焦头烂额。
但分页也有代价。vLLM的调度开销小,可如果你同时跑太多请求,显存还是会爆。
方向四:批处理策略
Continuous Batching(连续批处理)这个词,第一次见到觉得是噱头,后来真香了。
传统批处理是等所有请求来齐了才开始处理,而连续批处理在每个解码步动态调整批次的组成。我测过,在同等延迟约束下,连续批处理的吞吐量是传统批处理的2.5倍。
但也要看场景。如果服务的请求数不多,批处理带来的收益就很有限。只有高并发场景才需要上连续批处理。
方向五:算法层面
投机解码、分块预填充这些都归在这。前面已经聊过,不重复了。
现在框架那么多,到底选哪个
这个问题每周都有人问我。直接给结论:
- **vLLM**:最成熟,社区活跃,适合生产环境。我用它部署过Qwen-72B,稳定运行了三个月没出大问题。
- **SGLang**:RadixAttention做得很好,适合前缀频繁复用的场景,比如多轮对话。
- **TensorRT-LLM**:NVIDIA官方的,极致优化,但上手成本高,踩坑了连文档都查不到。
- **Llama.cpp**:CPU推理的神器,但我只在低资源场景用。
新手入门推荐vLLM。文档全、社区大、问题好搜。
追求极致性能就上TensorRT-LLM,但做好debug三个月以上的准备。
最后说几句掏心窝子的话
写这篇文章不是为了显摆自己多懂。恰恰相反,是想让你少走一些弯路。
大模型推理优化,说白了就三个字:抠细节。
同样的模型,同样的硬件,同样的请求,不同的人能跑出差10倍的速度差距。这不是天赋差距,是你愿不愿意蹲下来,看每个算子的实现、每轮通信的耗时、每个内存块的分配。
我见过有人一上来就问:“有什么万能优化方案?” 没有。你只能先跑一轮profiling,找到自己的瓶颈在哪,再对症下药。
我自己的习惯是:每做一个优化,先写一个实验报告,记录改动内容、指标变化、踩坑记录。三个月下来,光实验报告就攒了80多页。
这篇文章想表达的核心就一句话:别信玄学,别信捷径,老老实实跑数据。
你要真有这耐心,大模型推理优化这事儿,迟早能玩明白。
哦对了,我建了个小圈子,专门讨论大模型推理的各种实操问题。要是有兴趣可以私信我。但话说在前头,我不喜欢那种张嘴就问“这个能不能做”的人。先自己跑一跑,带着问题来找我,我乐意聊。
别指望一步登天,蹲下来把每个小数点抠明白,你就能赢过90%的人。
读者评论 2