文章

FlashAttention 入门:从 FA1 到 FA4 的 IO 感知注意力

FlashAttention 入门:从 FA1 到 FA4 的 IO 感知注意力 注意力层是把 Transformer 扩展到长序列时的主要瓶颈:它的时间与内存开销都随序列长度平方增长。FlashAttention 是一族让注意力保持精确(exact)的同时显著提速、省内存的算法,其核心理念是把 GPU 的内存流量——而不只是 FLOPs——当作需要优化的资源。本文用原创的图示与推导讲清核心思想:GPU 内存层级、分块(tiling)、在线 softmax(online softmax)、反向重计算(recomputation),然后是 FA1 → FA2 → FA3 → FA4 的时间线、独立 flash-attn 包与 PyTorch scaled_dot_product_attention 的区别,以及实践中真正要紧的硬件注意事项。 本文有两条规则。第一,所有性能数字均为引用,来自原始论文、Dao-AILab 官方仓库与 PyTorch 官方文档,每个数字都绑定其测量硬件;本文没有任何本地基准结果。第二,本文写作所用的工作站 GPU 是 TITAN RTX(Turing 架构,计算能力 7.5)——这不是巧合,因为官方的 FlashAttention-2/3/4 CUDA 内核无法在 Turing 上运行,最后一节把这个限制转化为一份诚实的验证方案。 文中所有”截至”表述均指 2026-08-09。 注意力为什么是平方复杂度 以单头为例,设 query、key、value 矩阵为 $Q, K, V \in \mathbb{R}^{N \times d}$($N$ 个 token,头维度 $d$),缩放点积注意力为: $$S = \frac{Q K^{\top}}{\sqrt{d}}, \qquad P = \operatorname{softmax}(S) \text{(按行)}, \qquad O = P V,$$

一分为二:面向 SLO 的 LLM 预填充/解码分离架构

一分为二:面向 SLO 的 LLM 预填充/解码分离架构 单个服务实例把提示词处理与逐词元生成混在一起,实现起来很简单,对很多部署来说也是正确选择。但一旦你需要在持续请求速率下满足延迟目标,LLM 请求的两个阶段就会在同一批 GPU 上互相干扰。预填充/解码分离(prefill/decode disaggregation)通过把两个阶段拆分到独立的机器池、并用快速的 KV 缓存交接把它们连接起来,消除了这种冲突。本文基于主要的系统论文(DistServe、Splitwise、Mooncake)以及生产引擎(vLLM、NVIDIA Dynamo)的现行官方文档,说明分离架构到底买到了什么——以及买不到什么。 文中所有性能数字均引自所列论文与官方文档,并附有各自的测试环境;本文未在本机复现任何一项。文章最后给出一个可在单机上执行的确定性轨迹回放实验设计,用来实测这一权衡。 两种延迟,一条队列 一个 LLM 请求包含资源画像截然相反的两个阶段: 预填充(prefill):用一次前向传播处理完整提示词并产出第一个词元。它受计算限制:对 13B 模型而言,512 个词元的提示词已足以让一块 A100 接近计算饱和 [1]。 解码(decoding):逐词元、逐步生成后续输出。每一步都要读取整个 KV 缓存,因此受显存带宽限制,计算单元大量空闲 [1, 2]。 两个延迟指标由此而来。首词元时间(time to first token,TTFT)主要由预填充阶段决定;每输出词元时间(time per output token,TPOT)是解码阶段的平均单步时间。vLLM 官方文档把 TPOT 称为 inter-token latency(ITL),并将 TTFT 与 ITL 视为两个可独立调优的在线服务目标 [4]。 问题在于:在共置(单体)实例中,两个阶段共享同一块 GPU 和同一条队列。连续批处理(continuous batching)刻意把两者混批,于是一次漫长的预填充会拉长与其同批的解码步骤(TPOT 恶化),而同批的解码工作也会推迟预填充(TTFT 恶化)。DistServe 在 13B 模型上的测量清楚地展示了这一效应:在单块 A100 上以 90% SLO 达成率为目标,单体系统大约只能支撑 1.6 请求/秒,而同一块 GPU 若只做预填充可支撑 5.6 请求/秒,只做解码可支撑 10 请求/秒。用 2 块 GPU 做预填充、1 块做解码,即可服务 10 rps——即每 GPU 3.3 rps,是单体系统的 2.1 倍 [1]。

SGLang:从前端 DSL 到 SRT 服务运行时

