abc小站

2026-10-12

长程 agent 把显存撑爆以后:哈工大 SparseEngine 为什么要从零重建推理引擎

哈工大开源 SparseEngine:长程 agent 的 KV cache 撑爆后,用稀疏优先推理引擎与 Chain Cache 接上被驱逐的记忆。

一个 AI agent 连续工作一个小时,它的"记忆"放在哪里?

很多人会说,放在上下文里。

这个回答没错,但是只说了一半。

上下文是文字,真正占用显卡内存的,是模型为这些文字算出来的一份中间结果,叫做 KV cache。

对话短的时候,它不起眼。

对话一长,它就会把显存撑爆。

最近,哈尔滨工业大学的团队开源了一个推理引擎 SparseEngine,论文编号 arXiv:2609.39068。

它要解决的,正是这个问题:长程 agent 的 KV cache 装不下时,怎么办。

它的答案是稀疏注意力。

但是,稀疏注意力并不是新东西,学界已经提出了很多种算法。

为什么还要专门做一个新引擎,而不是把这些算法装进现成的 vLLM 一类引擎?

今天就用大白话,把这件事讲清楚。

一、KV cache 是什么

先说一般原理。(这一节是大模型推理的通用知识,不是 SparseEngine 的发布内容。)

大模型生成文字,是一个 token 一个 token 往外蹦的。

每生成一个新 token,模型都要回头看一遍前面所有的 token,决定"现在该说什么"。

这个"回头看"的动作,就是注意力(attention)。

问题来了:如果每一步都把前面所有内容从头算一遍,计算量会非常大。

所以,推理引擎会把前面每个 token 算好的两份中间结果----Key 和 Value----存起来,下一步直接拿来用。

这份存下来的东西,就叫 KV cache。

打个比方。

KV cache 就像做数学题时的草稿纸。

前面算过的步骤写在纸上,后面要用时扫一眼就行,不用重算。

但是草稿纸有一个特点:题目越长,用掉的纸越多。

KV cache 的大小,大致和上下文长度成正比。

普通聊天,几轮就结束,草稿纸够用。

长程 agent 就不一样了。

二、长程 agent 的麻烦

所谓长程 agent,就是那种要跑几十轮、上百轮才能完成任务的智能体。

比如,SparseEngine 面向的场景里,提到了 BrowseComp 和 Terminal-Bench 这类长交互任务。

前者需要在网上反复搜索、翻页,才能找到一个难找的答案;后者需要在命令行里一步步操作,完成一个工程任务。(对这两个基准的描述是一般性介绍。)

我们设想一个场景(这是假设,用来说明问题):一个 agent 在做网页检索任务,每一轮都要把搜索结果、网页正文、自己的思考过程放进上下文。

第 1 轮,上下文几千个 token。

第 30 轮,可能已经十几万个 token。

每多一轮,草稿纸就厚一层。

而显卡内存是固定的,不会跟着变大。

总有一刻,KV cache 放不下了。

这时,引擎只有几个选择:拒绝新请求、减少同时服务的请求数,或者把一部分 KV 扔掉。

扔掉的动作,英文叫 eviction(驱逐)。

驱逐听起来很简单,但是扔掉哪些、扔掉以后怎么办,都是问题。

三、稀疏注意力:只看重要的那几页

稀疏注意力的思路,来自一个朴素的观察。(这一节同样是一般原理。)

模型回头看前文的时候,并不是每个 token 都同样重要。

一篇几万字的网页里,和当前问题真正相关的,可能只有几段。

既然如此,能不能只看重要的部分,忽略其他部分?

这就是稀疏注意力:不再对所有旧 token 一视同仁,而是挑出一部分来算,或者干脆把不重要的 KV 清理出去。

打个比方,普通注意力像是每做一步,都把整本草稿纸从头翻一遍;稀疏注意力像是只翻那几页做了标记的。

这样做,省显存,也省计算。

