论文分享 | Phantora:在机器学习系统模拟中最大化代码复用
2026/8/1 19:03:38 网站建设 项目流程

模型训练系统的性能估计对集群规划和并行策略选型至关重要,现有的模拟器需要重写框架代码且维护成本高。分享一篇发表于 2026 年 USENIX NSDI 会议的论文 Phantora,该研究提出一种混合模拟方法,复用现有训练框架代码来实现模型性能估计。

1 背景介绍

大语言模型推动着自然语言处理、计算机视觉、推荐系统等领域的快速发展。随着模型日益复杂,高效的推理和训练成为机器学习系统的核心关注点。在部署训练任务时,如果能提前估计出系统的性能指标,就能帮助运维人员决定分配多少硬件资源,并规划未来的硬件需求。

目前业界主要使用静态工作负载模拟进行性能估计,主流方案分为两类。

  • 轨迹驱动模拟(如 Astra-Sim)在大规模 GPU 集群上运行一次真实训练,收集执行轨迹(trace),将轨迹逆向提取为高层工作负载描述,最后注入模拟器按新配置重放调度。
  • Mock 框架模拟(如 SimAI)则为框架重写一套 Mock 替代库,复现框架自身的调度逻辑,配合 SimCCL 通信模拟库(包级模拟),产出底层计算和通信事件供模拟器执行。

Astra-Sim 输入执行轨迹回放训练过程,SimAI 利用配置生成事件执行模拟,两类方案都绕不开同一个根本问题:需要重新实现机器学习框架的调度逻辑,导致模拟器对新框架和新特性的支持严重滞后。

论文提出一种称为混合模拟的方法 Phantora,其核心想法是将真实系统的执行直接与事件驱动模拟整合在一起,为机器学习框架制造一种运行在真实 GPU 集群上的假象。项目代码已开源至 https://github.com/QDelta/Phantora,图 1 展示了两种静态工作负载模拟方法与 Phantora 的对比。

图1 三种机器学习框架模拟方案对比

2 混合模拟核心思路

Phantora 使用容器化环境,配备单张 GPU 来直接运行机器学习系统。每个容器模拟一台多 GPU 服务器,每个 rank (分布式进程编号) 持有一个虚拟时钟。Phantora 拦截框架发起的 GPU 计算和网络通信操作,计算完成时间并更新虚拟时钟。

图2 Phantora架构图

Phantora 架构如图 2 所示,浅绿色组件表示未经修改的原始代码(框架本身、PyTorch),绿色组件表示做了最小化修改的组件(训练脚本),蓝色组件则是由 Phantora 构建的插桩库以及模拟模块。

3 Phantora 系统设计

3.1 插桩拦截以支持代码复用

Phantora 在三个层次实施插桩拦截,确保覆盖框架的所有关键操作路径,同时不对上层框架的训练代码做任何修改。

第一层:Phantora Tracer。嵌入 PyTorch 的 ATen dispatcher,注册一个纯观察钩子,采集每个被调用的 PyTorch 算子及其参数元数据,通过 Unix Socket 以计算事件的形式推送给模拟器的事件队列。Tracer 不干预算子的执行路径,算子仍正常下发到 CUDA 层,由下一层的桩库继续拦截。

第二层:Phantora CUDA Runtime。通过 LD_PRELOAD 替换 CUDA Driver 和 CUDA Runtime 共享库,截获所有底层 GPU 调用。桩函数不真正在硬件上执行:cudaMalloc/cudaFree 跟踪显存分配状态;cudaLaunchKernel 等计算类调用封装为事件推送给模拟器,模拟器收到后在物理 GPU 上执行一次 profiling,记录耗时并缓存供后续使用;同步类调用(如 cudaStreamSynchronize)则阻塞等待模拟器回复,用于推进 rank 的虚拟时钟。

第三层:Phantora NCCL 与网络模拟。用独立的 Phantora NCCL 库替换原生 NCCL,截获 ncclAllReduce、ncclAllGather 等集合通信操作。桩函数遵循 NCCL 的非阻塞语义立即返回,通信操作转发给内置的流级网络模拟器 netsim。netsim 会等待通信组内所有 rank 都到达后,再按配置的网络拓扑模拟传输耗时并计算完成时间。

