“要是哪天像 DeepSeek 这样的成果先在华为平台上出现,那对我们国家会是非常糟糕的结果。”
经济观察网报道,4 月 15 日,英伟达 CEO 黄仁勋在接受美国科技播客主持人帕特尔专访时说了这句话。9 天后,DeepSeek V4 发布,分为 V4-Pro 和 V4-Flash 两个版本,上下文处理长度从上一代的 128K 扩展至 1M。同一天,华为宣布昇腾超节点。
这类新闻容易被写成宏大叙事。但对工程团队来说,问题更直接:原来跑在 CUDA 上的 PyTorch 模型,搬到昇腾 910C 和 CANN 8.0 环境后,能不能跑起来?跑起来以后,性能、显存和分布式训练能不能稳定?
迁移通常不是把 cuda 改成 npu 这么简单。真正耗时间的地方,往往藏在算子、显存、通信和调试工具里。
第一关通常不是性能,而是算子报错
很多团队第一次迁移时,先遇到的不是训练慢,而是模型直接起不来。
在 CUDA 环境里,一些复杂算子可以通过 torch.ops、第三方库或已有 CUDA 扩展解决。到了昇腾 910C + CANN 8.0,部分非标准算子可能没有现成实现,尤其是特定 Attention 变体、定制数据处理层,或者项目里长期沉淀下来的私有算子。
常见报错类似:
AICore error: operator not supported
这一般意味着当前算子没有被 AscendCL 或框架适配层正确承接。处理顺序可以更务实一点:
先查 CANN 的算子支持情况。CANN 8.0 相比旧版本扩充了对主流模型算子的覆盖,问题有时只是版本不一致。驱动、固件、CANN、torch_npu 之间的组合如果不匹配,报错会看起来像“算子缺失”,实际是环境没对齐。
如果确实缺算子,就要考虑 TBE 或 Ascend C 自定义算子。这个环节学习成本不低,但比在 Python 层用低效组合硬凑更可靠。对训练链路里的高频算子,绕开原生实现通常会把性能问题拖到后面集中爆发。
还有一种办法是从框架层处理。清华大学计图团队在 2025 年 1 月发布的适配信息中提到,计图框架已适配华为昇腾 910 系列,并与 CANN 8.0 接口融合优化。这个案例说明,框架侧统一算子注册和映射,能减少底层适配的重复工作。PyTorch 用户对应要重点检查 torch_npu 的算子映射;遇到不支持的自定义层时,可以尝试拆成标准算子组合,比如 Conv、BatchNorm、Activation 等基础模块。
显存问题,很多时候不是“卡不够大”
模型能启动以后,第二类高频问题是 OOM。
CUDA 下的显存管理经验,不能直接平移到 NPU。设备可见性、缓存策略、碎片整理、临时 buffer 复用方式都有差异。原来在 GPU 上刚好能跑的 batch,迁到昇腾后可能在某个算子处突然溢出;也可能小 batch 反复 OOM,大 batch 又影响训练稳定性。
排查时不要只盯总显存。更有用的是看峰值分配发生在哪一段:前向、反向、通信同步,还是数据预处理后的拷贝。
可优先做几件事:
- 检查 CANN 的显存分配策略,必要时配置
ASCEND_RT_MEMORY_POOL,减少碎片带来的不稳定; - 在 PyTorch 迁移场景下,确认使用的是 NPU 相关接口,而不是残留的 CUDA AMP 或 CUDA 显存控制代码;
- 对大模型训练启用 Gradient Checkpointing,用重新计算中间激活值换显存;
- 混合精度训练使用
torch_npu.amp,不要继续沿用torch.cuda.amp。
Loss Scale 也要单独观察。昇腾上的 FP16、BF16 行为和 GPU 环境不完全一样,如果训练发散,再去调整 init_scale、growth_interval 等参数;没出问题时,不建议一开始就把 GradScaler 改得很激进。
多卡训练要尽早检查 HCCL
单机单卡能跑,不代表多卡训练就稳。
进入多机多卡后,瓶颈经常从算子切到通信。GPU 时代常用 NCCL;昇腾集群里,对应要使用 Huawei Collective Communication Library,也就是 HCCL。在 PyTorch Distributed 环境中,后端需要明确指定:
backend = "hccl"
这里只改一行还不够。HCCL 对集群物理拓扑敏感,RANK_TABLE_FILE 配置是否正确,会直接影响进程和设备的对应关系。配置错了,轻则利用率波动,重则训练卡死或通信超时。
通信与计算的重叠也要重新做 Profiling。模型并行、张量并行、数据并行混用时,等待时间往往被隐藏在同步点后面。torch.npu.synchronize() 放得太频繁,会把本来可以异步执行的任务串行化;完全不放,又可能让错误定位变得困难。迁移初期可以先牺牲一点速度,把同步点放清楚,等链路稳定后再逐步收缩。
数据加载也别忽略。多进程 DataLoader、数据切片、CPU 到 NPU 的拷贝,如果和通信高峰撞在一起,会造成训练吞吐抖动。这里没有通用参数,建议从小规模任务开始压测,不要一上来就把集群资源全部打满。
调试工具换了,排障习惯也要换
CUDA 工程师熟悉 Nsight Systems、Nsight Compute。到了昇腾,常用的是 msprof 等 Profiling 工具。工具链不一样,排查节奏也要调整。
建议迁移阶段保留更完整的日志:
export MS_PROFILING=1
export ASCEND_GLOBAL_LOG_LEVEL=3
MS_PROFILING=1 可以帮助生成性能分析文件,再用相关工具查看算子耗时和通信耗时。ASCEND_GLOBAL_LOG_LEVEL 设为 3 或 4 时,日志会更详细,适合定位未知运行时错误。正式训练时再把日志降下来,避免 I/O 干扰。
更重要的是,不要把第一个验证任务做得太大。先用 2 到 4 卡检查模型逻辑、数据管道、混合精度和保存恢复,再逐步扩展。很多迁移问题在小规模时就会暴露:算子不支持、shape 推导异常、某个数据增强步骤仍在调用 CUDA、checkpoint 里保存了不兼容的设备信息。
这些问题如果拖到大规模训练时才发现,定位成本会高很多。
生态在补课,但工程债还要自己还
经济参考报 2026 年 4 月 27 日报道,昇腾计算生态已与 90 多个全球主流开源社区深度对接,对 70 余个全球主流大模型完成“0day 适配”与全链路优化,并全年向开发者开放 4000 卡算力资源。
这说明国产算力的适配条件正在改善。CANN 8.0、torch_npu、HCCL、框架适配层都在补齐能力,开发者不再只能从最底层摸索。
但具体到一个团队手里的模型,迁移成本不会自动消失。项目里用过哪些自定义算子,训练脚本里残留多少 CUDA 假设,显存峰值出现在哪里,分布式配置是否贴合集群拓扑,这些都要逐项过。
从 CUDA 到昇腾 CANN,真正的工作不是写一份“国产化替代方案”,而是把报错一个个清掉,把性能瓶颈一个个定位出来。先让模型稳定跑,再谈优化;先把算子、显存、通信三件事查清楚,再讨论集群效率。
对已经决定使用昇腾 910C 的团队来说,最实际的起点不是重写全套训练框架,而是从一次可复现的迁移开始:固定版本,固定模型,固定数据,记录每个报错和处理方式。工程账算清楚了,后面的规模化才有基础。