Shallow Encoding Emits Deep Memories,47 页,arXiv 2611.06084,11 月 4 日挂上去的。我第一眼看标题,以为是又一篇压 KV cache 的——翻到第三页就知道想错了,论文里明说了,它不压注意力缓存。它撬的是另一块地方:线性层每个 head 那坨固定大小的循环状态。
这玩意儿平时根本不在我们视野里。
画张图。现在能打的这批模型,不少是混着堆的——少量 softmax 注意力层,插在一大摞线性注意力或者状态空间层中间。为什么这么混,同行都懂,不展开。我要说的是这个混法带出来的东西:每一层都在攒自己的账。
层 1 [ softmax attn ] → KV cache(跟 token 数一起涨)
层 2 [ linear attn ] → 循环状态(固定大小)
层 3 [ linear attn ] → 循环状态
...
层 N [ softmax attn ] → KV cache
这张图没什么信息量,我知道。它唯一的用处是提醒你:账不是只有一本。
然后论文说了件事,我读第一遍没反应过来:服务的时候,维护这些记忆要花的算力和高带宽显存,比最后吐出那个 token 还多。
读第二遍,我停了一下。平时我们算账算的是什么?“生成一个 token 要多少 FLOPs”。很少有人把“维护记忆”这一项从总账里单拎出来摆桌上。它就那么一直在那儿,混在总数里。
往下看,是两段。
预填充 ── 提示里每个 token,都得从一楼爬到顶楼
解码 ── 每吐一个字,每层的抽屉拉开 → 改 → 推回去
预填充是“每个提示 token 都过所有层”,这个清楚。解码是“每一步都要把完整的循环状态读写一遍”——不是读一次就完事,是每一步都读、都写。这就有点要命了。
“固定大小”这四个字特别容易骗人。它在说“不随上下文增长”,但没说不绝对值大。在 Qwen3.8-Flash-Next 上,单个请求的状态占的字节数,能跟几千个 token 的注意力缓存打平。几千个 token 的 KV cache,那不是一个能随手忽略的数。
写比读便宜
论文里那句话,我照着它的意思抄一遍:给某个 token 往深层写记忆,需要的深层计算,远少于预测下一个 token 需要的深层计算。
——是远少于。等等等等,先别急。这三个字里藏着整篇论文。
我第一版看到这句,脑子里的图是:既然每层都在写记忆,那每层都得跑,这不废话吗。然后把这一页翻过去了。翻过去两页又觉得不对,翻回来重看。
第一版错在哪:我把“写记忆”和“用记忆预测”当成了同一件事。它们在一层里挨着出现,但代价不一样。
作者干的事说白了就一句:训一份深层写入路径的副本,叫 emitter,让它从较浅的锚定层拿残差流,直接把这个提示的深层记忆生成出来。这么一来,除了最后一个提示 token,其余的提示 token 只需要跑大约 63% 的层。
我以为的:
t1 ─► L1 ─► L2 ─► ... ─► LN ─► 写完记忆
t2 ─► L1 ─► L2 ─► ... ─► LN ─► 写完记忆
(每个 token,整栋楼爬一遍)
实际的:
t1 ─► L1 ─► ... ─► L(0.63N) ─┐
├─► emitter ─► 深层记忆
t2 ─► L1 ─► ... ─► L(0.63N) ─┘
tn ─► L1 ─► ... ─► LN (最后一个不能省,它要出预测)
那个“除了最后一个”的例外,我觉得比 63% 这个数字本身还有意思。它把线划出来了:能省的是写记忆的深度,不能省的是拿最后一个 token 出预测的那一段。这两件事在这篇里被彻底分开了;在我们平时的脑子里,它们黏成一坨。
第二个发现更意外。每个 head 的循环状态,大部分能量集中在固定方向上的一个秩一项上。剩下的那部分,才是真正在变、在装东西的低秩工作记忆。
我第一次读到“大部分能量集中在固定方向”,反应是:那减掉不就完了。不对。那个秩一项是参与前向的,它不是垃圾。
画个示意——注意只是示意,真实维度比这吓人得多