@charles_irl: 推理并非一切,但它确实需要一个新的技术栈——不是 Kubernetes,也不是 SLURM。在 @modal,我们深入探索构建…
摘要
Modal 工程师详细介绍了他们实现真正无服务器 GPU 用于 AI 推理的方法,结合了云缓冲区、自定义内容寻址文件系统以及 CPU/GPU 检查点/恢复,从而在几十秒内(而不是几分钟)扩展副本。
查看缓存全文
缓存时间: 2026/05/12 16:54
推理并非一切,但它确实需要一套全新的技术栈——不是Kubernetes,也不是SLURM。
在@modal,我们深入钻研,构建了这套技术栈。
本文中,我们将解释具体做法,涵盖计算管理与云原生缓存,到CRIU与GPU检查点恢复。
https://t.co/DQ4wvuXjre https://t.co/iF0ZYJQWFL
如何实现真正无服务器的GPU
来源:https://modal.com/blog/truly-serverless-gpus 图表:在基础云系统与Modal上启动推理服务器的延迟对比
我们正处于推理时代。百亿到万亿参数的神经网络在专用加速器上以每秒千万亿次运算的速度运行,用于大规模生成媒体(https://modal.com/blog/runway-chooses-modal-to-power-real-time-inference-for-runway-characters)、编写软件(https://modal.com/blog/lovable-case-study)以及折叠蛋白质(https://modal.com/blog/seamless-computational-bio-at-chai-discovery)。
推理工作负载比之前占主导的训练工作负载更加多变和不可预测。这使得它们自然而然地适合无服务器计算——在这种范式中,应用程序在(虚拟)机器之上定义,从而能更灵活地扩缩容以应对负载变化。
但无服务器计算只有在新的副本能够快速启动时才有效——快到足以跟得上需求的变化,而需求变化可能以秒计。如果天真地启动一个新实例(例如,SGLang在B200上服务于一个百亿参数大模型),可能需要数十分钟,甚至因GPU不可用而停滞数小时。
在Modal,我们在过去五年中进行了深度工程攻关来解决这个问题。本文中,我们将详细介绍我们的做法。
关键要素有四个:
- 云缓冲池:维护一小批健康、空闲的GPU,以承接新负载
- 自定义文件系统:从内容寻址、多层云原生缓存中懒加载容器镜像
- 检查点/恢复:通过直接恢复进程到内存,快速跳过CPU侧的初始化
- CUDA检查点/恢复:通过直接恢复CUDA上下文到内存,快速跳过GPU侧的初始化
这四个要素共同将AI推理服务器副本的扩缩容时间从数千米秒降低到仅数十秒。
我们在此过程中分享了部分成果(https://www.youtube.com/watch?v=3jJ1GhGkLY0)和片段(https://modal.com/blog/jono-containers-talk),因为我们相信保密不是好的护城河。而且如果更多人学会如何高效使用GPU,市场上就会有更多GPU可供我们使用!
但这篇文章是我们首次将所有内容整合在一起。我们希望它能说服你值得采用我们的系统(https://modal.com/signup)——或者加入我们(https://modal.jobs/)来共同构建它。
为什么要在乎无服务器GPU?为了最大化推理工作负载的GPU分配利用率。
首先,让我们明确问题。GPU昂贵且稀缺,因此我们希望最大化它们的利用率(https://modal.com/blog/gpu-utilization-guide)。这里“利用率”是一个无量纲量:
利用率 := 实际产出 ÷ 付费容量
衡量利用率的方式很多——即如何定义产出和容量。其中最复杂、最严格的大概是“模型FLOPS利用率(MFU)”,它将原始算法操作需求除以聚合算术带宽。
这对工程师来说极具吸引力。它对于大型训练的“冠军运行”也尤为关键,因此吸引了大量投资和关注,例如最近 everyone都在批评xAI约10%的MFU(https://x.com/theinformation/status/2050606311440531809?s=20)。
但在技术栈的另一端,有一种更基本的利用率形式,它破坏了推理工作负载中实际产出与分配容量之间的关系,那就是GPU分配利用率:
GPU分配利用率 := 运行应用程序代码的GPU秒数 ÷ 付费的GPU秒数
关于“GPU利用率“术语的说明nvidia-smi及类似工具报告的“GPU利用率“介于这两种极端之间。它报告的是内核代码在GPU上运行的时间比例——字面意思就是CUDA流在GPU上运行的时间比例。更多信息请阅读此处(https://modal.com/blog/gpu-utilization-guide)。
推理应用的规模变化很大。与训练不同,容量需求不在工程组织的直接控制和管理之下。相反,它由外部用户行为驱动——由市场、社交媒体算法或产品团队驱动。
下面是一个基于时变泊松过程的每分钟请求量示例轨迹,我们用它来建模推理应用。注意不仅存在季节性变化(每日周期),还有需求波动随平均需求增加而增大的长期趋势。
显示模拟推理流量的图表,来自具有季节性变化和尖峰的时变泊松过程
尖峰需求引发了严重的工程问题。借用AWS的Marc Brooker的话(https://brooker.co.za/blog/2023/03/23/economics.html):“系统的成本与其(短期)峰值流量成正比,但对于大多数应用,系统产生的价值与(长期)平均流量成正比。”尖峰需求意味着高峰均比,这对系统经济性构成挑战。
具体来说,设想一下此类应用的容量规划。你的需求(以在延迟目标内服务请求所需的GPU数量衡量)可能如下所示:
使用固定的、过度配置的GPU分配,利用率低
为了妥善服务预期负载,你分配(上架、在超大规模云上租赁)140个GPU。但这些GPU大多时间处于空闲状态——GPU分配利用率很低。
你可能认为我们在自卖自夸。但指出这一点的并非只有我们!请看Hebbia的精彩博文(https://www.hebbia.com/blog/the-hidden-economics-of-llm-inference)。而且我们有数据支持,绝非空谈:根据2024年《AI基础设施规模化状态》报告(https://ai-infrastructure.org/the-state-of-ai-infrastructure-at-scale-2024/),大多数组织在峰值需求运行时GPU分配利用率低于70%。实际的GPU分配利用率通常只有10-20%。
使用固定分配时,在意外尖峰期间需求还可能超过供给。试图预测尖峰只会进一步增加成本——而增加的收入则有限。
无服务器GPU难在何处?启动延迟。
直接的解决方案是配置自动扩缩容容量:当需求增加时,增加供应。
如果天真地实现,这实际上会加剧问题:
如果分配缓慢,利用率和QoS都会受损
不经优化,从超大规模云API请求到运行中的服务副本可能需要数十分钟。
你需要完成以下步骤:
- 启动新实例并进行健康检查(数分钟到数十分钟)
- 加载应用程序和文件系统状态(数分钟)
- 在主机上启动应用程序,使其准备好服务请求(数十秒)
- 在设备上启动应用程序,使其准备好服务请求(数分钟到数十分钟)
在这段时间内,负载超过容量,QoS通常会下降(表现为更高的并发或队列,从而导致尾部延迟膨胀,甚至出现503)。这意味着用户不满。如果容量上线太慢,甚至可能错过瞬时尖峰。而且由于需求不可预测以及分配困难,这些容量通常会闲置相当长一段时间。
在Modal(https://modal.com/),我们将推理应用在GPU上的启动时间从数十分钟优化到了几秒或几十秒。通过这些优化,各种GPU推理应用都可以“真正无服务器地”运行:供应量紧密匹配系统需求。
通过快速、自动的分配,利用率和QoS都可以很高
在本文剩余部分,我们将解释我们采取的工程方法以及针对上述四个步骤实现的性能优化,这些优化涵盖了从云存储系统和机器管理到本地磁盘、CPU,当然还有GPU的整个技术栈。
这些优化共同使Modal上的推理启动速度提升了40倍:从2000秒缩短到50秒。
图表:在基础云系统与Modal上启动推理服务器的延迟对比在基础云系统上启动推理服务器需要超过2000秒,而在Modal上只需约50秒。实现这一加速的关键架构优化已按目标系统组件进行颜色编码——GPU与GPU内存、CPU与CPU内存、本地固态硬盘(SSD)、机器/实例管理。本文后续将沿用此配色方案和示意图。
通过将实例分配和健康检查移出关键路径,你可以减少数十分钟的延迟。
考虑副本启动的第一步:
- 启动新实例并进行健康检查(数分钟到数十分钟)
我们可以通过提前完成这一步来将其移出关键路径:运行一个由多个应用共享的空闲、健康GPU缓冲池,将新副本调度到这些单元上,并异步地将新设备加入缓冲池。当缓冲池过大时,我们还可以在副本缩减时取消分配单元。管理这个缓冲池是一个有趣的线性规划问题,我们已在此处(https://modal.com/blog/resource-solver)写过。
在已分配的机器之上维护一小批准备好但未使用的机器,可以快速将新副本调度到空闲机器上(以亮色表示)。从缓冲池服务请求可将副本启动时间减少数十分钟。
图表:显示通过云实例缓冲池减少数十分钟推理启动延迟。
关于系统和应用层缓冲池的说明如果你运行的是单一工作负载而非多工作负载系统,你可能会问为什么只将实例分配移出“关键路径”放入缓冲池。难道不能将更多设置工作移入缓冲池吗?可以!Modal用户可以通过buffer_containers(https://modal.com/docs/guide/cold-start#run-more-warm-containers)维护应用层的就绪副本缓冲池。但即便如此,吸收给定大小尖峰所需的缓冲池规模与创建新副本的速度成正比,因此下文描述的优化对于单一工作负载系统仍然很重要。
运行缓冲池会将峰值分配利用率限制在100%以下。这是一个合理的权衡,因为100%的利用率通常是一种幻象。考虑一下,当CPU或IOPS等其他资源利用率过高时,惯常做法是启动新副本甚至通知工程师。
这对鲁棒性很重要。100%利用率的系统没有容错空间,因此故障通常会变成灾难。我们可以亲自建议你在生活中增加更多缓冲池——卫生间里多备一把牙刷;在办公室、家中和随身携带的包里都放上关键设备的充电器。
这个缓冲池对于在单个系统上容纳更多种类的工作负载尤其有用。在Modal,我们倾向于(https://modal.com/blog/agents-devex)支持多种“开发”工作负载,而不仅仅是生产服务,因为我们可以快速创建新的开发环境。另一个好处是,这些环境默认是可复现的,并且运行在生产就绪的基础设施上。缩小与生产基础设施的差距也有助于提高开发速度。
当然,细节决定成败。一个关键点:健康检查对于GPU至关重要,GPU的故障率远高于其他硬件,包括声名狼藉的易损组件如机械硬盘。我们在此处(https://modal.com/blog/gpu-health)详细介绍了我们的GPU健康检查系统。概括来说,根据我们的经验,你需要在启动时运行一次短时间的主动健康检查,并持续监控后续出现的健康问题(https://modal.com/docs/guide/gpu-health),但可以将更密集的检查(如dcgmi diag)推迟到较慢的频率(对我们来说是每周)。
按(匿名)云服务商分组的每GPU每小时关键级别Xid错误(https://modal.com/docs/guide/gpu-health)。故障率远非可以忽略不计!
通过从内容寻址缓存中懒加载文件,可以将容器启动时间从几分钟缩短到几秒。
现在来看下一步:
- 加载应用程序和文件系统状态(数分钟)
在当代实践中,这通常意味着启动一个或多个容器或虚拟机。
大致来说,容器是支持一个进程并带有权限限制的根文件系统。对于许多容器的分布式部署,性能瓶颈在于在工作实例上构建根文件系统。
操作系统发行版的根文件系统非常庞大——包含数万个文件,大小达GB。天真地使用docker run等命令,你需要加载整个文件系统,通常以云以太网支持的几GB/s速度传输。更糟糕的是,容器镜像被分成多个层,必须顺序应用。
解决方案是将容器启动器(Docker的runc,gVisor的runsc)与容器镜像交付分离。我们使用一个自定义文件系统,称为ImageFS,基于libfuse构建,它结合了懒加载与多层内容寻址缓存,旨在匹配云服务商的特性。
我们在自定义文件系统中实现的快速容器启动的关键“技巧”是明智地偷懒(正如所有优秀工程师所做的那样)。容器镜像包含许多文件,比如世界上所有时区和区域设置信息,大多数应用程序永远不会读取它们。你可以在容器启动前跳过加载整个文件系统,而只需在启动时阻塞加载元数据(索引)。元数据只有几MB,因此可以在100ms内加载完毕,同时加载启动容器所需的其他所有内容。
图表:显示在启动过程中同时懒加载容器文件系统内容
其余内容可以与其他工作同时加载——或者根本不加载!大多数文件永远不会被读取,如下面由USENIX FAST ’16的Slacker论文(https://www.usenix.org/conference/fast16/technical-sessions/presentation/harter)中的图5所示。
我们目前使用libfuse(https://github.com/libfuse/libfuse)实现这个文件系统。它是一个用于在用户空间编写Linux文件系统的库。内核在一个使用标准系统调用访问文件的用户空间程序与另一个实现新文件系统的程序之间进行中介(最终,新文件系统有自己的系统调用,其中一个最终通过内核返回到原始程序)。与在内核模块中实现自定义文件系统相比,这样做更易于构建和分发。
图表:显示在启动过程中同时懒加载容器文件系统内容
这是有代价的:用户空间和内核空间之间的上下文切换次数翻倍。这对于延迟敏感的工作负载(如从终端字符设备读取)可能会很痛苦,但对于我们使用它的吞吐密集工作负载,影响较小。有关性能影响的详细分析,请参阅USENIX FAST ’17的To FUSE or Not to FUSE(https://www.usenix.org/conference/fast17/te
相似文章
@bastani_behnam:我们刚刚发布了如何在 27B 模型上解锁 +50% 推理容量——无需新 GPU、无需新节点,成本仅为一小部分……
OpenInfer 展示“垂直拆解”,通过单节点 AMD EPYC CPU 与 Nvidia L40S GPU 协同执行量化层,并配合自定义 SLA 感知调度器,将 Qwen 3.5 27B 的吞吐量提升约 50%。
推理的变革(阅读时长约 8 分钟)
本文分析了 Cerebras 即将进行的 IPO,将其视为 AI 硬件领域“推理变革”的信号。文章指出,尽管 Nvidia 在基于 GPU 的训练领域占据主导地位,但为了支持推理工作负载,AI 算力的未来正变得越来越异构。
@Modular:HTTP路由问题已经解决了多年。然后大语言模型出现了。它们的后端不是可互换的…
Modular发布了一篇博客文章,解释为什么传统的HTTP路由不适用于LLM推理工作负载。文章描述了他们如何在其分布式推理框架中处理有状态的异构GPU pod(包括KV缓存、专用的预填充/解码后端以及对话级路由),这些是传统无状态路由算法无法解决的。
@modal: @vllm_project 和 @sgl_project 服务器在 Modal 上的新副本启动速度提升 3-10 倍。阅读文章了解具体实现方式 ——…
Modal 宣布,通过优化 GPU 健康管理和 CUDA 上下文检查点机制,vLLM 和 SGLang 服务器副本的启动速度提升了 3-10 倍。
AI推理遵循着截然不同的规则(9分钟阅读)
文章指出AI推理对云数据基础设施提出了独特挑战,其需求更接近高并发OLTP系统,而非传统面向人类速度的应用。文章强调需要优化存储和数据访问层,以应对自主智能体驱动的"AI数据海啸"。