动机与简介
在整个行业中,负责训练和部署大型 AI 模型的团队在有限的计算容量下正面临严苛的投资回报率(ROI)目标。随着工作负载的扩展,提升基础设施效率变得愈发困难,因为端到端的运行时间中,除了“实际训练”之外的开销(如初始化、编排、检查点保存、重试、故障和恢复)所占比例越来越大。
Meta 利用有效训练时间(Effective Training Time, ETT%)来量化效率,将其定义为端到端(E2E)总挂钟时间中用于高效训练的百分比。该指标直接指向时间浪费的领域,从而有助于确定效率改进的优先级。
在这一工作流程中,尽管是基于 Meta 使用 PyTorch 进行模型训练的生产经验,我们仍希望分享广泛适用的经验教训:一些改进已在开源中实现——例如 TorchRec 分片计划的改进,以及减少编译时间和重编译的 PyTorch 2 (PT2) 编译优化;而其他一些改进(如检查点和模型发布)则更具 Meta 的特定背景,但它们解决了通用的行业瓶颈,可以在其他地方进行调整应用。
有效训练时间的定义
有效训练时间(ETT%)定义为 E2E 挂钟时间中用于处理新数据的百分比。由于端到端的挂钟时间取决于模型架构、复杂度、训练数据量等多种因素,因此很难直接测量 ETT%。相反,我们重点关注测量闲置和故障,这可以通过以下公式表示:

该公式的直观视图如下,包含三个 L1 子指标:
- 启动时间(Time to Start):从作业分配到硬件资源,到开始训练第一批数据之间的时间段。
- 恢复时间(Time to Recover):训练作业在发生故障或中断后,重启并恢复高效训练所需的时间。
- 故障次数(Number of Failures):指训练作业生命周期内发生的基础设施相关中断或失败尝试的总次数。
启动时间和恢复时间用于从系统优化角度衡量每次尝试的闲置情况,而故障次数则旨在从可靠性角度衡量各种类型的故障。

图 1. 训练周期概述
其中这些 L2 区域的定义为:
- 调度时间(Scheduling Time):在有可用资源时,基础设施为调度训练作业所花费的时间。
- 硬件设置时间(Hardware Setup Time):在硬件上启动加载器/训练器二进制文件所花费的时间。
- 加载器初始化时间(Launcher Init Time):启动加载器以进入 PT2 编译阶段的时间。
- PT2 编译时间(PT2 Compilation Time):在开始消耗训练数据之前,应用 PT2 编译以优化训练模型的时间。
- 有效训练时间(Effective Training Time):在训练数据上进行训练的时间。
- 浪费的训练时间(Wasted Training Time):训练循环内但未处理新训练数据的时间,例如重复训练样本、阻塞训练时间等。
- 关闭时间(Shutdown Time):停止训练作业所需的时间。
Meta 提升 ETT% 的历程
从 2024 年下半年开始,我们一直在积极分析整个机群的有效训练时间(ETT)。这项工作旨在确定 ETT% 的状态、明确关键关注领域并实施改进措施。
过去几年中,我们开发了 40 多项新技术以提高整体 ETT%。下图简要展示了每个主要领域在启动时间方面的改进:

图 2. 各项技术对启动时间的改进
通过团队的集中努力,我们在 2025 年底达成了一个重要里程碑,成功将离线训练的有效训练时间(ETT%)提高到 >90%。
技术深度剖析
团队对促成有效训练时间(ETT%)的每个环节进行了详细分析,并主要集中在以下举措的优化上:
- 启动和恢复时间: 优化了训练器初始化和 PT2 编译,以降低与启动时间和恢复时间指标相关的训练成本。
- 检查点管理: 改进了检查点流程,以最小化训练期间的闲置并减少未保存的训练时间。
- 关闭时间优化: 切换为使用 CPU 机器而非 GPU 进行推理模型发布,从而节省了作业关闭时间的 GPU 小时数。
- 故障减少与可观测性: 与合作伙伴团队协作以缩短调度时间并提高抢占作业比例,建立了组件级的可观测性,并细化了训练器错误的分类,以减少故障频率。
训练器初始化优化
图 3. 训练器初始化概述
训练器初始化包括多个子阶段:device_init、process_group_init、preproc_creation、train_module_creation、init_plugins、pre_train 和 get_first_batch_data。
从 2024 年开始,我们专注于多项旨在最小化训练器初始化时间的举措。我们应用的主要方法是:
- 通信优化:删除各等级(rank)之间不必要的创建或通信,以减少开销成本。
- 流水线优化:对于独立的流程,让子阶段并行运行以重叠执行,从而最大限度地利用时间。
通信优化
在该工作流程之前,每个作业初始化时都会产生大量不必要的进程组创建和各等级间非最优的通信,这些共同导致了训练初始化时间的增加。
例如,团队实施了一项优化,不再依赖大量的 all_gather 调用来逐段构建分片元数据(这种方法在分片过程中造成了巨大开销)。现在,每个等级使用分片计划广播后本地已有的元数据来构建其对应的全局等级部分。这一改变显著提升了分片时间。
图 4. 通信优化概述
流水线优化
训练器初始化中的许多子阶段之间没有依赖关系,这为创建独立进程来运行这些子阶段并使其相互重叠提供了空间。
例如,PT2 编译和 DPP 预热(我们用于获取训练数据的流程)是获取第一批数据之前代价昂贵且耗时的步骤。目前,PT2 编译被延迟,因为它只能在第一批真实数据可用于编译过程时才能开始。
为了提高该流程的效率,我们引入了新技术,使用快速批处理(fast batch)快速获取数据,这使得 PT2 能够在 DPP 仍在获取第一批数据时就开始编译。
图 5. PT2 编译与 DPP 预热并行化
这项新技术对于大型模型(如基础模型)最有益,因为它们的数据加载过程比其他类型的模型耗时得多。
PT 2.0 编译优化
PyTorch 2.0 (PT2) 编译时间是团队投入的另一个重要领域。我们主要通过以下 3 种方法来减少冗长的 PT2 编译时间:
- 减少不必要的重编译
- 提高 PT2 的整体缓存命中率和覆盖率
- 减少大量用户定义的自动调优(autotune)内核配置
此前,团队已经发布了关于为 Meta 内部工作负载减少 PT2 编译时间的经验,此处仅简要重述我们最近采取的主要方法,详情请参考博客。
减少不必要的重编译
由于 动态形状(dynamic shapes)导致的重编译是我们 Meta 工作负载中显著的开销来源。这种重编译对机群整体编译时间贡献很大,导致了相当大的累积成本。
为解决这一问题,v-team 在 2025 年上半年与 Pytorch 团队合作开发了 TORCH_COMPILE_DYNAMIC_SOURCES,它通过提供一种无需修改底层代码即可将参数标记为动态的简便方法,改善了参数动态形状的处理。此功能还支持将整数标记为动态,并允许使用正则表达式包含更广泛的参数,从而增强了灵活性并缩短了编译时间。

图 6. 用于识别动态形状的内部工具
改善 PT2 缓存
MegaCache 将多种类型的 PT2 编译缓存集成在一起——包括 Inductor(核心 PT2 编译器)、Triton 捆绑器(用于 GPU 代码)、AOT Autograd(用于高效梯度计算)、Dynamo PGO(配置导向优化)以及自动调优设置——形成一个可以轻松下载和共享的单一存档。
通过整合这些要素,MegaCache 带来了以下改进:
- 最大限度减少对远程服务器的重复请求
- 缩短模型设置时间
- 使启动和重试作业更加可靠,即使在分布式或云环境中也是如此
到 2025 年底,各团队协作在所有训练平台上启用了 MegaCache。得益于此,平均 PT2 编译时间显著缩短了约 40%。
自动调优配置修剪
PyTorch 2.0 中的自动调优(Autotune)是一项通过调整各种超参数和设置来自动优化 PyTorch 模型性能的功能。随着 Triton 内核 采用率的增加,编译和搜索 Triton 内核最佳设置及超参数所需的时间也随之增加。
为解决此问题,我们开发了一个流程来识别最耗时的内核,并确定最佳运行时配置以在代码库中实现。这种方法已大幅缩短了编译时间。
检查点管理
检查点(Checkpoint):检查点是模型在训练期间的状态快照,包括其参数、优化器设置和进度。
在 Meta,检查点用于确保如果训练作业因硬件或软件问题而中断,流程可以从上次保存的点恢复,而不是从头开始。
虽然保存检查点是必要的,但它目前通过占用内存资源来阻塞 GPU 训练,导致 GPU 闲置。此外,检查点保存的时间间隔直接影响故障发生时损失的训练进度(未保存的训练时间)。
为解决这些低效问题,团队成功开发并实施了 异步检查点(Async Checkpointing) 和 PyTorch 原生暂存(PyTorch Native Staging)。这些进展通过减少所有模型的检查点阻塞时间,显著提高了检查点性能。
异步检查点:它涉及在 CPU 内存中创建检查点的副本,允许主训练器进程在后台进程完成检查点上传的同时恢复训练循环。
PyTorch 原生暂存:最初的异步检查点实现使用了自定义的 C++ 暂存,旨在通过利用流式复制来最大限度地减少暂存期间的训练器内存使用。检查点团队使用 PyTorch 原生暂存 API 开发了一个单独的异步检查点解决方案,它以增加训练器内存消耗为代价,改善了保存阻塞时间。
这些改进是通过大幅减少每天因检查点而阻塞的 GPU 小时数来实现的。
减少浪费的训练时间
优化保存检查点所需的时间,通过减少对训练循环的中断,直接提升了有效训练时间(ETT)百分比。此外,当与检查点间隔的调整相结合时,这些检查点保存的改进可以释放更大的 ETT% 增长空间。
调整检查点间隔会影响浪费的训练时间的两个组成部分:
未保存的训练时间: 指作业故障后丢失的训练进度,因为自上次检查点以来完成的所有工作都会被丢弃。
- 计算公式:(训练循环故障次数)*(检查点间隔)/2
检查点保存阻塞时间: 指专门在创建新检查点时训练循环被暂停的时间。
- 计算公式:((训练循环中的时间)/(检查点间隔))*(每个检查点的阻塞时间)
根据作业故障率,可以调整检查点间隔以最小化预期的浪费训练时间,等于:
sum(未保存的训练时间, 检查点保存阻塞时间)
下图展示了检查点保存间隔与浪费训练时间百分比(WTT%)之间的关系,设定场景为 15 秒的检查点保存阻塞时间和每天 3 次故障。
图 7. 检查点保存间隔与浪费训练时间的关系
通过优化检查点保存间隔,团队成功减少了生产作业和探索性作业的未保存训练时间。
关闭时间优化
团队深入分析了关闭阶段的每个组件,发现模型发布处理(为推理进行模型发布)在训练后流程耗时中占比最大。
模型发布处理:模型发布是使用处理代码优化模型以创建可部署的推理快照的过程。
团队的分析促成了独立发布策略的采用,该策略将发布与训练过程解耦。通过这种方法,发布仅在训练作业完成并创建锚点检查点后启动。随后,模型处理作业利用该检查点和存储的数据生成最终的推理快照。
这种独立发布方法与传统的“趋势末端(trending end)”模型发布之间的主要区别如下图所示。