SGLang:从前端 DSL 到 SRT 服务运行时 SGLang 是一个面向大语言模型与多模态模型的开源服务框架,由 LMSYS 组织下的 sgl-project/sglang 仓库以 Apache-2.0 许可证发布。截至 2026-08-09,该仓库约有 31.6k 星标,最新发布版本为 v0.5.17(2026-08-08)。在所有这些数字之前,有一句话更能说明问题:SGLang 实际上是两个系统——一个内嵌于 Python、用于编写”LLM 程序”的前端语言,以及一个最初被称为 SRT(SGLang Runtime)的服务运行时。理解两者之间的边界,就能同时看懂这个项目的历史和它在推理引擎中的当前位置。 本文是一次概念层面的巡览:前端与运行时、RadixAttention 与前缀复用、缓存感知调度、结构化生成、并行能力,以及今天与 vLLM 的比较边界在哪里。文中的性能数字均引自一手来源(NeurIPS 2024 论文、官方发布博客与官方文档),并标注了日期、硬件与基准版本;我们没有在本地复现任何一项。 两张面孔:前端语言与运行时 论文 SGLang: Efficient Execution of Structured Language Model Programs(arXiv:2312.07104,2023-12-12 首次发布,2024-06-06 修订,作为海报论文在 NeurIPS 2024 上报告)开篇即给出了一个至今仍然成立的设计拆分: 前端——一种内嵌于 Python 的领域特定语言(DSL),用于表达带生成调用、分支与并行的提示词程序; 运行时(SRT)——一个调度器、一个基数树 KV 缓存管理器与一个模型执行器,负责执行这些程序(或普通的服务请求)。 论文明确指出两部分可以独立工作:前端可以对接远程 API 模型,运行时也可以完全不涉及 DSL 地服务普通请求。这种独立性是解读 SGLang 演进的关键——运行时成长为通用的服务引擎,而前端成为该项目(可选的)另一张面孔。 前端:内嵌于 Python 的 DSL 前端语言就是普通的 Python,加上 @function 装饰器。在函数内部,通过追加消息块(s += user(...)、s += assistant(...)、s += system(...))和生成调用来构建一个 State 对象。依据论文与当前官方文档中的前端教程,核心原语包括:

vLLM 引擎解剖

vLLM 引擎解剖 vLLM 是部署最广泛的开源大语言模型推理引擎,它的核心思想几乎被后来所有的 serving 框架默默借鉴。本文从内到外拆解这个引擎:预填充/解码的执行模型及其时延指标、分页式 KV 缓存(PagedAttention)、当前 V1 引擎的统一调度器、抢占与前缀缓存,以及 vLLM 为生产监控暴露的 Prometheus 指标。最后讨论它与邻近系统——FlashAttention、SGLang 与分离式预填充——的边界,并给出在单块 TITAN RTX 上如实复现本文内容的指南。 文中一切内容均引自一手来源(PagedAttention 论文、vLLM 官方文档与仓库,以及相邻系统的原始论文),信息截至 2026-08-09;文末附有带日期的版本说明。本文作者没有运行任何基准测试:文中每个性能数字都引自测量它的原始来源。 预填充、解码与三个时延指标 Transformer 的文本生成是自回归的:模型一次只产出一个词元,每个新词元都要与之前的所有词元做注意力计算。serving 系统把这一过程切成两个形态截然不同的阶段: 预填充(prefill)处理提示词。长度为 $P$ 的提示词在一次(或少数几次)前向传播中并行跑完整个模型,每个提示词元组的键(key)和值(value)都被计算出来并写入 KV 缓存。预填充是计算密集型的,每一层都要全量计算。 解码(decode)逐个生成输出词元。每一步只对最新词元跑一次模型,此前所有词元的键/值直接从 KV 缓存读取。解码是内存带宽密集型的:每一步几乎不重复计算注意力状态,但必须把整份 KV 缓存流过 GPU。 这两个阶段对应着所有 serving 基准测试都会引用的三个时延数字: TTFT——首词元时延(time to first token):从请求提交(vLLM 从被调度算起)到返回第一个生成词元。它由预填充主导。 ITL——词元间隔时延(inter-token latency):解码阶段相邻输出词元之间的时间,即解码阶段每步的时延。 TPOT——每输出词元耗时(time per output token):解码阶段产出一个输出词元的平均时间。vLLM 官方的参考 Grafana 面板把 vllm:inter_token_latency_seconds 指标当作 TPOT 使用,因此实践中两者经常混用。 图 1 把它们放在一条时间线上。TTFT 期间请求是不可交互的,所以交互型用户最关心 TTFT;吞吐型负载关心的是 ITL/TPOT,以及有多少请求在并发解码。 请求到达 首词元 末词元 | | | |<------- 预填充 -------->|<---- 解码(每步一个词元)---->| |<------- TTFT --------->| |<-- ITL -->|<-- ITL -->|<-- ITL -->| |<--------- 生成时间 --------->| |<---------------------- 端到端请求时延 -------------------->| 图 1 —— TTFT、ITL 与 TPOT 在请求时间线上的位置。TTFT 覆盖预填充;ITL/TPOT 描述解码阶段。定义遵循 vLLM 的 per-request 指标文档。

字体
阴影
滤镜
圆角
主题色