图3 两个rank事件流执行示例图

这三个拦截层产生的事件统一汇入事件队列,原生支持 CUDA 流和事件的依赖语义:同一流上的操作隐式按序执行,不同流之间通过 CUDA 事件显式建立依赖。图 3 展示了两个 rank 的执行示例,每个 rank 将算子计算和集合通信放在不同流(s0 和 s1)上,通过 CUDA 事件管理同步。

3.2 事件驱动模拟与时间同步

混合模拟中存在两个独立推进的时间轴:脚本执行时间(容器中训练代码实际运行时间)和模拟虚拟时间(模拟器维护的逻辑时钟)。如果脚本执行快于虚拟时间推进,脚本通过流同步接口(如cudaStreamSynchronize)阻塞等待模拟器回复,因此不会出现问题。反过来如果虚拟时间推进快于脚本执行,后续产生新事件的时间戳可能落后于模拟器当前的虚拟时间,因而导致了过去事件问题

图4 过去事件问题示意图

图 4 展示了一个典型的过去事件场景。Rank 0 在T 1 T_1T1发送数据,模拟器计算出完成时间T 1 ′ T_1'T1。在模拟器到达T 1 ′ T_1'T1之前,Rank 1 也发起了一次通信(时间戳T 2 T_2T2),这条流会和 Rank 0 的流争抢网络带宽,但T 2 T_2T2早于T 1 ′ T_1'T1,从模拟器的视角看这已经是个“过去的事件”。

静态工作负载模拟不会遇到这个问题,因为所有事件在模拟开始前就已知。Phantora 的解决方案是采用时间回滚机制,让模拟器先按当前信息乐观推进,同时记录所有网络流的吞吐量历史。如图 5 所示,当“过去事件”出现时,模拟器回滚到对应时刻,基于历史状态重新计算受影响流的完成时间,并沿事件依赖图传播更新。

图5 时间回滚机制图

这个机制成立的关键前提是:机器学习训练中某个操作的执行时间不影响下一个操作的分支选择。矩阵乘法多花或少花几毫秒,不会改变下一个被调用的算子。因此回滚修正后的时间可以安全地通知各 rank,控制流不受影响。

历史状态垃圾回收。模拟器需要保存历史流状态以支持回滚。但有一个观察可以控制内存:当所有 rank 的虚拟时钟都超过时刻 T 后,就不可能再收到时间戳早于 T 的事件了。因此 T 之前的模拟器状态可以安全丢弃。

4 工程实现和效果评估

Phantora 的模拟器核心使用 Rust 实现,辅以 C 和 C++ 代码,整体代码量如下:

组件语言代码量
Phantora NCCL & CUDA RuntimeC + Rust1.8K + 1K 行
流级网络模拟器Rust3.6K 行
事件队列Rust3.4K 行
计算模拟器Rust1K 行
Phantora TracerC++500 行
总计约 11.3K 行

框架支持方面,Megatron 无需修改,DeepSpeed 改 4 行,TorchTitan 改 1 行,训练脚本仅需增加 6 行代码。

模拟精度方面,与 TorchTitan 官方 128 GPU 报告对比,平均误差 2.9%;与 H200 测试板对比(Llama2 7B),平均误差 3.7%;在非 LLM 模型(ResNet-50、Stable Diffusion、GAT)上也达到了 6.6% 的平均误差。

模拟速度方面,Llama3 8B 在 128 GPU 配置下每轮迭代约 15 秒,数分钟内即可完成吞吐量评估。

其他更具体的实验配置和评估结果可参阅原论文。


猴先生:Phantora 的混合模拟思路对上层机器学习框架透明,这与本人最近的研究工作高度相关。利用插桩获取事件序列形成依赖图,而不是从外部导入静态工作负载。不论从可信度还是实用性来看,都比传统方案更合理。

最后,附上文献引用及论文链接:

Qin J, Chen J, Kong X, et al. Phantora: Maximizing Code Reuse in Simulation-based Machine Learning System Performance Estimation[C]. 23rd USENIX Symposium on Networked Systems Design and Implementation (NSDI), 2026.

https://www.usenix.org/conference/nsdi26/presentation/qin

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询