学界围绕这个思路,提出了各种各样的方法。

SparseEngine 支持其中 4 个族、共 15 种稀疏注意力算法。(具体是哪 15 种、怎么分族,请看论文和项目仓库,本文不逐一列举。)

既然算法有这么多,为什么在实际的服务系统里不常见?

四、为什么进不了 vLLM 一类的引擎

要回答这个问题,得先说说 vLLM 这类引擎是怎么管理 KV cache 的。(以下是一般原理。)

现在主流的开源推理引擎,大多借鉴了操作系统的内存分页思想。

KV cache 被切成固定大小的块,叫做"页"。

每个请求需要多少,就分配多少页,用一张表记下"第几个 token 的 KV 在哪一页"。

这个设计很成功,它解决了显存碎片的问题,让一张显卡能同时服务更多请求。

但是,它有一个隐含的前提:每个 token 的 KV 都老老实实存在页里,注意力计算时,按顺序把这些页全部读一遍。

这就是"dense(稠密)"的意思。

整套系统----内存分配、调度、批处理、缓存复用----都是围绕这个前提设计的。

稀疏注意力恰恰要打破这个前提。

它要求引擎能做这些事:挑出一部分 token 来算,扔掉另一部分;扔掉以后,页表里留下空洞;不同的算法,挑选和丢弃的规则还各不相同。

在一个以"全部存、全部读"为中心的系统里,做这些事,就像在一栋按整层出租设计的写字楼里,突然要按工位出租。

不是做不到,但是水电、门禁、物业管理都要跟着改,每加一种出租方式,就要再打一轮补丁。(这里冲突点的归纳和比喻是我的推断,论文的具体分析请看原文。)

这大概就是很多稀疏注意力算法停留在论文和实验代码里,很难进入生产服务的原因。(这是我的推断。)

SparseEngine 的做法是:不在稠密引擎上打补丁,而是从零开始,按"稀疏优先"重新设计服务层。

也就是说,从一开始就假设 KV 会被挑选、会被驱逐,再在这个假设上搭内存管理和调度。

五、Chain Cache:扔掉的东西,下一轮还要用

稀疏优先的引擎,会主动驱逐 KV。

但是 agent 的工作是多轮的。

这一轮扔掉的内容,下一轮可能又需要了。

举个例子(假设场景):agent 在第 5 轮读过一份文档,第 12 轮时这份文档的 KV 已经被驱逐,到了第 20 轮,它又需要引用文档里的一段话。

这时候怎么办?

最笨的办法,是把前面所有内容重新算一遍,相当于草稿纸丢了,整道题重做。

对长程 agent 来说,这个代价很大,因为前文可能已经有十几万个 token。(这是按一般原理的推断。)

SparseEngine 用一个叫 Chain Cache 的机制处理这个问题:在 KV 被驱逐以后,跨多轮把它恢复回来。

它具体怎样记录和恢复,公开报道没有展开,有兴趣的话可以读论文。

但是它解决的问题很清楚:驱逐不再是"一次性的永久丢失",多轮对话之间可以接上。

六、Controllable Prefix-Cache Pruning:删旧历史,又不想丢前缀

第二个机制,名字比较长,叫 Controllable Prefix-Cache Pruning,直译是"可控的前缀缓存修剪"。

要理解它,先说 prefix cache(前缀缓存)。(以下是一般原理。)

很多请求的开头是一样的:同样的系统提示、同样的工具说明、同样的前几轮对话。

既然开头一样,就没必要每次都重新算,算一次,存起来,后面的请求直接复用。

这就是前缀缓存。

agent 特别依赖它,因为每一轮请求,都带着前面所有轮的历史,前缀高度重合。

但是前缀缓存有一个脾气:它是从头开始逐个 token 比对的。

只要中间有一处不一样,从那里往后的缓存全部作废。

现在矛盾来了。

长程 agent 上下文太长,自然想删掉一些旧历史,腾出空间。

