@athleticKoder:一篇关于LLM推理原理的1600字笔记,涵盖:1. 注意力机制——token交互的唯一场所 2. KV缓存——为何...

X AI KOLs Timeline 新闻

摘要

一篇详细阐述LLM推理关键概念的推文:注意力机制、KV缓存、分块预填充以及批处理技术,包括vLLM和SGLang中使用的连续批处理。

一篇关于LLM推理原理的1600字笔记: 涵盖: 1. 注意力机制——token交互的唯一场所 2. KV缓存——为什么一旦预填充完成,解码就变得廉价 3. 分块预填充——处理内存无法容纳的大提示词 4. 朴素批处理——为什么填充会扼杀吞吐量 连续批处理——不规则批处理 + 动态调度的结合 这就是安静驱动vLLM、SGLang以及每个服务栈的技术。从基本原理开始构建。 A
查看原文
查看缓存全文

缓存时间: 2026/07/02 18:25

一篇关于大语言模型推理如何工作的1600字笔记:

涵盖内容:

  1. 注意力机制——唯一让词元相互交互的地方
  2. KV缓存——为何预填充完成后解码就变得廉价
  3. 分块预填充——处理超出内存容量的提示词
  4. 朴素批处理——为何填充会扼杀吞吐量
    连续批处理——非对齐批处理与动态调度的结合

这项技术默默支撑着vLLM、SGLang以及所有推理服务框架。从基本原理构建起来。


A

一个LLM本质上就是下一个词元的预测器。它一次性读取你的完整提示词(预填充),然后逐个生成词元,每一步都会重新读取到目前为止的所有内容(解码)。

这个解码循环代价高昂。连续批处理是在服务众多用户时不浪费GPU周期的最大杠杆。

**注意力机制是唯一让词元彼此交互的层。**其他所有层(层归一化、矩阵乘法)都是逐词元进行的。

Q·Kᵀ 计算每对词元之间的相似度——这就是大家常抱怨的二次方开销。

然后你应用一个掩码(因果掩码 = 只能向后看)、softmax,再乘以V。这就是一个注意力头。

把掩码想象成一个网格:绿色 = “这个词元能看到那个词元。”

一旦你对全貌熟悉了,就可以简化:只需画出Q、K和掩码。V的长度总是与K相同,所以不需要单独画出来。

朴素续写:为了生成下一个词元,你会重新执行完整的前向传播——重新计算已经处理过的词元的K和V。纯粹是浪费。

#1 — KV缓存

最新的词元永远不会影响较早词元的注意力(因果掩码)。而且你已经在上一轮计算了它之前所有内容的K/V。所以将它们缓存起来,而不是重新计算。

这使得每个新词元的解码计算量从O(n²)降到O(n),代价是O(n)的内存。只有新词元需要全新计算——其他一切都是查表。

(Llama-2-7B:每个词元约16KB缓存。规模大了之后累积得很快。)

#2 — 分块预填充

真实的提示词(比如你在Cursor上下文窗口中的整个代码库)无法在一次传递中放入内存。将预填充拆分成多个块,利用KV缓存在它们之间传递状态。

现在来看批处理问题。朴素地对提示词进行批处理意味着将所有内容填充到相同长度——张量必须是矩形。

当提示词大约在同一时间完成时,这种方式工作得很好。

但实际流量并不配合。将一个已完成的位置换成一个新提示词,这个新提示词需要完整的预填充,而其他人还在解码中。

结果:一堵填充墙。代价随批大小×提示词长度呈二次方增长。

#3 — 非对齐批处理

不是将提示词堆叠在批处理轴上(→填充),而是将它们拼接成一个长序列。

然后使用注意力掩码防止提示词0的词元泄露到提示词1的注意力中。无需填充。

将尽可能多的提示词打包进你的词元预算中,在同一批次中混合预填充块和解码词元。结合动态调度(立即替换已完成的提示词)→ 连续批处理。

所以,连续批处理 = 三个概念的堆叠:

  1. KV缓存 → 不重新计算过去
  2. 分块预填充 → 在内存限制内处理长提示词
  3. 非对齐批处理 + 动态调度 → 消除填充,保持GPU满载

这就是ChatGPT能够同时服务数千用户的原因。

就是这样!你可以在这里找到完整的博客文章。

相似文章

内存

Reddit r/artificial

解释了为什么由于KV缓存随上下文长度和并发用户数扩展,LLM推理越来越受内存带宽限制,以及像vLLM和PagedAttention这样的系统如何提高内存利用率。