为什么上下文越长越贵?O(n²) 的账单
注意力机制要让每个 Token 看所有 Token:拖动上下文长度,看计算量和账单按平方往上蹿——长对话变卡变贵的根源
本页解决的问题
先给结论「为什么上下文越长越贵?O(n²) 的账单」要解决的关键问题是什么?
注意力机制要让每个 Token 看所有 Token:拖动上下文长度,看计算量和账单按平方往上蹿——长对话变卡变贵的根源
让这个结论先证明自己值得留下。 把这一页当成决策工具,而不是需要背下来的定义。把概念连到一个真实任务、一个可观察结果,以及一个能改变你判断的失败上。
写下一个问题:试完这个方法后,你能用什么证据回答它?
结论听起来很完整,却没有检查最关键的假设。
前面的课程讲过:大模型生成每个新词元(token)时,都要「回头看」前面所有的词元,给每个词分配注意力权重,才知道接下来该接什么。一个 token 看一遍所有 token——这句话用上一课的语言翻译一下:n 个 token,每个都要看 n 个,总共 n × n 次「对视」。这就是一张 n×n 的表格。拖滑块画给你看。
下面每一行代表「一个 token 要看所有 token」,深色对角线是它看自己。留意右边的格子总数:滑块只是匀速往右拖,数字却越跳越猛——这就是「平方增长」的手感。
同样问一句「帮我总结一下重点」,一个人先把历史精简到 1 万 token,另一个人把 10 万 token 的完整记录原样塞进去。token 只差 10 倍,看看账单差多少。留意「注意力计算量」那一行:它不是 ×10,是 ×100。
精简派 1 万 token
全塞派 10 万 token
① 为什么长对话越来越卡
聊得越久,n 越大,每生成一个新 token 要做的「回头看」就越多。卡顿不是网络问题,是 n² 在后台滚雪球。
② 为什么要做上下文压缩
Compaction 把旧对话摘要成一小段再继续聊。牺牲一点细节,换 n 大幅变小——n 砍一半,计算量砍四分之三,划算。
③ 为什么 KV Cache 能省钱
前缀部分算过的注意力结果缓存下来、下轮不重算(姊妹篇 ds-6 讲过)。正因为原始计算是 O(n²) 的贵,缓存的折扣才这么值钱。
「先回忆一下 · 注意力在干嘛」里的算法代价曲线
「前面的课程讲过:大模型生成每个新词元(token)时,都要「 回头看 」前面所有的词元,给每个词分配注意力权重,才知道接下来该接什么。一个 token 看一遍所有 token——这句话用上一课的语言翻译一下: n 个 token,每个都要看 n 个,总共 n × n 次「对视」 。这就是一张 n×n 的表格。拖滑块画给你看」真正训练的不是背诵步骤,而是识别重复工作:输入变大时,程序到底多做了多少次比较、移动或递归。
先找重复工作,再谈快慢
「下面每一行代表「一个 token 要看所有 token」,深色对角线是它看自己。」可以拆成输入规模、每轮做什么、以及是否能缩小下一轮范围三个问题。Big-O 是描述增长趋势的语言,不是对每台机器的精确计时;常数、内存和真实数据分布也会影响最终结果。
- 注意力是 O(n²) :每个 token 都要回头看所有 token,n×n 张表逃不掉
- 上下文不是免费的仓库 :塞进去的每个 token 都会被后面所有 token 反复看
- 翻 10 倍 = 贵 100 倍 :计算量按平方涨,这是长对话变卡变贵的根源
别把理论最优当成无条件最优
面对 AI 写出的算法,先用小输入手算一遍,再用逐渐放大的数据做基准测试。这样才能把「前缀部分算过的注意力结果缓存下来、下轮不重算(姊妹篇 ds-6 讲过)。」从一句结论变成可检查的性能判断。
从「先回忆一下 · 注意力在干嘛」走到「交互一 · 注意力矩阵:n² 长什么样」
「先回忆一下 · 注意力在干嘛」先把问题落在「前面的课程讲过:大模型生成每个新词元(token)时,都要「 回头看 」前面所有的词元,给每个词分配注意力权重,才知道接下来该接什么。一个 token 看一遍所有 token——这句话用上一课的语言翻译一下: n 个 token,每个都要看 n 个,总共 n × n 次「对视」 。这就是一张 n×n 的表格。拖滑块画给你看」上;到了「交互一 · 注意力矩阵:n² 长什么样」,讨论继续推进到「下面每一行代表「一个 token 要看所有 token」,深色对角线是它看自己。 留意右边的格子总数:滑块只是匀速往右拖,数字却越跳越猛——这就是「平方增长」的手感」。两段连起来,重点就不只是记住一个结论,而是看清它成立所依赖的条件。
把这条判断带到下一个场景
算法题换成真实任务后,先找出重复工作,再问输入规模如何变化,最后用一个小基准验证理论判断。这样不会把复杂度记成脱离场景的标签。
- 「先回忆一下 · 注意力在干嘛」:前面的课程讲过:大模型生成每个新词元(token)时,都要「 回头看 」前面所有的词元,给每个词分配注意力权重,才知道接下来该接什么。一个 token 看一遍所有 token——这句话用上一课的语言翻译一下: n 个 token,每个都要看 n 个,总共 n × n 次「对视」 。这就是一张 n×n 的表格。拖滑块画给你看
- 「交互一 · 注意力矩阵:n² 长什么样」:下面每一行代表「一个 token 要看所有 token」,深色对角线是它看自己。 留意右边的格子总数:滑块只是匀速往右拖,数字却越跳越猛——这就是「平方增长」的手感
- 「最后的要点」:精简上下文 = 省钱省时间 :压缩、摘要、KV Cache 全是在和这个 n² 搏斗
最后的「最后的要点」把讨论落到「精简上下文 = 省钱省时间 :压缩、摘要、KV Cache 全是在和这个 n² 搏斗」。回看这条线索时,最值得保留的是:当输入、规模或风险改变,哪些判断需要重新做一遍。
✅ 这一课想和你分享的
- 注意力是 O(n²):每个 token 都要回头看所有 token,n×n 张表逃不掉
- 上下文不是免费的仓库:塞进去的每个 token 都会被后面所有 token 反复看
- 翻 10 倍 = 贵 100 倍:计算量按平方涨,这是长对话变卡变贵的根源
- 精简上下文 = 省钱省时间:压缩、摘要、KV Cache 全是在和这个 n² 搏斗
我把这篇文章里的一个判断改写成了今天可以验证的小实验。比记住结论更有用的是,知道下一步要观察什么。
读完以后我先回头找它成立的条件,而不是直接把方法搬进项目。这个顺序让后面的取舍清楚很多。
如果把这个判断放到真实工作里,最先需要补的约束是什么?我想知道从阅读到第一次实践之间,哪一步最值得先做。
还没有这篇文章的讨论。