可是,如果从对话中间删掉一段,新请求的 token 序列就和缓存里的不一致了。

结果是:显存省下来了,前缀缓存却失效了,后面的内容得重算。(这一段对冲突的描述,是按一般原理的推断。)

Controllable Prefix-Cache Pruning 要解决的,就是这个两难:在删除旧历史的同时,保住前缀匹配。

至于名字里的"可控",我的理解是,删什么、怎么删,可以按需要控制,而不是一刀切。(这是我根据名字的推测,请以论文为准。)

把两个机制放在一起看,思路是一致的。

Chain Cache 管的是"扔掉以后还能找回来"。

Prefix-Cache Pruning 管的是"删掉一部分,不连累其他部分"。

两者都是为了让"驱逐"和"多轮复用"这两件事,在长程 agent 里不再互相打架。

七、效果怎么样

下面这些数字,都是论文称的结果。

(1)在发生 KV 驱逐的情况下,吞吐量提升超过 10 倍。

(2)同样的并发数下,解码速度比 vLLM 快超过 2.5 倍。

(3)端到端的任务执行,快了超过 2 倍,并且推理准确度没有下降。

这些数字看上去很亮眼,但是读的时候要注意几点。

第一,它们都是论文作者自己的测量,目前我没有看到第三方的独立复现。

第二,每个数字都有前提条件。比如"超过 10 倍"是在 KV 驱逐场景下,"超过 2.5 倍"是在同等并发、只看解码阶段。具体用了什么模型、什么硬件、和哪个版本的 vLLM 对比,要看论文原文。

第三,"准确度不降"也是论文的说法,适用于论文测试的任务和设置,换一个场景未必一样。(这三点提醒是我的看法。)

做一个简单的换算,帮助理解端到端 2 倍是什么意思。(以下是我自己算的,场景是假设的。)

假设一个长程任务原来要跑 60 分钟,端到端快 2 倍,就是 30 分钟左右。

如果一个团队每天要跑 100 个这样的任务,那就是从 100 个小时,降到大约 50 个小时的机器时间。

当然,前提是你的任务和论文的测试条件相近。

八、对普通开发者意味着什么

我觉得,这个项目最值得注意的,不是某一个具体数字,而是它提出的问题。(这一节是我的观点。)

过去两年,推理引擎的主要优化目标,是"短对话、大批量":一个问题,一段回答,尽量同时服务更多人。

agent 的工作方式不一样。

它一次任务要跑很多轮,上下文越积越长,KV cache 成了最先撑不住的地方。

当负载的形状变了,原来围绕稠密注意力设计的系统,就未必是最合适的。

SparseEngine 的选择是:与其在旧房子上不断加盖,不如按新的用途重新盖一栋。

这条路对不对,还需要时间和更多人的使用来检验。

但是它是开源的,代码在 GitHub 上,论文在 arXiv 上,任何人都可以去读、去跑、去验证。

如果你在自己部署模型跑 agent,经常遇到显存不够、上下文被截断的问题,可以关注一下这个项目。

需要提醒的是,它来自学术团队,在生产环境里的稳定性、对各种模型和硬件的支持程度,目前公开信息不多,上线之前最好自己测一测。(这是我的推断和建议。)

总结

用一句话概括。

长程 agent 会把 KV cache 撑爆,稀疏注意力是解法之一,但它很难塞进以稠密分页内存为中心的现有引擎,所以哈工大的 SparseEngine 选择从零开始,按稀疏优先重建服务层,并用 Chain Cache 和可控的前缀缓存修剪,处理"驱逐以后怎么接上"的问题。

论文称效果显著,但这些数字值得你亲自验证。

(完)

来源:arXiv:2609.39068;GitHub CURRENTF/SparseEngine;aicoder.com 报道(2026-10-10)。性能数字均为论文自述;换算与机制理解处为作者推断,正文已标明。