迁移从驱动和生态开始。
测试用了两台服务器:一台8卡华为昇腾910C(单卡标称640 TFLOPS),另一台8卡寒武纪MLU590(单卡FP32算力120 TFLOPS,稀疏480 TFLOPS)。系统是Ubuntu 20.04,目标PyTorch 2.3.1。
华为这边,装好CANN 8.0.RC1 toolkit和torch_npu插件后,import torch和torch.npu.is_available()都顺利返回。但导入成功不代表能跑。第一个模型ResNet-50,直接.to('npu')在A100上大概0.03秒,昇腾910C实测平均要1.7秒——这个初始化时间得提前算进去。第一个报错来自数据加载:DataLoader默认的多进程(num_workers>0)在NPU下老报“内存映射文件错误”。解决办法是设num_workers=0或persistent_workers=False,牺牲点吞吐换稳定。
寒武纪MLU590用的是Cambricon PyTorch(深度定制版)。装好magicmind SDK后,API差别不小:张量移到设备要用ctensor.to('mldl'),混合精度训练由cnmix.amp替代torch.cuda.amp,文档说得不够清楚,得反复试。
跑三个模型,看真实数据
测的三个模型和场景:
- ResNet-50(图像分类):在ImageNet-1K验证集上测。
- Whisper-Large-v3(语音识别):用LibriSpeech测试集。
- Llama-3 8B(大模型推理):跑MMLU基准,单条问题,batch size=1。
基准是NVIDIA A100-80G。
| 模型 | 任务 | A100-80G | 华为910C | 寒武纪MLU590 |
|---|---|---|---|---|
| ResNet-50 | 图像吞吐(img/s) | 1,850 | 1,420 | 1,105 |
| Whisper-Large | 语音处理速度(WER) | 2.8% | 2.9% | 3.1% |
| Llama-3 8B | 首字延迟(ms) | 180 | 310 | 385 |
| Llama-3 8B | 生成速度(tokens/s) | 92 | 64 | 51 |
测试环境是双路Intel Xeon 8480+, 512GB RAM,2026年6月内部测的。
视觉模型上,华为910C跑到A100约77%的吞吐,寒武纪MLU590约59%。语音模型三者词错误率相差不超过0.3个百分点。大模型推理差距就明显了,910C和MLU590生成速度分别是A100的58%和44%。硬件规格不一样:A100是80GB显存加NVLink,910C是64GB HBM2e,MLU590是32GB GDDR6。
比跑分更头疼的报错
算子缺失:最常见的卡点。CUDA生态里常用的算子,在国产卡的自定义算子库里可能还没实现。比如torch.special.scaled_dot_product_attention的某些参数组合在910C上报“NotImplemented”,只能去翻CANN算子支持列表,用基础算子自己组合,特别耗时间。
混合精度训练的坑:910C上用npu.amp时,自定义loss里有些非标准操作可能导致梯度静默出错,训练不收敛。我们花两天才定位到是torch.clamp在低精度下的行为差异。寒武纪的cnmix.amp也有类似但不同的边界条件问题。
多卡通信库不同:从NCCL切到华为HCCL或寒武纪CNCL,不只是改个参数。HCCL对初始化顺序很敏感,分布式训练脚本得显式调用hccl.comm_split划分通信域,不然就会卡死。
四条实用建议
- 从最小模型开始:先跑通ResNet-18的“数据加载-前向-反向-更新”全流程,再上复杂模型。
- 用好迁移工具:华为的“ModelArts迁移助手”、寒武纪的“CNToolkit迁移工具”能自动检测大部分不兼容API并给修改建议,能省掉60%以上查文档时间。
- 盯紧内存显存:国产卡的内存管理有时不如CUDA透明,迁移初期要频繁用
npu.max_memory_allocated()等函数监控,防止内存泄漏。 - 直接联系厂商技术支持:深水区的算子问题,官方文档往往不够,通过论坛或商务渠道找性能优化团队,解决效率是指数级的提升。
这次迁移说明,国产算力在“能跑通”这个层面已经没问题了,主流PyTorch组件基本都能接上。但要“跑得好、跑得快”,差距主要在高性能算子的完备性、工具链的成熟度,以及针对大模型推理的优化深度上。