Acceleration notes
生成模型加速原理
从采样步数、注意力内核、KV cache、量化、缓存、批处理和分布式训练理解现代生成模型如何提速。
先读这个:生成为什么慢?
生成模型慢,通常不是因为“模型大”这一个原因,而是因为它同时受到四类约束:算得多、搬得多、等得久、排队乱。 LLM 的 prefill 更像一次性读完整个 prompt,decode 更像一个字一个字串行吐出; diffusion 则像反复去噪几十步,每一步都要跑一次大网络。
所以,加速不是一个动作,而是一组针对不同瓶颈的手术:FlashAttention 减少 attention 中间矩阵的 HBM 往返; KV cache 避免重复计算历史;continuous batching 让 GPU 不等短请求;量化减少权重和 KV 的字节数; speculative decoding 用小模型猜、大模型验;diffusion sampler 则直接减少 denoising 步数。
阅读路径:从直觉到诊断
| 路径 | 先建立的直觉 | 重点章节 | 读完应该能做什么 |
|---|---|---|---|
| 建立直觉 | 慢不是一个原因:LLM 串行吐 token,diffusion 多步去噪,训练卡在显存和通信。 | 开头、Roofline、KV cache、Diffusion sampler、常见误解 | 能分清 TTFT、TPOT、NFE、显存峰值这些词。 |
| 定位瓶颈 | 先测瓶颈,再选最小干预。 | Roofline、Serving、Quantization、Training、决策地图 | 能设计 profiling checklist,并判断该上哪个优化。 |
| 检查边界 | 每种加速是否 exact、是否改变分布、是否只是调度优化。 | 加速分类、Speculative Decoding、Quantization、MoE、benchmark checklist | 能检查算法边界、质量回归和 benchmark illusion。 |
总体问题:慢在哪里,才能快在哪里
生成模型加速不是单纯压缩模型。核心问题是:如何用更少的计算、更少的内存、更少的数据搬运、更少的同步等待,近似或等价地得到同一个生成分布。
一句话直觉
参数多只是表象;很多真实瓶颈来自串行生成、HBM 数据搬运、KV cache 膨胀、请求长度不规则,以及 GPU 调度空泡。
统一代价模型
单步延迟的下界可以拆成计算、带宽、通信、同步和调度几项:
不同加速技术本质上是在压缩某一项:NFE、token 数、precision bytes、KV cache、HBM traffic、batch 空泡或通信等待。
可视化:瓶颈地图
调节 workload 类型,观察主要瓶颈如何从 compute 转移到 memory、serial depth 或 scheduling。
decode 常被 KV cache 带宽、串行 token 和 batch 利用率限制。
伪代码:统一延迟估计
# Training profiler view
for step in training:
flops = estimate_forward_backward_flops(model, batch)
bytes_moved = estimate_weight_activation_optimizer_io(model, batch)
comm = estimate_collectives(parallel_plan)
latency = max(flops / peak_flops, bytes_moved / bandwidth) + comm
log_by_component(step, latency)
# If memory-bound: try FlashAttention, fused kernels, quantization, cache.
# If compute-bound: try tensor cores, lower precision, model/parallel changes.
加速到底改变了什么
同样叫“加速”,有些只是 exact 实现更高效,有些改变数值精度,有些减少计算,有些改变请求调度。先分类,才能判断质量风险。
| 类别 | 代表技术 | 改变什么 | 通常不改变什么 | 主要风险 |
|---|---|---|---|---|
| Exact implementation | FlashAttention, kernel fusion, compiled runtime | 内存访问、kernel launch、layout | 数学目标和输出分布 | kernel 条件、数值边界、动态 shape |
| Distribution-preserving | 严格 speculative decoding | 目标模型 forward 调用次数 | 验证/接受/残差采样正确时的目标分布 | 工程变体可能近似化,draft 成本过高会变慢 |
| Approximate numerics | FP8, INT8, INT4, GPTQ, AWQ, SmoothQuant, KV quant | 权重、激活或 KV 的表示字节数 | 计算图结构 | outlier、长上下文、硬件 kernel 不匹配 |
| Approximate computation | token pruning/merging, diffusion feature cache | 参与计算的 token、block 或 denoising 子路径 | 高层任务目标 | 细节丢失、事实检索下降、视频运动发粘 |
| Scheduling / serving | continuous batching, prefix cache, request scheduling | GPU 空泡、KV 分配、请求排队 | 单个模型 forward 的数学 | 长尾延迟、公平性、多租户隔离 |
| Architecture / training change | MoE, distillation, LoRA, QLoRA | 训练目标、激活路径或可训练参数 | 部署约束需要重新评估 | 质量回归、router imbalance、adapter 调度 |
Roofline 视角:算力瓶颈还是带宽瓶颈
GPU 很快,但把数据从显存搬到计算单元也很慢。很多快算法不是少算了,而是少搬了。
数学对象 / 代价模型
定义 arithmetic intensity:
当 \(I\) 很低时,模型更像 memory-bound;当 \(I\) 很高时,模型更可能被 compute throughput 限制。
Roofline Calculator
输入每步 FLOPs、数据搬运和硬件峰值,估计 compute time、memory time 与瓶颈类型。
这个计算器是教学近似。batch 使用 \(\sqrt{B}\) 的简化缩放,只帮助建立直觉,不代表生产 latency 模型。
计算中:将显示教学估计的 latency lower bound、瓶颈类型和 arithmetic intensity。
优点、风险、诊断信号
先判断瓶颈,避免盲目追逐 FLOPs。
实际 runtime 还有 kernel launch、shape、cache miss、通信和调度成本。
TFLOP/s、HBM bandwidth、kernel utilization、prefill/decode 分开测。
memory-bound 优先看 IO-aware kernel、量化、cache;compute-bound 再看并行和低精度 tensor core。
如何证明真的快了:Benchmark Checklist
| 场景 | 必须分开看的指标 | 常见假快 |
|---|---|---|
| LLM prefill | TTFT、prompt tokens/s、prefill kernel time、batch shape | 只报总 tokens/s,把 decode 和 prefill 混在一起。 |
| LLM decode | TPOT、decode tokens/s、KV bandwidth、active batch、P50/P95/P99 | 短上下文 benchmark 很快,长上下文或高并发下 KV 爆掉。 |
| Quantization | 显存、prefill/decode latency、困惑度、任务准确率、long-context 指标 | 模型文件变小,但 dequant 未融合,端到端 latency 没降。 |
| Diffusion image | NFE、每步 denoiser time、FID/CLIP score、人审偏差、失败 prompt | 只展示精选图,不统计少步采样的坏样本率。 |
| Video generation | 帧数、分辨率、FVD、motion consistency、VRAM peak | 静态画面看起来好,但运动细节被 cache 抹平。 |
| Training | samples/s、MFU、step time breakdown、显存峰值、通信占比、data wait | 只测单步 microbatch,忽略 optimizer、checkpoint、eval 和 dataloader。 |
Attention Kernel:FlashAttention 的原理
FlashAttention 仍然计算 exact attention,但用分块和在线 softmax 避免把完整 \(T\times T\) score matrix 写回 HBM。
一句话直觉
标准 attention 慢,不只是 \(O(T^2)\);更关键是巨大中间矩阵的显存读写。FlashAttention 尽量让中间状态停留在 SRAM / shared memory。
数学对象 / 在线 softmax
通过递推维护每行最大值和分母,就不需要显式保存完整 attention matrix。
Attention Memory Visualizer
比较 standard attention 与 FlashAttention 在 score matrix materialization 和 HBM traffic 上的差异。
计算中:将显示 attention matrix 大小、估计 HBM traffic 和是否 materialize。
伪代码:Blocked Exact Attention
# Exact blocked attention
for q_block in blocks(Q):
running_max = -inf
running_sum = 0
output = 0
for k_block, v_block in blocks(K, V):
scores = q_block @ k_block.T / sqrt(d)
block_probs = exp(scores - row_max(scores))
output, running_sum = online_softmax_update(output, running_sum, block_probs, v_block)
write(output / running_sum)
# Same attention result, less HBM traffic.
风险与诊断
- 不同 kernel 对 mask、dropout、head dim、causal attention 和硬件代际支持不同。
- 低精度 attention 要做 numerical parity test,尤其是长上下文和高温采样。
- prefill 与 decode 要分开 benchmark;decode 往往还需要 KV cache 与 serving 优化。
KV Cache:从重新计算到记忆历史
自回归模型每生成一个 token 都要看历史。KV cache 把每层历史 key/value 存起来,避免每步重复计算整段上下文。
KV cache 内存公式
设 batch \(B\)、层数 \(L\)、上下文长度 \(T\)、KV heads \(H_{kv}\)、head dim \(D\)、每元素字节 \(b\),则:
MQA 令 \(H_{kv}=1\),GQA 令 \(1<H_{kv}<H_q\),因此 KV cache 可线性下降。
直觉
LLM 生成第 1001 个 token 时,前 1000 个 token 的 key/value 不该每次重算。KV cache 就是把历史注意力索引记下来。
数量级
若 \(B=16,L=32,T=8192,H_{kv}=8,D=128,b=2\),KV cache 约 \(16\) GiB;若用 MQA 把 \(H_{kv}\) 降到 1,约降到 \(2\) GiB。
机制细节
\(M_{KV}=2\times B\times L\times T\times H_{kv}\times D\times bytes\)。decode 阶段很多时候不是 matmul 算不动,而是每步读 KV 的带宽和布局跟不上。
KV Cache Memory Calculator
比较 MHA、GQA 和 MQA 在同一 batch/context 下的 KV 显存占用。
计算中:将显示 GQA cache、MHA 对比和节省比例。
伪代码:KV Cache Decode Loop
def decode_one_token(model, token_t, kv_cache):
hidden = embed(token_t)
for layer in model.layers:
q_t, k_t, v_t = layer.project_qkv(hidden)
kv_cache[layer].append(k_t, v_t)
hidden = attention(q_t, kv_cache[layer].K, kv_cache[layer].V)
hidden = layer.mlp(layer.norm(hidden))
return sample(model.lm_head(hidden)), kv_cache
伪代码:Paged KV Allocation + Prefix Sharing
class PagedKVCache:
def append_kv(request_id, k_t, v_t):
if current_block_full(request_id):
block = free_blocks.pop()
block_table[request_id].append(block)
write_to_last_block(request_id, k_t, v_t)
def share_prefix(new_request, owner, n_blocks):
block_table[new_request] = block_table[owner][:n_blocks]
increase_ref_count(block_table[new_request])
PagedAttention 与 Prefix Cache
把 KV cache 切成固定 block,用 block table 映射逻辑序列和物理显存,减少碎片。
多个请求共享 system prompt、few-shot 或文档前缀时,只 prefill 一次并复用 KV。
prefix 命中率低、block 太粗或太细、多租户隔离不足都会削弱收益。
KV hit rate、fragmentation、active/free blocks、tokens/sec、TTFT 与 TPOT。
Serving & Continuous Batching:让 GPU 不等慢请求
静态 batch 会被长请求拖住;continuous batching 允许新请求在旧请求 decode 过程中动态加入,填补 GPU 空泡。
一句话直觉
普通 batching 像等整桌人都吃完再换桌;continuous batching 是谁吃完谁走,新请求立刻补位。
Continuous Batching Timeline
对比静态 batch 和 continuous batch 的空白 slot、平均 latency 与 GPU utilization。
计算中:将显示 continuous batching utilization 与 static batch utilization。
伪代码:Serving Scheduler
def continuous_batching_loop(engine):
active = []
while True:
while waiting and engine.has_capacity():
req = waiting.pop()
req.kv_cache = engine.prefill(req.prompt)
active.append(req)
next_tokens = engine.decode_step([r.last_token for r in active])
for req, token in zip(active, next_tokens):
req.append(token)
if req.done:
engine.free(req.kv_cache)
边界与诊断
GPU slot 空泡、KV 分配碎片、长短请求混合造成的队列等待。
不改变模型本身的概率分布;它改变的是请求进入 prefill/decode 的排程。
prefix 命中率低、长尾请求过多、调度过度追求吞吐时,P99 latency 可能变差。
queue time、TTFT、TPOT、active tokens、KV block fragmentation、per-tenant fairness。
Quantization:用更少 bit 表示权重、激活和 KV
量化不是随便截断 float。好的量化要回答 scale 怎么选、outlier 怎么处理、误差对输出是否敏感、硬件 kernel 是否真正加速。
基本公式
SmoothQuant 用 \(Y=XW=(XS)(S^{-1}W)\) 把 activation outlier 的难度迁移给 weight;GPTQ 用近似二阶信息补偿逐列量化误差;AWQ 用 activation-aware scaling 保护 salient channels。
| 方法 | 主要对象 | 核心直觉 | 收益 | 失败边界 |
|---|---|---|---|---|
| GPTQ | 权重 PTQ | 用近似 Hessian 顺序补偿量化误差。 | 4-bit 权重压缩强,适合离线量化。 | 校准集不匹配时误差会集中到敏感层。 |
| AWQ | 权重 PTQ | activation-aware 地保护 salient channels。 | 常在 instruction/chat 模型上更稳。 | scale 保护过多会削弱压缩和 kernel 友好性。 |
| SmoothQuant | 权重 + 激活 INT8 | 把 activation outlier 平滑迁移到 weight。 | 更利于 INT8 GEMM 的系统部署。 | 需要真实校准数据;极端 outlier 仍可能破坏质量。 |
| KV quant | decode KV cache | 降低每步读取历史 KV 的字节数。 | 长上下文和高并发 decode 更省显存/带宽。 | retrieval、代码、数学和精确复制任务更敏感。 |
边界句:量化通常减少 storage 和 memory bandwidth,但不保证端到端 latency 一定下降;是否变快取决于真实瓶颈、kernel、batch shape 和 dequant 是否融合。
Quantization Error Lab
调节 bit 数、scale 类型、outlier 强度和方法,观察重构误差与动态范围浪费。
计算中:将显示 relative error、量化 levels、scale type 和方法。
伪代码:PTQ Calibration + Quantized Linear
def post_training_quantization(model, calibration_loader, method):
stats = collect_activation_stats(model, calibration_loader)
for layer in model.layers:
if method == "smoothquant":
scale = smooth_activation_outliers(stats[layer], layer.weight)
elif method == "awq":
scale = protect_salient_channels(stats[layer], layer.weight)
elif method == "gptq":
scale = second_order_error_compensation(stats[layer], layer.weight)
layer.weight = quantize_weight(layer.weight, scale)
return export_quantized_model(model)
风险与诊断
- 权重量化通常减显存和权重带宽,但不保证端到端 latency 更低。
- KV quant 会影响 long-context retrieval;数学、代码和精确复制任务更敏感。
- 诊断要分开看 perplexity、exact match、pass@k、long-context accuracy、prefill latency 和 decode latency。
Speculative Decoding:小模型草稿,大模型验收
小模型先猜多个 token,目标模型一次性验证,减少大模型串行 forward 次数;正确的 rejection sampling 可以保持目标分布。
接受概率
目标模型 \(p\),draft 模型 \(q\)。候选 token \(\tilde{x}\) 的接受概率为:
被拒绝时从残差分布采样,因此最终输出仍来自目标模型 \(p\)。
严格版本只有在 verify、accept 和 residual sampling 都正确实现时,才保持 target distribution;很多工程变体为了吞吐会做近似,需要单独标注质量边界。
Speculative Acceptance Simulator
调节 draft quality、proposal length、draft cost 和 temperature,估计接受长度与 speedup。
计算中:将显示教学估计 accepted tokens、target forward 摊销和 speedup。
伪代码:Draft / Verify Loop
def speculative_decode(target, draft, prompt, K):
tokens = list(prompt)
while not done(tokens):
proposal, q = draft.propose(tokens, K)
p = target.verify(tokens, proposal)
for i, y in enumerate(proposal):
if uniform() < min(1, p[i][y] / q[i][y]):
tokens.append(y)
else:
residual = normalize_positive_part(p[i] - q[i])
tokens.append(sample(residual))
break
return tokens
边界与诊断
decode 的串行 target forward 次数。
严格算法在接受/拒绝/残差采样正确时不改变目标模型分布。
draft cost 高、温度高、proposal 过长或 verify overhead 高时,speedup 可能低于 1。
accepted tokens per target call、draft/target latency ratio、rejection position、质量 parity。
Diffusion / Flow 采样器:从一阶小步到高阶大步
快速 sampler 的目标是不重新训练模型,也尽量用更少 NFE 解出相似的反向轨迹。
DDIM 与 ODE solver 视角
DPM-Solver、DPM-Solver++、UniPC、DEIS 等方法利用 diffusion ODE 的结构,以少量 denoiser evaluations 得到更高阶近似。
| 路线 | 减少什么 | 代表技术 | 直觉 | 风险 |
|---|---|---|---|---|
| Sampler / solver | NFE | DDIM, DPM-Solver, DPM-Solver++, UniPC | 用更好的数值积分少走几步。 | 少步、强 CFG、高频细节下容易偏。 |
| Distillation | 学生模型需要的 denoising 步数 | progressive distillation, consistency distillation | 把多步老师压进少步学生。 | 训练成本高,分布覆盖和 prompt 鲁棒性要重测。 |
| Feature cache | 相邻 step 的重复 block 计算 | DeepCache, DiT cache, video cache | 相邻去噪状态相似,部分中间特征可复用。 | 运动变粘、细节漂移、cache policy 依赖模型。 |
| Token reduction | attention / MLP 中参与计算的 patch/token | ToMe-like merge, pruning, window attention | 冗余 patch 可以合并或跳过。 | 文字、手部、细节纹理和长程依赖更敏感。 |
NFE vs Quality Simulator
比较 DDPM、DDIM、DPM-Solver 和 UniPC 在不同 NFE、guidance scale 与 solver order 下的速度和误差趋势。
计算中:将显示教学估计 latency、quality-risk score 和 CFG 风险。
伪代码:Fast Diffusion Scheduler Loop
def fast_diffusion_sample(model, scheduler, condition, num_steps):
x = randn(latent_shape)
history = []
for t in scheduler.select_timesteps(num_steps):
pred = model(x, t, condition)
x = scheduler.step(x, t, pred, history)
history.append((t, pred))
return decode_latent(x)
# Fewer denoiser evaluations, same base model.
风险与诊断
- 少步采样容易丢细节;高阶 solver 在强 CFG 下可能过冲。
- 不同模型的 prediction type 不同,epsilon / x0 / v 的 scheduler 公式不能混用。
- 视频生成要同时看 quality、FVD、motion score 和 temporal consistency。
Diffusion / DiT / Video Cache:复用跨时间步特征
相邻 denoising step 的 latent 与中间特征常有冗余。Cache 方法把变化不大的部分复用起来,少跑一部分网络。
缓存成立的近似
U-Net 可高频更新低层、低频更新高层;DiT 可按 block 与 denoising stage 动态刷新;视频还要避免画面发粘和 subtle motion 丢失。
Diffusion Cache Timeline
横轴是 denoising step,纵轴是 network block,颜色表示 compute、reuse 或 forced refresh。
计算中:将显示教学估计 speedup、cache hit rate 和 quality risk。
伪代码:Diffusion Feature Cache Loop
def cached_diffusion_sample(model, scheduler, condition, policy):
x = randn(latent_shape)
cache = {}
for step, t in enumerate(scheduler.timesteps()):
h = model.input_embed(x, t, condition)
for block_id, block in enumerate(model.blocks):
key = (block_id, policy.group(step, t))
if policy.can_reuse(block_id, step, cache.get(key)):
h = cache[key]
else:
h = block(h, t, condition)
cache[key] = detach(h)
x = scheduler.step(x, t, model.output_head(h))
return decode_latent(x)
边界与诊断
单步 denoiser 内部重复计算,尤其是 DiT/video 的 attention 和 block stack。
不减少 NFE;它减少每个 denoising step 里实际执行的 block。
大运动、细粒度纹理、文字和快速时序变化会放大 cache 误差。
cache hit rate、forced refresh ratio、FVD、motion consistency、人审坏样本率。
Token Reduction:少处理一些 token / patch
图像、视频和长文本里有大量冗余 token。Token reduction 通过合并、剪枝或延后计算降低 attention 和 MLP 负担。
Token merging 与 pruning
Patch Merge Lab
调节 merge ratio,观察哪些图像 patch 被合并,以及 attention token count 如何下降。
计算中:将显示 attention cost reduction、token count 和模式。
风险与诊断
- 训练时启用可让模型适应 token reduction;推理 plug-and-play 质量风险更高。
- 文本 LLM 删除历史 token 会破坏事实检索和长程依赖,比视觉 patch merging 更危险。
- 诊断应同时看速度、细节丢失、文本一致性和 long-context retrieval。
Training Acceleration:让训练放进显存、跑满集群
训练加速要同时处理参数、梯度、optimizer state、activation、temporary buffers 与通信。多卡如果通信设计不好,可能只是放大等待。
训练显存组成与 ZeRO / FSDP
Activation checkpointing 不是“更少 IO”的魔法,而是用更多 forward FLOPs 换更少 activation 保存和更低显存峰值。ZeRO/FSDP 把 optimizer states、gradients 和 parameters 分片;tensor/pipeline/sequence/expert parallel 分别切单层矩阵、层、序列和 expert。
这个公式是理想化 ZeRO-3 / FSDP full sharding 心智模型。DDP 会在每张卡复制参数、梯度和 optimizer states;ZeRO-1/2/3 分别切 optimizer、gradient、parameter 的范围不同,真实显存还包括 activation、临时 buffer、通信 bucket 和 allocator 碎片。
| 策略 | 切分对象 | 解决什么 | 代价 / 边界 |
|---|---|---|---|
| DDP | 数据 batch | 最直接扩展吞吐。 | 每卡复制完整模型状态,显存不省。 |
| ZeRO-1 | optimizer states | 先省 Adam moments。 | 参数和梯度仍复制。 |
| ZeRO-2 | optimizer states + gradients | 进一步降低训练状态显存。 | 通信和 bucket 调度更复杂。 |
| ZeRO-3 / FSDP | parameters + gradients + optimizer states | 把大模型装进多卡。 | layer 前 all-gather、后 reduce-scatter,通信 overlap 很关键。 |
| TP | 单层矩阵/heads | 切大 matmul。 | 层内 collectives 频繁,跨节点代价高。 |
| PP | 模型层 | 深模型切段。 | pipeline bubble、microbatch 调度和激活传输。 |
| SP | 序列维度 activation | 长序列训练省 activation。 | 需要和 TP/attention kernel 配合。 |
| EP | MoE experts | 切 expert 参数和条件计算。 | all-to-all、router imbalance、capacity overflow。 |
Training Memory Simulator
估计参数、梯度、optimizer state 和 activation 在不同 GPU 数、precision 与 checkpoint 策略下的 per-GPU memory。
计算中:将显示教学估计 per-GPU memory、optimizer 和 checkpoint 状态。
伪代码:Activation Checkpointing
def forward_with_checkpointing(layers, x, interval):
for start in range(0, len(layers), interval):
segment = layers[start:start + interval]
x = checkpoint(run_layers, segment, x)
return x
# Save segment inputs, recompute internals during backward.
# Less activation memory, more forward FLOPs.
伪代码:FSDP / ZeRO-3 Conceptual Step
def fsdp_training_step(model_shards, batch):
hidden = batch.inputs
for layer in model.layers:
W_full = all_gather(layer.weight_shard)
hidden = layer.forward(hidden, W_full)
free(W_full)
loss = compute_loss(hidden, batch.labels)
loss.backward()
for layer in reversed(model.layers):
grad_shard = reduce_scatter(layer.full_grad)
optimizer.update(layer.weight_shard, grad_shard, layer.state_shard)
LoRA / QLoRA 与 Runtime Engine:训练省钱,不等于推理魔法
LoRA 加速的是微调:少训练参数、少存 optimizer state。推理是否更快取决于 adapter 是否合并、kernel 是否融合、动态多 adapter 是否引入额外调度。
LoRA 数学与图编译
Runtime engine 通过 graph capture、operator fusion、layout transformation、shape specialization、kernel autotuning 和 CUDA graph replay 减少临时 tensor、kernel launch 和 Python 调度。
伪代码:LoRA / QLoRA Training and Merge
def lora_finetune(base_model, dataset, rank):
freeze(base_model.parameters())
for linear in target_linear_layers(base_model):
linear.lora_A = Parameter(randn(rank, linear.in_features))
linear.lora_B = Parameter(zeros(linear.out_features, rank))
train_only_lora_parameters(base_model, dataset)
def merge_lora(linear):
linear.weight += (linear.alpha / linear.rank) * (linear.lora_B @ linear.lora_A)
remove_lora_modules(linear)
伪代码:Graph Capture / Kernel Fusion
def compile_for_inference(model, example_inputs):
graph = trace(model, example_inputs)
graph = fuse_ops(graph)
graph = specialize_shapes(graph, example_inputs.shapes)
graph = choose_kernels(graph, hardware="cuda")
graph = capture_cuda_graph(graph)
return build_runtime_engine(graph)
边界与诊断
微调显存和 optimizer state,而不是自动减少 base model 推理 FLOPs。
kernel launch、临时 tensor、layout 转换和 Python 调度。
动态 shape、graph break、多 adapter 热切换和未融合 dequant 会吞掉收益。
graph break count、kernel launch count、CUDA graph hit rate、adapter cache hit rate。
Architecture Acceleration:从 dense 到 conditional compute
MoE、稀疏 attention、动态深度等方法让不同 token 只走部分计算路径,但通信、router 和负载均衡会决定真实速度。
MoE 与 sparse attention
MoE Routing Lab
调节 expert 数、top-k、batch size、router imbalance 和 capacity,观察 active parameters、dropped tokens 与 expert utilization。
计算中:将显示 dropped tokens、active experts 和 all-to-all 风险。
伪代码:MoE Routing Forward
def moe_forward(x, experts, router, top_k=2):
scores = softmax(router(x))
selected = topk(scores, k=top_k)
y = dispatch_tokens_to_experts(x, selected)
y = all_to_all(y)
y = expert_parallel_forward(y, experts)
y = all_to_all(y)
return combine_expert_outputs(y)
边界与诊断
dense FFN 的每 token FLOPs,用 conditional compute 只激活少数 expert。
总参数可能更大;快的是每 token active parameters,而不是模型文件更小。
小 batch、router 偏斜、capacity overflow 和跨节点 all-to-all 会让 MoE 变慢。
expert utilization、dropped tokens、all-to-all time、tokens per expert、load balance loss。
生成模型加速路线演化
不要只记论文名;更重要的是每个节点解决了哪种瓶颈。
去掉 RNN recurrence,让训练序列并行。
减少 decode KV 带宽;解决大模型训练显存和并行。
不重训 DDPM 也能跳步采样,把 diffusion 推向几十步。
IO-aware attention、PTQ 与高阶 solver 同时成熟。
LLM serving 进入动态批处理与 KV 管理;低比特部署和低显存微调普及。
注意力 kernel 适配新硬件;diffusion 开始系统复用跨步特征。
长上下文与多模态 serving 进一步转向 memory hierarchy、跨请求复用和硬件低精度;具体收益仍应以公开实现和真实 benchmark 为准。
决策地图:遇到慢,先判断慢在哪里
可操作的加速流程不是“把所有优化都上”,而是先分解瓶颈,再选择最少的干预。
LLM 推理慢
prefill 慢:FlashAttention、chunked prefill、prompt prefix cache、FP8/INT8、tensor parallel。
decode 慢:KV cache、MQA/GQA/MLA、PagedAttention、continuous batching、speculative decoding、KV quant。
Diffusion 图像慢
NFE 太高:DDIM、DPM-Solver、DPM-Solver++、UniPC、better timestep schedule。
单步太慢:FlashAttention、token merging、DeepCache / DiT cache、lower latent resolution、compiled runtime。
视频生成慢
瓶颈通常是 frames × resolution × denoising steps × temporal attention。优先看 video DiT cache、temporal window attention、frame chunking、decoder slicing 和 latent temporal compression。
训练慢 / 显存不够
显存:mixed precision、activation checkpointing、gradient accumulation、ZeRO/FSDP、QLoRA、sequence packing。
吞吐:FlashAttention、fused optimizer、data loader profiling、parallel degrees、communication overlap。
| 组合 | 什么时候适合 | 互补点 | 需要防的坑 |
|---|---|---|---|
| FlashAttention + continuous batching | LLM serving 同时有长 prompt 和高并发。 | 前者降 prefill IO,后者填 decode 空泡。 | prefill 抢占 decode 会伤 TPOT,需要 chunked prefill。 |
| GQA/MQA + KV quant + PagedAttention | 长上下文、高并发 decode 卡在 KV 显存/带宽。 | 减少 KV head、降低 bytes、改善分配碎片。 | long-context retrieval 和精确复制任务要单独评测。 |
| Speculative decoding + batch scheduler | target model decode 串行慢,draft 足够便宜。 | 减少 target forward 次数,同时保持 GPU occupancy。 | proposal 长度会让 batch shape 更不规则,accept rate 低会反噬。 |
| INT4/FP8 + fused kernels | 模型被权重带宽或 matmul throughput 限制。 | 低字节表示必须有真实 kernel 才能转成 latency 收益。 | 只压文件不融合 dequant,可能只省显存不省时间。 |
| Diffusion solver + feature cache | 图像/视频生成既 NFE 高,单步 denoiser 也重。 | 一个少走步,一个少算每步。 | 两种近似叠加,坏样本率可能非线性上升。 |
| FSDP/ZeRO + activation checkpointing + FlashAttention | 训练长上下文或大模型时显存放不下。 | 分别压模型状态、activation 和 attention IO。 | checkpoint 增加 FLOPs,sharding 增加通信,吞吐要实测。 |
常见误解
加速问题里最危险的是把不同瓶颈混成同一个词。
- FLOPs 少一定更快:不一定。LLM decode 经常 memory-bandwidth bound;不规则访存和 kernel launch 可能抵消 FLOPs 下降。
- 量化一定加速:量化会降低存储,但是否降低 latency 取决于硬件低精度 kernel、batch size、dequant 是否融合和真实瓶颈。
- FlashAttention 是近似 attention:不是。它是 exact attention 的 IO-aware 实现,不是 low-rank 或 sparse approximation。
- KV cache 只会加速:KV cache 避免重复计算,但长上下文和高并发下会成为主要显存与带宽瓶颈。
- Diffusion 加速只有蒸馏:蒸馏很重要,但 DDIM、DPM-Solver、UniPC、cache、token merging、scheduler 和 attention kernel 也能加速。
- MoE 参数多所以一定慢:MoE 每 token 只激活少数 expert,真正瓶颈常在 router imbalance 和 all-to-all communication。
阅读边界
本页是机制地图,不替代真实 profiling。任何加速方案落地前,都应分开测 prefill / decode、单请求 / batch、TTFT / TPOT、显存峰值、kernel utilization 和质量指标。
进一步阅读
这里列的是相对稳定的论文、工具和系统方向;2025-2026 的内容只按趋势观察理解,落地时仍要读具体实现和 benchmark。
Attention / Kernel
- FlashAttention / FlashAttention-2 / FlashAttention-3:IO-aware exact attention。
- xFormers, Triton, CUTLASS:理解 kernel fusion、layout 和硬件 tensor core 的工具链。
LLM Serving
- vLLM / PagedAttention:KV cache block 管理与 high-throughput serving。
- Orca, Sarathi-style chunked prefill:continuous batching、iteration-level scheduling 和 prefill/decode 共存。
Quantization
- GPTQ, AWQ, SmoothQuant:PTQ 的误差补偿、salient channel 保护和 activation smoothing。
- bitsandbytes, AutoGPTQ, TensorRT-LLM:部署时检查 kernel 与硬件路径。
Speculative Decoding
- Speculative Decoding / Assisted Generation:draft-verify 的分布保持版本。
- Medusa, EAGLE, multi-token prediction:工程上常见的 proposal 变体,需要单独标注近似边界。
Diffusion
- DDIM, DPM-Solver, DPM-Solver++, UniPC:少步 sampler / solver 的主线。
- DeepCache, DiT cache, Token Merging:减少单步 denoiser 或 token 计算的近似路线。
Training
- ZeRO, FSDP, Megatron-LM:模型状态 sharding 与多维并行。
- Activation checkpointing, sequence parallel, QLoRA:显存峰值和低显存微调的实用工具。