Title: 一张全景图!拆解大模型推理性能优化技术的目标 | BestBlogs.dev
URL Source: https://www.bestblogs.dev/article/d15678b267?amp%3Butm_medium=feed&%3Butm_campaign=resources&%3Bentry=rss_article_item
Published Time: 2026-08-05 00:00:00
Markdown Content: FlashAttention、PagedAttention、Radix Cache、FP8、AWQ、MLA、continuous batching、CUDA Graph、投机解码……这些看起来彼此无关。其实优化的目标就只有两个:单条请求更快 ——延迟;同一批硬件单位时间吐出更多 token ——吞吐。
大模型推理优化的技术很多,但不建议从 FlashAttention、量化、PagedAttention 这些名字开始背。更有效的办法,是先看一条请求究竟慢在哪里。
在 H100 上跑 batch=1 的解码,GPU 算力利用率不到 1%。不是配置错了:这块卡每从显存搬 1 个字节,要做约 300 次浮点运算,才对得起它的算力;而解码每搬 1 个字节,只做约 1 次。推理优化的大部分技术,都是在处理这个 300 比 1 的失衡——只是它们藏在一张让人眼花的名词表后面。
FlashAttention、PagedAttention、Radix Cache、FP8、AWQ、MLA、continuous batching、CUDA Graph、投机解码……每个名字背后都是一篇论文、一套工程。我们一个个啃,啃完还是没有全局感,因为它们看起来彼此无关。
其实优化的目标只有两个:
* • 单条请求更快 ——延迟;
* • 同一批硬件单位时间吐出更多 token ——吞吐。
这两个目标还经常打架:把更多请求合在一批里算,总吞吐上去了,单条请求可能等得更久;投机解码能降低单条延迟,但系统满负载时,多出来的草稿计算反而抢资源。
所以判断一项优化,不能只问“能加速多少”,要问:它解决哪个瓶颈,花掉什么资源,在什么负载下划算?
下面用一套尽量简单的框架,把这些技术放回它们真正解决的问题里。
一、先把 GPU 想成一家后厨
推理系统的瓶颈,和一家后厨能不能忙得过来,是同一类问题:
| 后厨的问题 | 推理系统的问题 | 决定了什么 | | --- | --- | --- | | 灶火不够,菜炒不过来 | GPU 算力不够 | 每一轮的计算时间 | | 食材送得太慢,厨师站着等 | 显存带宽不够,数据搬不过来 | 每一轮的搬运时间 | | 案板和冰箱太小 | 显存容量不够 | 模型装不装得下、能同时接多少单 | | 下一道菜必须等上一道出锅 | 生成必须一个 token 一个 token 来 | 至少要串行跑多少轮 |
灶火和送菜通道决定每一轮多快,案板决定能同时做多少单,出菜顺序决定至少要跑多少轮。四个约束,下面挨个看。
1.1 灶火和送菜:为什么 Decode 时 GPU 总吃不饱
GPU 执行一个计算任务,时间取决于两件事里更慢的那件:
计算时间 = 要做的计算量 ÷ 算力搬运时间 = 要搬的数据量 ÷ 显存带宽单步时间 ≈ max(计算时间, 搬运时间)
计算更慢,叫 compute-bound(受算力限制);搬数据更慢,叫 memory-bound(受带宽限制)。硬件圈把这两种情况画在一张图上,叫 roofline(屋顶线)模型:
!Image 2: Roofline:Prefill 和 Decode 撞的墙不同
Roofline:Prefill 和 Decode 撞的墙不同
H100 的 BF16 算力约 1000 TFLOPS,显存带宽约 3.35 TB/s,相除得到约 300 FLOPs/字节 的分界点:平均每搬 1 字节,要做满约 300 次运算,算力才不闲着。
而 batch=1 的 Decode 很接近矩阵乘向量:每生成一个 token 都要把大量权重读一遍,每个权重只参与很少的计算,平均每字节只有约 1 次运算。1 比 300——这时不是 GPU 不会算,是权重还在路上,计算单元只能等。
顺带一提国内常见的 H20:算力约 148 TFLOPS,带宽却有 4 TB/s,分界点只有约 37——算力弱、带宽强,天生更适合跑 Decode。同一套优化在不同卡上收益不同,根源就在这个分界点。
于是推理的两个阶段,瓶颈完全不同:
| 阶段 | 在做什么 | 常见瓶颈 | 优化重点 | | --- | --- | --- | --- | | Prefill | 一次并行处理整段输入,几千个 token 共享一次权重读取 | 算力 | 少算、低精度计算 | | Decode | 每轮每条请求只出 1 个 token,却要把权重和 KV 搬一遍 | 带宽 | 少搬、合批、减少空隙 |
还有一个贯穿全文的杠杆:batch 。把 N 条 Decode 请求合在一起算,权重只读一遍却服务 N 个 token——一次送来的食材做了 N 份菜,搬运成本被摊薄 N 倍。这是几乎所有吞吐优化的底层原理。但 batch 能开多大,取决于案板。
1.2 案板和冰箱:显存容量不直接等于速度
显存里主要放两样东西:模型权重 (加载后基本固定)和 KV Cache (保存历史 token 在注意力层的中间状态,随并发数和上下文长度增长)。
KV 有多大?以 Qwen3-32B 为例:64 层、8 个 KV 头、每头 128 维,BF16 存储,每个 token 的 KV 是:
2(K 和 V)× 64 层 × 8 头 × 128 维 × 2 字节 ≈ 256 KB/token
一条 128K 上下文的请求,光 KV 就要约 32 GB 。如果不用 GQA、64 个头各存一份,就是 2 MB/token——8 倍。
容量的微妙之处在于:它本身不是时间。显存变大,不会让任何一次矩阵乘变快。但它通过两条路变现成速度:
* •装得下更多并发 → batch 更大 → 吞吐更高;
* •存得下更多历史前缀 → 缓存命中率更高 → 更多 Prefill 可以直接跳过。
所以显存像案板和冰箱:它不负责炒菜,但空间不够,厨师就没法同时开工、也存不下备好的料。带宽的账记在每一轮的耗时上,容量的账记在能同时干多少事上——这是两种不同的资源,很多文章把它们压扁成“优化显存”四个字,账就算不清了。
1.3 出菜顺序:一道接一道的串行依赖
生成第 N 个 token,必须先有第 N-1 个——这是自回归的定义。要 100 个 token,就得顺序跑 100 轮。
前面的计算优化、搬运优化,都只能缩短每一轮的时间,不能把 100 轮变成 50 轮。只有投机解码、多 token 预测这类技术,才直接攻击轮数本身。
三个约束合起来,就是全文最重要的一组关系:
总时间 ≈ 串行轮数 × 每轮时间 ← 出菜顺序每轮时间 ≈ max(计算量 ÷ 有效算力, 搬运量 ÷ 有效带宽) ← 灶火和送菜,哪个慢听哪个其中 有效算力 / 有效带宽 = 硬件峰值 × 利用率约束 权重 + 所有并发请求的 KV ≤ 显存容量 ← 案板
后面的技术看起来五花八门,其实都在改这几项。
二、一条公式,六个动词
要让总时间变小,从上面那组关系看,路只有四条,不重不漏:
| 杠杆 | 动词 | 逻辑 | | --- | --- | --- | | 减少每轮的工作量 | 不算 / 少算 / 少搬 | 工作量有两个维度——要算的和要搬的:不算直接删掉整段工作(计算和搬运一起消失),少算砍计算量,少搬砍搬运量 | | 提高利用率 | 打满 | 硬件明明有能力,但在空转等待 | | 减少串行轮数 | 破串行(少走几轮) | 每轮再快,100 轮就是 100 轮——这条杠杆直接砍轮数 | | 放松容量约束 | 少占 | 不直接省时间,通过 batch 开大和缓存命中间接变现 |
(严格说还有第五条路:提高硬件峰值——换更好的卡,或者加卡。多卡并行 TP/PP/EP 本质上属于这一档,后面在“打满”里细说为什么。)
四条杠杆,拆出六个动词。有两处边界先说清楚,免得较真的读者觉得分类不干净:“不算”可以看成“少算”的极限,但机制完全不同——一个靠复用,一个靠降价,分开才有操作性;
“破串行”的可行性依赖 Decode 阶段闲置的算力,和“打满”用的是同一个资源池,后面会看到它们的关系。动词是工程上好用的近似,到具体技术,还得用矩阵记账——第五节见。
不算 → 少算 → 少搬 → 少占 → 打满 → 破串行
这个顺序是优先级,不是实施顺序:越靠前的杠杆越便宜——省掉的计算,永远比优化过的计算划算。
动词一:不算——复用已有的结果
最便宜的计算,是不再重复的计算。 KV Cache:同一条请求内复用。 不存缓存的话,生成第 t 个 token 要把前 t 个 token 全部重新前向一遍——它们的 K/V 没存,只能重算。生成 n 个 token,总工作量从 1 累加到 n,是 O(n²) 规模;存下 K/V 后,每轮只算最新那个 token,降到 O(n)。
有一部分省不掉:注意力打分每轮仍要读取 全部历史 KV,序列越长读得越多。所以 KV Cache 没有让历史消失,而是把“反复重算历史”变成了“保存并读取历史”——用显存容量和带宽,换掉大得多的重复计算。这是整个领域的第一笔交易,非常划算,但绝不免费:后面几乎所有 KV 优化,都在收拾这笔交易带来的新问题。 Radix / Prefix Cache:跨请求复用。 很多请求的开头是一样的——系统提示词、few-shot 例子、多轮对话的历史。SGLang 用一棵基数树索引这些公共前缀,新请求命中就直接复用算好的 KV,跳过对应的 Prefill。 HiCache:把缓存池扩到 CPU 和硬盘。 前缀命中率的天花板是缓存池大小,而 GPU 显存里缓存要和运行中的请求抢地盘。HiCache 把缓存分层:GPU 放热的,CPU 内存放温的,SSD 放冷的,命中时搬回来。
它表面上在“多搬”(KV 在 CPU 和 GPU 之间来回倒),凭什么归“不算”?算笔账:Qwen3-32B 重算一段 4K token 的 prompt,约 2 × 32B × 4096 ≈ 2.6×10¹⁴ 次浮点运算,H100 上也要百毫秒到秒级;而这段 KV 总共 4096 × 256KB ≈ 1 GB,从 CPU 内存搬回显存是几十毫秒的事。差一到两个数量级——花搬运,买免算,账算得过来。
前提是搬运真的快:一旦被零碎小块传输或 PCIe 争抢拖垮,这笔交易就由赚变亏。所以 HiCache 要盯的不是“命中率”一个数,而是命中在哪一层、搬回花了多久、最终省了多少重算。
> 🍳 熬好的高汤别倒掉,下一锅接着用;灶边放不下就放冷藏库——取回来多花一点功夫,还是比从头熬快得多。
动词二:少算——减少真正要执行的计算
躲不掉的计算,能不能每次更便宜?这一维有个适用条件:只有算力是瓶颈时(Prefill、大 batch),省计算才真正省时间 。系统本来就在等数据的话,砍计算量砍的是本来就闲着的东西。
* •FP8 / W8A8 计算量化:权重和激活都用低精度参与矩阵乘,直接用上吞吐更高的低精度计算单元。它顺带也少搬、少占,但在 Prefill 和大 batch 下,主要收益确实是“同样时间做更多计算”。
* •稀疏注意力:不让每个 token 都看全部历史,只看局部窗口或挑出来的重要位置,把注意力计算从 O(n²) 砍下来。GLM-5.2 的 IndexShare 更进一步:多层稀疏注意力共用一份“该看哪些 token”的筛选结果,连筛选本身的重复计算也省了——这类设计直接面向 1M 上下文的成本。
* •MoE:结构化的稀疏——模型有很多专家,每个 token 只激活几个。Qwen3-30B-A3B 总参数 30B、每 token 只算约 3B;DeepSeek-V3 是 671B 总参数、37B 激活。模型容量很大,每个 token 的计算量却不用等比例涨。
MoE 还能说明一个常见误区:计算少,不等于部署简单。所有专家的权重都得放在显存里(少算但巨占);专家分布在多卡时 token 要跨卡发送;路由不均匀时,热门专家所在的卡就是短板。省下的计算,以容量、通信和负载均衡问题的形式还了回来。
> 🍳 简化配方:少放几味不影响味道的料,备料和翻炒都省——但料的种类还得备齐,占的还是冰箱。
动词三:少搬——减少每轮读写的数据
Decode 的主战场。带宽是瓶颈时,真正救命的是让每一轮要搬的字节变少。每轮 Decode 搬两样:权重,和这批请求的所有 KV。 少搬权重——Weight-only 量化(AWQ / GPTQ):只把权重压到 4bit,算的时候再解压回高精度。解压是额外计算 ——它比不量化算得更多,却在 Decode 下反而更快。
这个反直觉的事实很重要:有时多算一点反而快,因为瓶颈是搬数据 。
顺带把量化的账理清:W8A8 主要省计算,weight-only 主要省搬运——都叫量化,是两笔不同的交易,适用场景也不同。 少搬 KV:KV 量化(BF16 压成 FP8/INT8,每轮读一半字节);GQA/MLA 让 KV 从根上变小——主账记在下一个动词,这里先挂个号。 少搬中间结果:
* •FlashAttention:朴素注意力会产生一个很大的中间矩阵,写进显存再读回来。FlashAttention 用分块计算 + 边算边归一化,让中间结果留在 GPU 片上的高速缓存里,不落显存。数学结果一样,数据走的路短了一个量级。它对 Prefill 和长序列尤其重要——那时中间矩阵才够大。
* •算子融合(torch.compile / TensorRT):原来一串小算子各自读写一次显存,融合成一个大算子后,数据进来一次、连算几步、出去一次。(kernel 这个词,指的就是在 GPU 上执行的一段计算程序。)
> 🍳 别在冰箱和灶台之间来回跑:一次拿齐,一气呵成,半成品别端来端去。
动词四:少占——减少显存浪费和状态体积
容量不是时间,但它是 batch 和命中率的弹药。这一维的收益,都走 1.2 节那两条变现路径。 PagedAttention:最容易被归错位置的技术——名字带 Attention,常被当成计算优化,其实它一个计算都不省、一个必要的字节都不少搬,治的是浪费 。
早期系统按最大长度给每个请求预留整块显存,短请求留下大量空洞,实际利用率只有 20%~40%;PagedAttention 借操作系统内存分页的思路,把 KV 切成固定大小的块按需分配,浪费降到 4% 以下。同样的显存,并发翻几倍——再由“打满”把并发变成吞吐。 MQA → GQA → MLA:注意力结构对 KV 体积的三代压缩。
MQA 让所有查询头共享一份 KV(最省但伤效果);GQA 分组共享(Qwen3-32B 就是 64 个查询头共享 8 个 KV 头,8 倍压缩);
MLA(DeepSeek)把所有头的 KV 压成一个小的低维向量,对比不压缩的 MHA 能省约 93%(DeepSeek-V2 论文数字)。它改的是状态的体积 ,收益自动兵分两路:每轮读 KV 更少(少搬),同样显存装更多请求(帮打满)。
一处结构改动,多处受益——这也是新模型清一色往这个方向走的原因。 KV 驱逐 / 滑动窗口:直接丢掉远处的 KV,用“看不到完整历史”的风险换容量,是这一维里最激进的一档。 HiCache 的容量面:KV 下沉的同时,也在给 GPU 腾地方——它同时服务“不算”(主)和“少占”(副)。
> 🍳 小份装盒、真空压缩:冰箱还是那个冰箱,能备的桌数翻倍。
动词五:打满——减少等待和空转
前四个动词决定“要算多少、搬多少、存多少”;这一维解决:干这些活的时候,硬件有没有闲着。空转有好几种,来源不同,解法也不同: batch 里有空位 → Continuous Batching:静态批要等最慢的请求跑完,先结束的白占位置。连续批处理按 token 轮动态进出:谁完了立刻让位,新请求马上补进。batch 常满,权重每读一遍都被摊得更薄。 Prefill 和 Decode 互相堵 → Chunked Prefill / PD 分离:一个撞算力、一个撞带宽,混在一起互相拖累——突然插进的长 Prefill 让所有 Decode 卡一大顿。
单机的解法是把长 prompt 切块、和 Decode 穿插着跑;集群的解法是干脆拆开,Prefill 和 Decode 各用各的实例、各配各的硬件。代价是 KV 要在两边之间传输。 多卡互相等 → TP / PP / EP 的工程部分:这里要说清楚一件事——单卡装不下、单卡算得慢,都是“采用并行”的原因,但那本质是加资源(把算力和容量撑大),不是打满 。
真正属于打满的,是加了卡之后让每张卡都有活干:TP 要把卡间通信藏进计算里,PP 要减少流水线的空泡,EP 要让专家负载均匀。加了卡而没做好这些,利用率反而暴跌——并行的“买卡”和“用好卡”是两件事,打满管的是后者。 GPU 等 CPU 派活 → CUDA Graph:GPU 上每段计算都要 CPU 发一条启动指令,一轮 Decode 要发几百上千条;小 batch 下 CPU 发指令的速度追不上 GPU 干活的速度,GPU 反过来等 CPU。
CUDA Graph 把整轮固定的计算序列录制一次,之后一句“回放”替代上千次指挥。代价是灵活性:输入形状固定,要按不同 batch 大小预录多张图。 等下一轮调度 → Overlap Scheduler (SGLang 的招牌):GPU 算当前这批时,CPU 同步处理上一轮结果、准备下一批的数据,把调度时间藏进 GPU 的执行时间里。
它和 CUDA Graph 治的是两种不同的等:一个治指令开销,一个治调度开销。
> 🍳 空出一个灶眼马上补单(batching);红案白案分开排班(PD 分离);固定的菜不用每次口头交代整套步骤(CUDA Graph);炒这一单时,下一单的料已经在切(overlap)。
动词六:破串行——少走几轮
前五个动词都在优化“每一轮多快”,只有这个在攻击“轮数”。名字听起来玄,说白了就是:用额外的工作,换一次确认多个 token,让大模型少串行跑几轮。 投机解码:先用便宜的“草稿”(小模型,或 EAGLE、MTP 这类挂在大模型上的预测头)猜出后面几个 token,再让大模型一次前向并行验证 。
验证方法在数学上有保证:最终的输出分布和逐个生成完全一致。猜对几个,就一次前进几步,典型加速 2~4 倍。
它为什么可行?回到 1.1 节:Decode 受带宽限制,验证 5 个 token 和验证 1 个,权重都只搬一遍,多花的只是本来就闲着的算力。所以破串行和 batching 其实在花同一笔钱:batching 拿闲置算力服务更多请求 ,投机解码拿它赌同一条请求的未来 。
但它不是免费午餐:草稿要占显存、花计算;猜不准时验证全白做;高负载大 batch 下,闲置算力已经被 batching 吃光,投机解码反而和正经请求抢资源,收益缩水甚至为负。所以它是低延迟场景的利器、高吞吐场景的鸡肋——真正决定收益的是接受率:草稿一次猜得再多,大部分在第一个就被拒,也是白搭。 MTP(多 token 预测):把“草稿”直接做进模型——训练时就带上预测未来多个 token 的头。DeepSeek-V3 和 GLM-5.2 都内置了这个能力,GLM-5.2 还专门优化了平均接受长度。这是模型厂在训练时就为推理提速预埋的钩子。
> 🍳 猜熟客下一道要点什么,提前备着;猜对了直接上,猜错了损失一份备料。生意越忙,越没有闲手玩预判。
三、一次请求的一生
把六个动词放回时间线上——一条请求从到达到退场,它们在不同站点轮流上场:
到达 ─▶ ①前缀匹配 ─▶ ②排队进批 ─▶ ③Prefill ─▶ ④写缓存 ─▶ ⑤Decode循环 ─▶ ⑥退场 不算 打满/少占 少算 少占 少搬/打满/破串行 │ ▲ KV 留作前缀 └────────────────────────────────────────────────────────────────┘
* •到达 · 前缀匹配(不算):先查基数树,历史前缀命中就跳过对应的 Prefill;GPU 里没有、CPU/SSD 分层里有的,搬回来接着用。
* •排队 · 进批(打满 + 少占):调度器把它塞进当前 batch;长 prompt 切块和 Decode 混批;KV 按页分配,不留碎片。集群部署下,它可能先被路由到 Prefill 专属实例。
* •Prefill(少算主场):几千 token 并行前向,算力是瓶颈——低精度计算、稀疏注意力、MoE 的收益在这里兑现。
* •写缓存(少占):新产生的 KV 写进分页池;模型是 MLA/GQA 的话这份 KV 天生就小,KV 量化再砍一半。
* •Decode 循环(少搬 + 打满 + 破串行):每轮搬权重、读 KV——量化砍字节,CUDA Graph 消指令开销,overlap 消调度间隙;带草稿的系统一次验证多个 token。一圈一圈,直到生成结束。
* •退场(回到不算):它的 KV 不一定被丢掉——留在缓存树上当前缀,等下一条请求命中,回到第①站。
一次请求的一生
四、另一条轴:每个动词住在系统的哪一层
时间线回答“什么时候发生”,还有一条空间轴:“在哪一层发生”。推理系统从外到内分四层,每层能动的东西不一样:
请求进来 │┌──▼──────────────────────────────────────────┐│ ④ 服务与集群层:请求怎么排,卡和实例怎么协作 ││ Continuous Batching / Chunked Prefill ││ PD 分离 / TP·PP·EP / Overlap Scheduler │├──────────────────────────────────────────────┤│ ③ 缓存与运行时层:哪些状态复用,KV 放在哪 ││ KV Cache / Radix Cache / PagedAttention ││ KV 量化 / HiCache │├──────────────────────────────────────────────┤│ ② 算子执行层:一次前向具体怎么算、怎么搬 ││ FP8·AWQ / FlashAttention / 算子融合 ││ CUDA Graph │├──────────────────────────────────────────────┤│ ① 模型结构层:模型天生要算多少、产生多少状态 ││ GQA·MLA / MoE / 稀疏注意力 / MTP │└──────────────────────────────────────────────┘ │GPU 算力、显存、卡间互联
四层的依赖关系很清楚:结构层决定每个 token 天生要多少计算、多大 KV;算子层决定这些计算在硬件上怎么跑;缓存层管理跑出来的状态;服务层把请求、多卡、多实例组织起来。
最要紧的分界在第①层和其余三层之间:结构层是训练时定死的 。推理工程师拿到模型,MHA 改不成 MLA,没有 MTP 头也不能凭空造——只能“接住”:kernel、缓存布局、调度都支持了,结构的收益才能兑现;接不住,就只是论文里的数字。(量化的校准虽然发生在部署前的离线阶段,但它不改模型结构,归推理侧。)
这个视角最实用的地方是看懂新模型发布。DeepSeek-V3 选 MLA + MoE + MTP,不是三个孤立的技术点:MLA 管搬运和容量,MoE 管计算,MTP 管串行轮数——模型厂在训练时,就把三条杠杆的钩子全预埋了。
GLM-5.2 的稀疏注意力 + IndexShare + 改进 MTP,同样是一组围绕 1M 上下文成本的组合拳。反过来,推理框架的很多迭代(MLA 专用 kernel、MTP 投机调度),本质是在兑现模型厂预埋的支票。
落到一个真实系统:SGLang 的请求链路
四层不是纸上谈兵,拿 SGLang 对一遍(vLLM、TensorRT-LLM 结构类似):
SGLang 请求链路与四层架构
请求从 API 进来,经过分词,到 Scheduler ——前缀匹配、连续批处理、chunked prefill 都在这一站(服务层 + 缓存层的入口);Scheduler 背后是KV 池和缓存体系——分页分配、基数树、HiCache 分层(缓存层);
组好的 batch 交给 Model Runner ——attention 后端选择、量化 kernel、CUDA Graph 回放、投机验证都在这里(算子层);多卡时 TP/PP/EP 的通信组也挂在这一层之下。生成的 token 一路流回客户端。
这张图的价值不在“某个功能在哪个文件”,而在看出一项优化会牵动哪些上下游:MLA 不只需要一个新 attention kernel,还改变 KV 池的布局和调度器能开的 batch 上限;
HiCache 不只是一套存储,还反过来影响调度器“这条请求的 Prefill 值不值得跳过”的决策。跨层的技术(投机解码同时跨结构、算子、调度三层)比单层技术难做稳,也是这个原因。
五、账本:技术 × 动词矩阵
时间线和分层管理解,矩阵管查账。把每个技术塞进单独一格,是分类最容易撒的谎——真实情况是:好技术往往一石多鸟,而且几乎都有代价 :
> ● 主要收益 ○ 次要收益 ✗ 付出的代价 > > 行序按主收益动词从“不算”到“破串行”排(即正文出现顺序)。“决策层”一列训练/推理混排是有意的——同一个动词,往往同时有训练时的结构实现和推理时的系统实现:破串行 = MTP(训练)+ 投机解码(推理),少搬少占 = MLA(训练)+ KV 量化(推理)。
| 技术 | 不算 | 少算 | 少搬 | 少占 | 打满 | 破串行 | 决策层 | | --- | --- | --- | --- | --- | --- | --- | --- | | KV Cache | ● | | ✗ 每轮读历史 | ✗ 占容量 | | | 推理 | | Radix / Prefix Cache | ● | | | ✗ 占容量 | | | 推理 | | HiCache 分层缓存 | ● | | ✗ 搬运 KV | ○ 给 GPU 腾地方 | | | 推理 | | PagedAttention | | | | ● | ○ batch↑ | | 推理 | | W8A8 / FP8 计算量化 | | ● | ○ | ○ | | | 推理 | | AWQ / GPTQ(仅权重) | | ✗ 解压多算 | ● | ● | | | 推理 | | KV 量化 | | | ● | ● | | | 推理 | | MQA / GQA / MLA | | | ● | ● | ○ batch↑ | | 训练 | | 稀疏注意力 / IndexShare | | ● | ○ | ○ | | | 训练 | | MoE | | ● | | ✗ 全部专家占显存 | | | 训练 | | FlashAttention | | | ● | ○ 中间矩阵不落显存 | | | 推理 | | 算子融合 / compile | | | ● | | ○ | | 推理 | | Continuous Batching | | | | | ● | | 推理 | | Chunked Prefill | | | | | ● | | 推理 | | 多卡并行(TP/PP/EP) | | | | ○ 权重分摊 | ● | | 推理 | | PD 分离 | | | ✗ 两边传 KV | | ● | | 推理 | | CUDA Graph | | | | | ● | | 推理 | | Overlap Scheduler | | | | | ● | | 推理 | | 投机解码 / EAGLE | | ✗ 草稿+验证多算 | | ✗ 草稿占显存 | ○ 用闲置算力 | ● | 推理 | | MTP | | | | | | ● | 训练 |
(多卡并行的“加卡”部分属于把峰值和容量撑大,不进这张表;表里记的是它的工程部分——让多张卡不互相等。)
有三个格子特别有意思:
* • KV Cache 自己就带两个 ✗ ——整个领域的第一个技术,就已经是“花容量和带宽买免算”的交易。容量问题不是后来才有的,是地基自带的。
* • AWQ 的 ✗ 在“少算”列 ——靠多算换少搬还净赚,是“Decode 慢在搬不在算”最硬的实证。
* • 投机解码一行三个 ✗ 一个 ● ——收益最戏剧化的技术,代价也最多,所以最挑场景。
六、看到新技术,问四个问题
以后再冒出新名词,按这个顺序过一遍:
1、它针对的瓶颈是什么?算力、带宽、容量、空转,还是串行轮数?
2、它省的是什么?对应六个动词的哪一格?
3、它花的是什么?没有白拿的优化:HiCache 花搬运买免算,投机解码花算力显存买轮数,量化花精度,PD 分离花卡间传输,CUDA Graph 花灵活性。找不到代价,多半是我们还没看懂它。
4、它服务哪个目标、什么场景?延迟还是吞吐?batch 多大、上下文多长、负载多高?投机解码低负载是利器、满负载是鸡肋;chunked prefill 和 PD 分离是同一个问题在单机和集群的两个答案。没有普适赢家,只有场景赢家。
四问过完,一项技术的价值边界基本就清楚了。
结语
推理优化不是一张要背下来的名词表,而是一组资源交换:
* • 用显存换掉重复计算——KV Cache;
* • 用一点解压计算换少搬一半权重——weight-only 量化;
* • 用更复杂的内存管理换显存利用率——PagedAttention;
* • 用卡间传输换两个阶段各自安稳——PD 分离;
* • 用草稿计算和显存换更少的串行轮数——投机解码。
国产模型已经给出了很好的现实注脚:Qwen3 用 GQA 和 MoE 控制 KV 和激活计算,DeepSeek-V3 用 MLA + MoE + MTP 同时按下搬运、计算、轮数三个按钮,GLM-5.2 又把稀疏注意力、IndexShare 和改进的 MTP 推到 1M 上下文场景。
技术会一直翻新,但灶火、送菜、案板、出菜顺序这四个约束不会变——那是硬件物理和自回归数学决定的。先找到瓶颈,再算清交易,新名词通常都能放回熟悉的位置。
如果你最近也遇到了新的推理优化技术(论文、框架 feature、新模型的结构选择都行),欢迎在评论区聊聊,一起用四问过一遍。更欢迎指出归不进这六个动词的例子 ——那说明这套框架还有缺的格子,也是我最想知道的部分。
参考资料
[1] Qwen3 官方介绍 · Qwen3-32B 配置: https://huggingface.co/Qwen/Qwen3-32B/blob/main/config.json
[2] DeepSeek-V3 技术报告: https://github.com/deepseek-ai/DeepSeek-V3
[3] GLM-5.2 模型说明: https://huggingface.co/zai-org/GLM-5.2
[4] SGLang 文档 · vLLM PagedAttention 论文: https://arxiv.org/abs/2309.06180
[5] Roofline 模型(Williams et al., 2009): https://dl.acm.org/doi/10.1145/1498765.1498785
加入青稞AI技术交流群,不仅能与来自MIT、港中文、CMU、UCLA、斯坦福、清华、阿里、腾讯等名校名企AI研究员/开发者一起进行技术交流,同时还有一线青年AI研究员/开发者的Talk分享、青稞Tea、论文精读、招聘内推、国内外硕/博申请、大模型技术报告解读等。备注:姓名+学校/公司+方向,暗号"AI"优先审核通过!