摘要:现在的大模型市场,热闹得像个集市。就拿Hugging Face来说,上面挂着超过一百万个模型。大公司训的大模型,小团队微调的行业模型,应有尽有。
阿里云把1192块英伟达H20 GPU砍到了213块,足足省了82%的资源,而且服务质量不降反升。
他们靠的是一个叫“Aegaeon”的自研计算池化方案。
这套东西被计算机系统领域的顶级学术会议SOSP(操作系统原理研讨会)2025收录了。
SOSP这会议,说是操作系统界的“奥斯卡”也不为过,每年只收几十篇论文,含金量极高。
大模型推理的GPU空置危机
现在的大模型市场,热闹得像个集市。就拿Hugging Face来说,上面挂着超过一百万个模型。大公司训的大模型,小团队微调的行业模型,应有尽有。
繁荣之下,是效率的巨大黑洞。
用大模型推理,分两步:预填充(prefill)和解码(decoding)。用户扔过来一个问题,模型先“预填充”,把问题里的每个字都过一遍。接着进入“解码”阶段,每次只处理上一步生成的新字,一个接一个往外蹦,直到说完或者达到长度限制。
这个过程中,会产生一种叫KV缓存的中间状态,存起来给后面解码用,不用重复计算。
评估服务快慢,也有两个指标:TTFT(Time-To-First-Token),就是你看到第一个字要等多久;TBT(Time-Between-Tokens),就是后面每个字蹦出来的间隔。这两个指标共同构成了服务的SLO(服务级别目标)。
在真实世界里的模型调用,根本不像实验室里那么规整。
大量模型部署后,模型调用极不均衡。绝大多数模型仅接收极少数请求。这意味着,大量GPU都在服务那些偶尔才有人用的“冷”模型,大部分时间都在空转。
就算是最火的“热门”模型,也躲不过请求量的潮汐。流量一来,像洪水猛兽,瞬间冲垮预留的资源。为了应对这种突发流量,就得多备GPU,可流量一退,这些GPU又闲置了。还是烧钱。
为了让GPU忙起来,业界想了两种办法:多路复用(multiplexing)和自动扩展(auto-scaling)。
多路复用,就是想办法在一块GPU上塞进多个模型。但这有个硬伤:GPU的显存是有限的。一块80GB显存的英伟达A100,撑死塞进两个140亿参数的模型。实际场景里,模型平均大小25.1GB,一块GPU上能跑两三个模型就顶天了。池化程度太低,还是救不了利用率。
自动扩展,听起来更灵活。模型不用就从GPU上拿下来,要用的时候再加载上去。平时可以放在主机内存或者SSD(固态硬盘)里。听着很美。
但现有方案有个根本缺陷:它们是以“请求”为单位进行扩展的。
一个LLM请求的执行时间很长。这就导致,哪怕模型调用很稀疏,也总有很大一部分模型处于“活动”状态,因为总有那么一两个请求在它上面跑着。数据统计,100个模型,哪怕总请求到达率只有每秒3.7个,平均也有46.55个模型是“活动”的。
当所有GPU都被这些“活动”模型占着时,一个新的请求来了,想调用一个不在GPU上的模型怎么办?只能等。等某个GPU上的请求跑完,把那个“活动”模型缩减掉,腾出地方来,新模型才能上。
这就是队头(HOL)阻塞。这种等待,对于用户来说是灾难性的延迟,严重违反SLO。所以,为了保证服务质量,你还是得保留比活动模型数量更多的GPU。绕了一圈,又回到了原点,池化效率依然低下。
Aegaeon看透了这一点,它的解法很简单:别按“请求”来,我们按“令牌”来。
Aegaeon用令牌级调度破局
请求级的扩展,就像飞机,必须等一整机人都下完了,下一批人才能上。Aegaeon的令牌级扩展,则像地铁,到站就开门,上下同步进行,效率极高。
具体来说,Aegaeon可以抢占一个正在运行模型的解码任务,把它“缩减”掉,为新来的请求“扩展”出它需要的模型。跑几个令牌,再换下一个。通过这种极高频的切换,实现了真正的资源共享。
Aegaeon的系统架构里,代理层负责分发请求,可以把不同模型的请求发到同一个实例上。实例里的令牌级调度器是核心大脑,它决定了下一个生成令牌的任务属于哪个请求,以及是否需要抢占和切换模型。
这个想法很性感,但实现起来有两大挑战。
第一个挑战是调度。细到令牌这个粒度,决策空间变得异常复杂。调度器得不停地决定,从一堆运行中的请求里,下一个令牌该给谁生成?要不要切换模型?每个令牌的执行时间、截止时间都不同,切换模型还有开销。决策一旦失误,SLO就可能保不住。
第二个挑战是成本。令牌级的切换意味着自动扩展必须快,非常快。现有的方案优化的是“从无到有”的冷启动,而Aegaeon面对的是连续不断的“缩减”再“扩展”,中间还得传来传去KV缓存。如果这个过程慢得像蜗牛,令牌级调度就成了空谈。一个130亿参数的模型,未经优化的切换过程要几十秒,这绝对无法接受。
Aegaeon用两套组合拳解决了这两个问题。
调度的手术刀, 精准到令牌
面对复杂的令牌级调度,Aegaeon的第一刀,是把预填充和解码两个阶段彻底分开。
如果混在一起调度,很容易顾此失彼。你优先保证预填充,那么当一大波请求同时涌入时,正在解码的请求就会被饿死,TBT会飙升。你优先保证解码,那要是某个请求的回答特别长,新来的请求就得一直等着,TTFT又会爆掉。
Aegaeon的做法是,把GPU池分成两个区:预填充区和解码区。请求来了,先进预填充区完成第一步,然后带着生成的KV缓存,再去解码区排队。各行其道,互不干扰。
在预填充区,Aegaeon采用分组调度策略。因为预填充阶段的自动扩展开销,和执行一次预填充任务的时间差不多。比如扩展一个130亿参数模型要0.8秒,跑一批预填充也差不多是这个时间量级。频繁切换得不偿失。
所以,Aegaeon会把相同模型的请求打包成一个“组”,尽量让一个模型在GPU上多待一会儿,处理完一组请求再走。这样既减少了切换次数,又通过先来先服务的总体顺序避免了饥饿。
到了解码区,调度策略就完全不同了。
解码任务有个特性:输出的令牌可以先在缓冲区里存一下。比如要求的TBT是100毫秒,而GPU生成一个令牌只要20毫秒,那中间就有80毫秒的“松弛时间”。Aegaeon就利用这点时间,去服务其他模型的解码请求。
Aegaeon设计了一套加权轮询方案。每个解码实例上,都有一张工作列表,列表里是不同模型的请求批次。系统会进入一轮一轮(round)的循环。每一轮开始时,Aegaeon会根据一套公式,给每个批次分配一个时间配额,比如模型A的请求解码3秒,模型B的解码2秒。
其中n_k = d/t_k,c是工作列表中所有模型的自动扩展开销总和,而
是轮次估计SLO达成率的倒数。
这套公式的核心思想是,精确计算每个模型能“忍受”多长的等待时间,然后把这个等待时间变成服务其他模型的时间片。通过这种精密的计算,保证在轮流服务多个模型的同时,每个模型的TBT都恰好达标,既不浪费时间,也不违反SLO。
调度问题解决了,下一个就是如何把切换模型的成本降到最低。
把27秒的切换压缩到1秒以内
未经优化的抢占式自动扩展,慢得令人发指。
一个默认的流程是这样的:旧模型的最后一个推理步骤跑完,得先把它的KV缓存全部保存到主机内存。然后,启动新实例,先进行垃圾回收,释放显存,再重新初始化推理引擎,加载新模型权重,最后再把新作业的KV缓存加载回显存。一套下来,一个130亿参数的模型,耗时26.9秒。这在令牌级调度场景里,完全是天方夜谭。
Aegaeon对这个过程进行了庖丁解牛般的优化。
第一招,组件重用。
推理引擎复杂,初始化分布式执行器(比如Ray和NCCL)要几十秒,分析和优化要几秒,加载模型权重又要几秒。Aegaeon发现,这里面大部分组件,比如分布式执行器、调度器,其实是通用的,根本没必要每次都重新初始化。
Aegaeon的做法是,每个实例只完整初始化一次推理引擎。之后切换模型,只换掉那些跟模型强相关的部分,比如模型权重和KV缓存。其他所有组件都缓存起来重复使用。这一下,就把80%以上的延迟给砍掉了。
第二招,显式内存管理。
抢占式扩展的另一个痛点是内存碎片。在GPU上,频繁加载卸载模型权重,很容易产生显存碎片,导致后面想分配一块大内存时失败,必须得花几秒钟进行垃圾回收。在主机内存DRAM(动态随机存取存储器)里也一样,不同模型的KV缓存形状千奇百怪,胡乱堆放很快就会把内存搞得一团糟。
Aegaeon选择自己动手,丰衣足食。
它在GPU上划出一大块自管理VRAM缓冲区,专门用来放模型权重和KV缓存。分配和释放都用最简单的指针移动,瞬间完成,彻底绕开了张量库(比如PyTorch)自带的、慢吞吞的内存分配器,也就告别了垃圾回收。
为了加速模型加载,Aegaeon在主机内存里也建了个模型缓存区。加载模型时,直接从这个缓存区通过专用的暂存缓冲区,以多线程、流水线的方式拷到GPU上,把PCIe(高速计算机扩展总线标准)带宽吃满。一个130亿参数的模型,加载时间不到一秒。
Aegaeon甚至还能预取。在解码区,调度器知道下一轮要调度哪个模型,就可以提前在后台把那个模型的权重预取到GPU上。等真正轮到它的时候,只需要一个廉价的设备内复制,几乎是零开销切换。
对于形状各异的KV缓存,Aegaeon借鉴了经典的slab分配机制。它把内存区域划分成大小固定的块(slab),每个slab只存放一种特定形状的KV缓存。这样既避免了碎片,又提高了内存利用率。
第三招,细粒度KV缓存同步。
优化的最后一步,是让KV缓存的传输(从CPU到GPU,或反之)和推理计算完全并行起来。
这事说起来容易,做起来难,因为存在数据依赖。你不能在一个请求的KV缓存还没完全传到GPU上时,就开始用它推理。也不能在前一个模型的KV缓存还没传输出去时,就把那块内存分配给新模型。
Aegaeon的解法是,用CUDA事件给每个KV缓存块打上精细的标记。
它为每个KV缓存块维护了三个事件:最后访问时间、最后写入时间、最后交换操作时间。通过查询这些事件的状态,Aegaeon可以精确地知道每一小块数据在任何时刻的状态,从而安全地实现异步传输和计算的重叠。还有一个守护线程专门负责这些异步传输任务,整个数据通路像一个被精确指挥的交响乐团,高效且不出错。
三招下来,Aegaeon把自动扩展的延迟做到了极致。
在阿里云模型市场的Beta部署中,Aegaeon服务集群包含213块H20 GPU,为28个1.8–7B模型(TP=1)和19个32–72B模型(TP=4)提供服务。
为支持这种混合并行模式,集群中部署了多个Aegaeon实例,每种并行配置对应一个实例。请求到达率在0.01到1.13之间波动,平均值为0.037。这些模型原本需要总共1192块H20 GPU来提供服务,这表明(使用Aegaeon后)资源节省了82%。
Aegaeon真正的杀手锏,是它超高的模型并发度。
当RPS为0.1时,Aegaeon的有效吞吐量是ServerlessLLM的2倍。值得注意的是,Aegaeon仅用10个解码实例就能支持多达70个模型,每个GPU可高效服务7个模型。
Aegaeon的成功,代表了一种趋势:AI的发展,越来越需要底层系统软件的深度创新和优化。
当上层应用狂飙突进时,真正决定其效率和成本边界的,是这些看不见的底层功夫。
参考资料:
来源:算泥社区
