三个月前到货的几台华为 Atlas 800,如今还在机房里跑基座模型微调。每台配有 8 张昇腾 910C。监控曲线比刚从英伟达 A100 切过来时平了不少,但还谈不上顺手。
最初的目标很朴素:先跑通。借助 MindSpore 或 MindFormers 的适配样例,模型代码和训练脚本很快能完成第一轮替换。真正耗时间的是后面那段:程序不报错,吞吐却上不去;显存看着没满,任务突然 OOM;单机运行正常,一扩到两台,通信时间开始吞掉收益。
算子有了,不代表这条链路够快
CANN(Compute Architecture for Neural Networks)算子库覆盖了主流基础算子,但“能调用”和“跑得快”不是一回事。
我们在一个自定义 FFN 变体上首先碰了壁。这个复合算子融合了 BiasAdd、GELU 和 Dropout。在 CUDA 环境里,可以手写 CUDA 核函数,或者沿着 cuBLAS、cuDNN 的路径做优化。迁到 CANN 后,摆在面前的是两个都不算理想的选项:拆成 3 个独立算子,中间结果在显存里反复读写;或者交给 AutoTuning 尝试自动融合。
在我们当时的模型和运行环境中,AutoTuning 生成的核函数,执行效率约为原始 CUDA 实现的 60%。它能跑,也不会报错,但训练吞吐就是提不上去。
GRPO(Group Relative Policy Optimization)训练里的问题更明显。多组回答相对排序需要一类特定的规约操作,我们没有在当时的 CANN 算子库中找到可直接替换的高效实现,只能用基础算子拼接。结果是单次训练迭代速度相较 CUDA 版本下降约 40%。这个数字只对应当时的模型与配置,不能外推到所有 GRPO 任务,但它足以改变排期。
经济观察报在 2026 年 5 月 1 日刊发的《华为算力“开链”》谈的是平台层面的开放。落到研发现场,问题会具体到一个复合算子:没有高效落点,整条训练链路都可能被拖慢。
显存只用了七成,OOM还是会来
昇腾 910C 配备 HBM2e,纸面带宽并不紧张。可在变长序列输入的 LLM 微调任务里,显存使用效率比我们预想的低。
这类任务的 batch 会动态变化,前向计算中的显存申请与释放也不固定。在原来的 CUDA 环境中,PyTorch Caching Allocator 对这种模式处理得相对稳定。换到当时使用的 CANN 与 PyTorch 动态图组合后,显存碎片开始出现。
最典型的一次故障是:监控面板显示全局显存占用约 70%,新的内存申请却因为找不到足够大的连续块而失败,任务最终 OOM。只看“还剩多少显存”,很难提前发现这种问题。
我们最后没有继续依赖动态分配,而是改成更保守的“预分配+固定池”。代价也很直接:batch size 不再容易调整,训练配置的灵活性下降,还要多做几轮超参数搜索。
从那以后,显存监控不再只看峰值占用。分配与释放节奏、连续大块是否充足,也被放进了日常检查项。
两台机器接起来,16卡并不会自然变快
任务扩到两台 Atlas 800、共 16 张昇腾 910C 后,AllReduce 梯度同步成了新的瓶颈。
单机内的卡间通信主要依赖 HCCS(Heterogeneous Cluster Communication System),跨机还要经过机间链路。在我们的梯度张量形状和通信频率下,AllReduce 实际带宽利用率约为标称值的 70%。当张量大小不均匀,或者小粒度通信过于频繁时,折扣还会更大。
这同样不是一个可以套到所有集群上的结论。它只说明,单链路标称带宽不能直接换算成多机训练的扩展效率。
为了减少同步等待,我们把原本以数据并行(DP)为主的方案,改成更多使用流水线并行(PP)。吞吐有所改善,代码改造和调试工作却随之增加。通信问题没有消失,只是换了一种方式处理。
21世纪经济报道在 2025 年 6 月 24 日刊发的《昇腾破局 国产算力不再低调》提到,CloudMatrix 384 由 384 个昇腾 NPU 和 192 个鲲鹏 CPU 连接而成,Pangu Ultra 的后训练基于它。这个案例反而提醒我们:通信效率依赖整机拓扑和系统设计,不能拿超节点的表现直接推算普通两节点集群。
我们现在先查这九件事
这份清单来自前三个月的返工记录。它不保证一次解决所有问题,但能让算子、显存和通信瓶颈更早暴露。
上机之前
- 先做算子审计。 列出模型中的基础算子、自定义算子和第三方库算子,在 CANN 中逐项确认。遇到缺失或效率偏低的算子,我们现在会预留至少 30% 的开发与调优时间。
- 保留 CUDA 环境的内存画像。 记录训练峰值显存、分配方式是静态还是动态,以及 batch 变化时的显存曲线。迁移前就要判断,目标任务是否需要固定 batch size。
- 先测通信基线。 原 CUDA 集群用 nccl-tests,目标集群用 hccl-tests,分别检查 AllReduce、AllGather 的实际带宽和延迟。不要等完整模型跑起来后,才猜通信慢在哪里。
模型刚跑通时
- 优先从官方版本起步。 能使用华为 ModelZoo 或 MindFormers 中已有的模型代码,就不要一开始大面积自行改写。若继续沿用 PyTorch 或 TensorFlow 训练代码,需要单独验证动态图和自动微分行为。
- 把精度比对放到前面。 使用 CANN、MindSpore 提供的精度对比工具,在算子编译和单步执行阶段查数值偏差,不要等完整训练出现损失异常后再回头定位。
- 把通信路径写清楚。 哪些链路走 HCCS,哪些经过以太网,需要在部署和启动脚本中明确配置。拓扑不清楚,后面的带宽数据就没有解释价值。
准备扩容和上线时
- 让 Profile 成为日常动作。 用 MindInsight Profiler 持续看算子执行时间、显存曲线和通信开销,不能只盯着最终训练耗时。
- 准备不止一种并行方案。 DP、TP、PP、ZeRO 都应保留可切换的代码和配置。硬件规模一变,原来最合适的组合可能马上失效。
- 保留 CUDA 备用链路。 关键业务模型应继续维护原有的训练和推理流水线。迁移遇到短期无法解决的阻塞问题时,至少还有可用的回退方案。
能启动,不等于迁移完成
这次从 A100 到昇腾 910C 的迁移,让我们改了一个判断:代码能启动,只代表接口替换完成了。算子效率、显存稳定性和多机扩展效率都能解释清楚,才算真正具备上线条件。
证券时报网转引界面新闻的报道显示,华为已经公布昇腾 AI 芯片三年发展路线图。硬件和软件栈还会继续变化,某个版本上的最佳参数未必能长期照搬。更值得留下的是测量方法:算子级 Profile、显存画像、通信基线,以及一条随时可切回 CUDA 的备用链路。
现在,机房里的任务仍在运行,损失函数还在下降。和第一个月相比,最大的变化不是某项指标突然变得漂亮,而是我们已经知道该先查算子、再查内存分配,最后看通信拓扑。下一次再遇到 OOM 或吞吐下滑,至少不用从头猜。