图 8. “趋势末端”模型发布与独立发布对比
新模型发布流水线的实施已成功将每个作业的关闭时间缩短了约 30 分钟。

故障减少与可观测性
故障减少一直是团队的主要关注领域,因为故障数量会显著影响整体有效训练时间(ETT)百分比。代码或配置变更引发的回归会直接导致该百分比下降。
ETT 仪表板的波动主要归因于两个因素:
- 增加的作业抢占: 运行中的作业数量越多,会导致更多的抢占。
- 服务回归: 服务问题导致更多的作业故障。
为解决抢占问题,我们正与基础设施团队合作开发一种新的调度算法,旨在在不负面影响用户配额或体验的情况下降低抢占率。
在故障减少方面,专门团队正在审查每个与 ETT 相关的组件,并建立仪表板以监控整体 ETT 性能,包括启动/重启时间(TTS/TTR)、未保存的训练时间和检查点保存时间。这种主动监控确保任何回归都能在 SLA 范围内被及早发现并缓解。
结语
随着模型训练规模的扩大,资源限制正成为整个行业面临的决定性挑战。多年来,提高训练效率的主要手段是通过模型协同设计和内核优化来增加模型 FLOPs 利用率(MFU)。这项工作依然至关重要,但大规模训练揭示了一个补充瓶颈:大量的 GPU 时间闲置在稳定的训练循环之外。
我们的分析表明,非训练开销可能是巨大的,特别是在一些最大的运行任务中。
为解决这一问题,我们启动了一个成功的工作流,专注于提高有效训练时间(ETT%),这已经产生了显著的容量节省。从业者的主要经验很简单:要在大规模下提高成本效率和吞吐量,必须优化“中间”阶段——而不仅仅是训练步骤本身。
由于我们的训练栈使用了 PyTorch,我们努力确保这些改进能够超出单一环境的局限。我们已将相关构建块(例如 TorchRec 和 PyTorch 2 中的组件)开源并分享到开源 PyTorch 生态系统中。这使得其他人能够利用这些改进,复制我们的成果,并在我们的工作基础上继续开发。其他组件(如模型发布和检查点)虽然更具 Meta 的特性,但它们解决了常见的行业挑战,并且可以进行调整以供他处使用。
我们希望这些经验能帮助各团队诊断类似的瓶颈,应用 ETT% 类型的测量,并为生态系统贡献进一步的改进。
致谢
我们衷心感谢 Max Leung、Apoorv Purwar、Musharaf Sultan、John Bocharov、Barak Pat、Jonathan Tang、Vivek Trehan、Chris Gottbrath 和 Vitor Brumatti Pereira 对本文进行的宝贵评审与深刻支持。我们还要感谢整个 Meta 团队在该工作流的开发和生产化过程中所付出的努力。