把记忆交给CPU,大模型会变快
真正值得关注的不是量子位这一条动作本身,而是它可能把「大模型」的竞争焦点推向能力、成本与开放生态的再平衡。
原文链接:https://www.qbitai.com/2026/09/489724.html
不过,如果我们把目光从聊天窗口移到背后的数据中心,事情就没那么简单了。
一个Coding Agent改跨十几个文件的bug,需要反复读代码、查资料、跑测试。前几轮交互可能还很顺畅,但任务继续跑下去,系统要处理的历史信息也会越积越多。
当成千上万个Agent同时这样干活,运营方就可能遇到一个头疼的问题:服务器还在跑,能接住的并发却越来越吃紧,有些请求连吐出第一个Token都要等上好一会儿。
模型还是那个模型,服务器也还是那个服务器,问题的根儿啊,其实是出在了 记忆 。
因为大模型每生成一个新的Token,都还要继续用到前文的信息。为了不用每次从头计算,系统会把前面已经算好的中间结果保存起来;会话越聊越长,这份记忆自然也就越堆越厚。
一旦显存装不下,部分缓存被清走,等Agent下一轮又需要这些历史信息时,就可能重新做一遍Prefill。前面明明已经算过的东西,又得花GPU时间再算一次。
尤其是到了Agent时代,AI很少干一问一答的事儿,更多是那种反复需要思考、规划和行动的任务,期间会不断积累会话历史、检索证据、工具结果和中间状态等等。
于是乎,一个过去藏在大模型推理内部、普通用户几乎感知不到的东西,就这样被推到了台面儿上—— KV Cache 。
它的特点,说起来就一个字: 大 。但运营方又不能为了省空间,任由已经算过的内容反复占用GPU重算。所以,长上下文推理要算的这笔账,也就从算力延伸到了存储、搬运和复用。
对于采用因果自注意力的Transformer模型来说,前面处理过的Token,会在注意力层中留下对应的Key和Value。模型生成后续Token时,还能继续使用这些结果。推理系统把它们缓存起来,就有了KV Cache。
你可以把它理解成模型读书时做的笔记。后面再遇到需要联系上文的地方,模型可以调用笔记,省去对已有Token的重复计算。
所以,我们这里说的记忆,指的是 推理过程中留下的中间状态 ,模型的权重并没有因此发生变化。
这份笔记确实能省计算,但它也是实实在在要占地方的。而且,Agent读的东西越多,服务器要替它保存的笔记往往就越厚。
我们拿Qwen3-8B算一笔账。按照它的公开模型配置,在KV Cache采用BF16或FP16、每个数值占2字节的条件下,每个Token对应的KV数据是147456字节,也就是约 147KB 。这还没有计入缓存管理等额外开销。
为什么一个Token会带出这么大一份缓存?因为系统保存的并不是这个Token的文字本身,而是它在多层注意力计算中对应的Key和Value。按这个模型的结构,计算式就是:2份K/V × 36层 × 8个KV头 × 每头128维 × 2字节。
接下来,我们只借用这个每Token开销,做一次百万上下文的容量推演:如果需要缓存100万个Token,对应的KV数据就约为147GB。注意,这里的1M是测算假设,不代表Qwen3-8B实际支持百万上下文;它的官方说明是原生32768 Token,采用YaRN可扩展到131072 Token。
单个请求已经如此,如果把请求规模也放大呢?假设一个服务有300万日活用户,每人每天发出10个请求,而且每个请求都按前面的1M上下文计算,一天就是3000万个请求。
先不考虑压缩和共享复用,按每个请求约147GB全量累加,对应的日累计KV数据规模就是: 300万 × 10 × 147GB ≈ 4410PB 。如果日活再增加到3亿,相同假设下,这个数字还会放大100倍,达到约 441000PB,也就是441EB 。
不过,这里得分清两件事:一天的请求累计涉及多少KV数据,和数据中心同时需要存下多少KV数据,不是一回事。上面是每次请求都独立、全量计数的规模推演,不能直接当作存储采购清单。
实际要配多大的缓存池,运营方还得看高峰时有多少请求同时运行、缓存要留多久、哪些前缀能够共享,以及压缩和淘汰策略。已经复用的同一份缓存,也不该因为被请求多次就重复占一份容量。
当然,不同模型的“笔记本”也不一样。模型层数、KV头数量、缓存精度等都会影响大小,不能只看参数量。上面的数字不是某个服务的真实用量,却能说明运营方为什么要格外关注这份“记忆”:上下文长度和请求规模,会一起把缓存的账越算越大。
而GPU的显存,还要放模型权重和运行时的其他数据。大家共用这么多空间,KV Cache占得越多,系统留给其他请求的余地就可能越小。
这时候,推理系统就得做取舍了:减少同时处理的请求,把部分缓存卸载到其他存储层,或者清理暂时不用的缓存。
再拿前面的Coding Agent来说。它可能正在等工具跑测试,系统趁这个空当,把它的一部分历史缓存清掉了。等测试结果返回,Agent准备接着干活,却发现需要用的缓存已经不在了。
如果其他存储层也没保存这份数据,模型就得重新处理相应的历史输入、重建缓存。这个处理输入的阶段叫 Prefill ,输入越长,通常就越费时。用户等待首个Token的时间,也就是 TTFT ,便可能跟着增加。
算过一遍的内容,过一会儿又得再算。对运营方来说,消耗掉的不只是电和时间,还有这批GPU原本可以用来处理新任务、生成新Token的机会。
这也解释了,为什么KV Cache再大,运营方仍然要认真考虑怎么把它用好。
从成本角度看,GPU应该尽量把资源花在必要的新输入处理和新Token生成上,少为已经处理过、又可以复用的历史内容重复做Prefill。KV Cache保留下来的,正是这部分已有计算的成果。
当然,这不意味着所有缓存都得永久保存。真正要算的是:保留和取回一份缓存,能不能比下次重算更划算?谁能把这笔账算好,谁就更有机会用同一套设备服务更多请求。
聊到这里,你可能已经想到了,显存放不下,难道不能先存到别处,等要用的时候再拿回来?
在服务器里,GPU显存之外还有CPU侧的DDR内存、本地SSD,以及远端存储。它们的容量、速度和成本各不相同,正好可以用来存放不同活跃程度的缓存。
例如眼下正在生成回答,需要频繁访问的数据,就留在GPU的高带宽显存HBM里;短时间内可能继续用到的缓存,可以先放进CPU侧的DDR内存;至于更久没有访问、但还值得保留的历史缓存,则可以继续下沉到SSD或远端存储。
再聚焦到Coding Agent的任务里,就是它写代码时,相关缓存尽量留在GPU侧;任务暂停后,系统可以把缓存转存到内存;如果这段会话很久没继续,再考虑把数据移到更下一层。用户回来后,系统根据缓存命中情况,把需要的部分取回来。
对运营方来说,这样安排的直接好处是:显存不用一直替所有历史会话占着位置,腾出的空间可以交给正在运行的请求。
不过,把东西搬出去只是第一步。哪些数据可以搬、应该放在哪里、什么时候得提前取回来,总得有个地方统一管理。
推理服务运行在主机侧的管理逻辑,需要跟踪会话状态、剩余容量和缓存访问情况。CPU连接的大容量内存和存储,也为显存之外的缓存池提供了基础。系统可以结合这些信息,决定一份KV Cache接下来该留在哪一层。
这类机制其实已经出现在一些推理框架里了。例如,vLLM的KV Offloading支持将缓存块卸载到CPU内存,还可以配置次级存储层。在它描述的多层方案里,次级存储与GPU之间的数据传输,会经过CPU侧的缓存层。
毕竟,DDR、SSD和远端存储的访问条件各不相同。假如取回缓存比重新计算还费时,用户还是得等,甚至可能等得更久。所以,系统需要根据访问频率和传输开销安排缓存,不能一股脑地把数据全塞到硬盘里。
要减少搬运量,另一个办法就是压缩。数据变小了,同样的空间能存得更多,传输时要搬的字节也更少。
可压缩也不是白来的,压缩和解压都要花时间,如果全让通用CPU核心来干,又可能挤占请求调度等工作需要的资源。