开家高级餐厅,前几桌客人下单秒出餐。可人一多,每桌都点了复杂套餐,厨房就开始卡顿。这不是厨师手慢,而是料理台的备餐盘在捣乱。为了盯住每桌订单,厨师给每张桌子预留了一整套巨型托盘,不管客人是点12道菜的品鉴套餐,还是只要一杯白水,这套盘子都先占上。大部分托盘空着,却把操作台塞得满满当当,新订单根本没法开工。
大语言模型跑线上服务时,这套“空盘子堵路”的毛病直接反映在首词延迟上。换成千万用户的真实产品,多卡半秒,体验就崩了。要搞懂修法,得先看看推理时大模型到底怎么“想”的。
![]()
打出一段长提示音,按回车,系统立刻进入预填充阶段。整个输入在模型里被加工成一次数学表征,这一步吃的是算力,全看纯计算快不快。紧接着进入解码阶段。大模型是自回归的——一个字一个字往外蹦——每吐出一个新词,都得回头翻看之前所有已生成的上下文,才能决定下一个词该是谁。这一步的瓶颈,不在算力,在显存。
为避免每生成一个新词都把整场对话重新算一遍,大家用上了KV缓存。它把之前词元的“键”和“值”暂存在GPU显存里。过去的做法是:根据模型最大上下文长度预留一整段连续显存。假设上限是2048个词元,就算你只打了句“你好”,也先划出2048份空间等着。这就造成两类碎片:块内浪费的内部碎片,以及新请求搜遍显存都找不出一大块连续空位的外部碎片。一张GPU能同时服务的用户数,就这样被按得死死的。
PagedAttention的解法像给图书馆档案馆换了一套索引系统。以前是给每位研究员发一套10卷本的大活页夹,里面插满空白页,让他们按顺序填。现在是每人只发一份目录。研究员不断找到新资料,管理员就递给他一张标准尺寸的索引卡片,随手塞进柜子里任意一个空槽。研究员压根不用管卡片物理上放在哪儿,他只看目录就能翻到想要的那页。
这个比喻里,活页夹就是连续预留的显存,目录就是页表,索引卡片就是非连续存储的KV缓存块。显存碎片问题一下子被打散了:原本因为预先划出2048份大块而堆满的空盘子,现在化整为零,哪儿有空塞哪儿。因为不再需要为大段空白连续空间发愁,一张GPU能同时招待的请求量立刻翻着跟头往上涨,首词延迟也降了下来。
这里藏着一个小细节。为什么这个东西叫“PagedAttention”,而不叫“Paged Allocation”?表面上看它确实是在搞显存分配,但真正改名的是注意力机制的寻址方式。在标准Transformer里,注意力核会默认KV缓存是一整条连续张量,像一卷展开的长卷轴。PagedAttention直接出手改了注意力核,允许它在不连续的内存块之间“跳跃”着抓取数据。它不是简单把数据搬来搬去,而是改变了模型“查阅”自己记忆笔记的方式。
回到餐厅。过去厨房每桌留一整套餐具,不管点不点菜都占着。现在改成每道菜用一张流动卡片记录,厨师看一眼目录就知道菜序,出餐盘按需取用,用完收回。整个厨房的吞吐量一下就松快了。GPU显存有限,但用这种分页式的“目录卡片”周转,那些被空盘子浪费的显存又重新流动起来,把被碎片卡住的推理速度重新还给用户。对大模型服务而言,这不止是技术上的内存管理优化,更是一条让昂贵算力真正跑满的商业捷径。
特别声明:以上内容(如有图片或视频亦包括在内)为自媒体平台“网易号”用户上传并发布,本平台仅提供信息存储服务。
Notice: The content above (including the pictures and videos if any) is uploaded and posted by a user of NetEase Hao, which is a social media platform and only provides information storage services.