wafer_ai发布全球最全AI性能工程知识库
我们上周发布了全球最全面的AI性能工程代码库。现在我们会对每一项资源做深度解析。这就是Wafer的AI性能工程系列,把它存下来作为你的起点。链接如下🧵
第一部分:预填充(Prefill) vs 解码(Decode)
因果自回归Transformer会基于提供的前缀计算下一个token的logits。解码策略选出一个token,把它拼在末尾,再让模型预测下一个。
在传统因果解码器中,每个位置只能关注自身和更早的位置。追加新token不会给旧位置增加允许的输入。在评估模式下,前缀、权重、掩码和位置计算都是固定的,旧的表征可以重复利用。
KV缓存会存储更早位置的每层键和值,供后续前向传播重复使用。预填充会在因果掩码下处理已知提示,保存每一层的键和值。提示的最后一个位置会产出用来选择第一个输出token的logits。同一个层内的所有提示位置可以并行处理,层之间仍然存在依赖关系。
解码策略选出一个token。贪心解码选择得分最高的token;采样则从分布中抽取token。把选好的token送回模型处理,生成它的K/V,再产出下一个输出的logits。输出token和处理token是两个独立步骤。
要输出N ≥ 1个token,普通循环需要一次完整分块的预填充和N−1次增量前向传播。输出最后一个token不需要再把它送入模型处理。新token仍然需要经过所有层处理,包括投影和MLP。它的查询会计算新的注意力分数,再对缓存值做加权求和。
存储K/V节省了重复的前缀计算,但还是需要在不断增长的上下文上做新的注意力计算。对于固定的提示长度和模型维度,缓存把总的投影和MLP计算量从输出长度的二次方变成了线性。整个生成过程的全因果注意力计算量仍然是二次方的。
这些计算量统计不能直接对应实测的延迟提升。预填充处理来自同一个提示的大量已知token行。普通解码每个活跃请求只新增一行,所以可以把不同请求打包成批次处理。每个请求还需要独立的逻辑KV状态。更多并发请求、更长的保留上下文都会增加这个状态的占用。
你需要根据工作负载选择性能目标。离线生成可能优先满足截止时间内每美元完成的工作量。流式对话还要求首Token延迟低,后续输出响应快。单用户设备可能要在内存和算力限制内优先降低延迟。
做服务性能对比时,要固定提示/输出长度和并发数。测量客户端的首Token时间、后续Token间隔,以及共同测量窗口内的总输出Token数。把纯模型预填充时间和排队、传输时间分开统计。光看总吞吐率更高,没法告诉你单个用户的答案会不会更早到达。
本文由 AI 翻译自英文原帖,技术名词保留英文。
查看 X 原帖