在大模型推理国产化替代的浪潮中,海光DCU、摩尔线程、华为昇腾和寒武纪是四条最常被提及的技术路线。然而,很多团队在选型时只关注硬件算力参数(TFLOPS、显存容量),却忽略了决定实际推理性能的软件栈成熟度和CUDA迁移成本。本文将从软件生态、代码迁移、推理性能三个维度对四大国产GPU平台进行横向对比,给出可复现的基准测试方法和量化的迁移成本评估。

一、四大国产GPU平台架构与软件栈概览
国产GPU的推理性能不仅取决于硬件算力,更取决于上层软件栈对PyTorch生态的兼容程度。四家厂商走了截然不同的技术路线:
| 平台 | 硬件架构 | 软件栈 | CUDA兼容方案 | PyTorch后端 | 推理框架支持 |
|---|---|---|---|---|---|
| 海光DCU | GPGPU架构(类CU设计) | DTK (基于ROCm定制) | HIP源码级兼容 | PyTorch-DCU (原生fork) | vLLM-DCU分支、自研推理引擎 |
| 摩尔线程 | MUSA架构(MTGPU芯片) | MUSA SDK | musify自动迁移工具 | TorchMUSA (PyTorch插件) | vLLM-MUSA适配、自研推理引擎 |
| 华为昇腾 | 达芬奇架构(NPU) | CANN + MindSpore | 无CUDA兼容层,需重写 | PyTorch-Ascend (torch_npu) | vLLM-Ascend、MindIE推理引擎 |
| 寒武纪 | MLUv架构(Cambricon Chip) | Neuware (CNToolkit) | CNToolkit API映射层 | PyTorch-Cambricon (torch_mlu) | 自研推理引擎、vLLM适配中 |
从表格可以看出,海光DCU和摩尔线程采用了”源码级兼容CUDA”的路线,迁移成本最低;华为昇腾走的是完全独立的NPU架构,需要大规模重写算子;寒武纪介于两者之间,提供API映射但底层完全不同。
二、CUDA代码迁移:四家平台的工具链对比
代码迁移是国产GPU落地最耗时也最容易踩坑的环节。下面分别展示四家平台的迁移工具链和实际操作方法。
2.1 海光DCU:HIP源码级兼容
海光DCU基于AMD ROCm深度定制,使用HIP(Heterogeneous-compute Interface for Portability)作为CUDA兼容层。HIP的核心思路是将cuda开头的API调用替换为hip开头的调用,大部分代码可以自动转换:
1
2
3
4
5
6
7
8 # 安装DTK工具链后,使用hipify工具自动转换
hipify-perl --inplace --exclude-kernels-name=my_kernel.cu
# 或者使用hipify-perl批量转换整个项目
hipify-perl --inplace --output-directory=src_hip/ src/*.cu
# 转换后的代码直接用hipcc编译
hipcc -o inference_engine src_hip/main.cu -lhipblas -lmiopen
HIP兼容的关键限制在于:不支持CUDA特有的驱动API(如cuLaunchKernel),需要手动改写为HIP Runtime API。此外,ROCm版本的MIOpen与cuDNN在算子覆盖上存在差异,部分自定义算子需要用MIOpen API重写。
2.2 摩尔线程:musify自动迁移工具
摩尔线程提供了musify工具,将CUDA源码自动转换为MUSA代码。其工作原理类似HIP,但针对MUSA架构做了优化:
1
2
3
4
5
6
7
8 # musify基本用法
musify --in-source=cuda_kernel.cu --out-source=musa_kernel.mu
# 批量迁移整个项目
musify --in-dir=src/cuda/ --out-dir=src/musa/ --recursive
# 编译MUSA代码
musacc -o inference_engine src/musa/main.mu -lmusart -lmublas
musify的一个关键优势是对PyTorch C++ Extension的自动支持。大部分通过torch.utils.cpp_extension加载的CUDA算子可以零代码修改直接编译为MUSA版本。但MUSA SDK的算子库(muBLAS、muDNN)相比cuBLAS/cuDNN仍有功能缺口,尤其是FlashAttention等复杂算子需要厂商适配。
2.3 华为昇腾:无CUDA兼容层,完全重写
昇腾NPU采用达芬奇架构,与GPU的SIMT模型完全不同。没有CUDA兼容工具,所有自定义算子需要用Ascend C或TBE(Tensor Boost Engine)重写:
1
2
3
4
5
6
7
8
9
10
11
12
13 # 昇腾C++ Extension示例:使用torch_npu后端
import torch
import torch_npu # 注册npu后端
# 模型直接迁移到NPU上运行
model = MyModel().to("npu:0")
input = torch.randn(1, 3, 224, 224).to("npu:0")
output = model(input)
# 自定义算子需要用Ascend C编写
# 1. 用Ascend C编写算子核函数
# 2. 用te.lang.cce_build编译为离线模型(.om)
# 3. 通过ACL(Ascend Computing Language)调用
昇腾的优势在于PyTorch-Ascend后端的自动图模式——大部分标准PyTorch模型只需.to(“npu”)即可运行,无需修改前向逻辑。但自定义CUDA算子、CUDA Graph、Triton kernel等需要完全重写为Ascend C或使用GE(Graph Engine)构图。
2.4 寒武纪:CNToolkit API映射层
寒武纪的CNToolkit提供了类似CUDA Runtime API的接口设计,但底层是MLUv架构:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 // 寒武纪CNRT API示例
#include <cnrt.h>
cnrtRet_t ret;
cnrtDev_t dev;
cnrtQueue_t queue;
cnrtInit(0);
cnrtGetDeviceHandle(&dev, 0);
cnrtCreateQueue(&queue, dev);
// 内存分配(类似cudaMalloc)
void *mlu_ptr;
cnrtMalloc(&mlu_ptr, size);
// 算子调用通过MagicMind推理框架
auto builder = magicmind::CreateIBuilder();
auto network = builder->BuildNetwork(model_proto);
auto engine = network->BuildEngine();

三、迁移成本量化对比
基于多个实际项目的迁移经验,以下是对四家平台迁移工作量的量化评估:
| 迁移维度 | 海光DCU | 摩尔线程 | 华为昇腾 | 寒武纪 |
|---|---|---|---|---|
| 标准PyTorch模型迁移 | 低(改import即可) | 低(改import即可) | 中(需torch_npu适配) | 中(需torch_mlu适配) |
| 自定义CUDA算子 | 低(HIP自动转换) | 低(musify自动转换) | 高(需重写为Ascend C) | 高(需重写为CNRT) |
| Triton Kernel | 不支持 | 不支持 | 不支持 | 不支持 |
| vLLM适配 | 有社区分支 | 有社区分支 | 官方支持(vLLM-Ascend) | 适配中 |
| FlashAttention | 厂商适配 | 厂商适配中 | 厂商适配 | 厂商适配中 |
| 预估迁移人天(7B模型) | 3-5天 | 3-7天 | 10-20天 | 10-15天 |
| 预估迁移人天(70B模型+多卡) | 10-15天 | 15-25天 | 30-50天 | 25-40天 |
关键结论:海光DCU的迁移成本最低,因为HIP兼容层覆盖了90%以上的CUDA API;摩尔线程次之,musify工具虽好但算子库覆盖尚在完善;华为昇腾和寒武纪由于架构差异大,自定义算子迁移成本显著高于前两者。
四、LLM推理性能基准测试方法
为了公平对比四家平台的推理性能,我们需要一套标准化的基准测试方案。以下是基于LLaMA-2-7B模型的测试方法论:
4.1 测试环境与工具
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 # 使用统一的benchmark脚本框架
# 测试指标:首Token延迟(TTFT)、吞吐量(TPS)、显存占用
# 海光DCU测试
export HIP_VISIBLE_DEVICES=0
python benchmark.py --model meta-llama/Llama-2-7b-hf \
--backend vllm-dcu --batch-size 1 --input-len 128 --output-len 256
# 摩尔线程测试
export MUSA_VISIBLE_DEVICES=0
python benchmark.py --model meta-llama/Llama-2-7b-hf \
--backend vllm-musa --batch-size 1 --input-len 128 --output-len 256
# 华为昇腾测试
export ASCEND_VISIBLE_DEVICES=0
python benchmark.py --model meta-llama/Llama-2-7b-hf \
--backend vllm-ascend --batch-size 1 --input-len 128 --output-len 256
# 寒武纪测试
export MLU_VISIBLE_DEVICES=0
python benchmark.py --model meta-llama/Llama-2-7b-hf \
--backend cambricon-engine --batch-size 1 --input-len 128 --output-len 256
4.2 统一基准测试脚本
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77 import time
import torch
import json
def benchmark_inference(model_path, device, batch_size=1,
input_len=128, output_len=256, warmup=3, repeats=10):
"""统一的推理性能基准测试"""
# 加载模型
model = load_model(model_path, device)
model.eval()
# 预热
for _ in range(warmup):
inputs = torch.randint(0, 32000, (batch_size, input_len)).to(device)
with torch.no_grad():
_ = model.generate(inputs, max_new_tokens=output_len)
sync_device(device)
# 正式测试
results = []
for i in range(repeats):
inputs = torch.randint(0, 32000, (batch_size, input_len)).to(device)
start = time.perf_counter()
with torch.no_grad():
outputs = model.generate(inputs, max_new_tokens=output_len)
sync_device(device)
end = time.perf_counter()
total_time = end - start
ttft = measure_first_token_time(model, inputs)
tps = (output_len * batch_size) / total_time
results.append({
'total_time': total_time,
'ttft': ttft,
'tps': tps,
'peak_memory': get_device_memory(device)
})
# 汇总
avg_tps = sum(r['tps'] for r in results) / len(results)
avg_ttft = sum(r['ttft'] for r in results) / len(results)
avg_mem = sum(r['peak_memory'] for r in results) / len(results)
return {
'device': str(device),
'avg_tps': round(avg_tps, 2),
'avg_ttft_ms': round(avg_ttft * 1000, 2),
'avg_memory_mb': round(avg_mem / 1024 / 1024, 2),
'repeats': repeats
}
def sync_device(device):
"""跨平台同步"""
dev_str = str(device).lower()
if 'npu' in dev_str:
import torch_npu
torch_npu.npu.synchronize()
elif 'mlu' in dev_str:
import torch_mlu
torch_mlu.mlu.synchronize()
else:
torch.cuda.synchronize()
def get_device_memory(device):
"""跨平台显存查询"""
dev_str = str(device).lower()
if 'npu' in dev_str:
import torch_npu
return torch_npu.npu.memory_allocated()
elif 'mlu' in dev_str:
import torch_mlu
return torch_mlu.mlu.memory_allocated()
else:
return torch.cuda.memory_allocated()
以上脚本通过抽象设备同步和显存查询接口,实现了对四家平台的统一基准测试。实际使用时需要根据各平台的推理引擎做适配调整。
五、推理性能参考数据与对比分析
以下是基于公开资料和社区测试整理的参考性能数据(LLaMA-2-7B,FP16精度,batch=1,input 128 tokens,output 256 tokens):
| 平台 | 芯片型号 | 显存(HBM) | 首Token延迟 | 吞吐量(tokens/s) | 峰值显存占用 |
|---|---|---|---|---|---|
| NVIDIA A100 (基准) | A100 40G | 40GB HBM2 | ~45ms | ~85 | ~14GB |
| 海光DCU | 深算二号 K100AI | 32GB HBM2 | ~80ms | ~45 | ~16GB |
| 摩尔线程 | MTT S80 | 48GB GDDR6 | ~120ms | ~30 | ~18GB |
| 华为昇腾 | Ascend 910B | 64GB HBM2e | ~60ms | ~65 | ~15GB |
| 寒武纪 | 思元590 | 48GB LPDDR5 | ~95ms | ~40 | ~17GB |
注:以上数据来自公开基准测试和社区反馈,实际性能受驱动版本、软件栈版本、模型优化程度影响较大,仅供参考。建议在具体采购前进行实测验证。
从数据可以看出几个关键趋势:
- 华为昇腾910B在性能上最接近A100,吞吐量约为A100的76%,这得益于其较高的显存带宽和成熟的MindIE推理引擎优化。
- 海光DCU凭借HIP兼容性在易用性上占优,但绝对性能约为A100的53%,受限于较老的架构设计和显存带宽。
- 摩尔线程MTT S80使用GDDR6而非HBM,显存带宽成为瓶颈,大模型推理时性能受限明显。
- 寒武纪思元590的LPDDR5显存带宽介于GDDR6和HBM之间,性能表现中规中矩,但软件生态仍在快速迭代中。
六、实际迁移踩坑经验总结
在实际将CUDA推理代码迁移到四家平台的过程中,以下是最高频出现的踩坑问题及解决方案:
6.1 算子不支持问题(最高频)
所有四家平台都存在不同程度的算子缺失问题。常见的不支持算子包括:flash_attn_varlen、rotary_embedding、silu_backward等大模型专用算子。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29 # 检测算子支持情况的通用方法
def check_op_support(model, device, sample_input):
"""逐层检测算子是否被支持"""
hooks = []
unsupported_ops = []
def make_hook(name):
def hook(module, input, output):
try:
# 尝试反向传播检测算子完整性
if output.requires_grad:
output.sum().backward(retain_graph=True)
except RuntimeError as e:
if "not implemented" in str(e) or "not supported" in str(e):
unsupported_ops.append(f"{name}: {str(e)[:100]}")
return hook
for name, module in model.named_modules():
hooks.append(module.register_forward_hook(make_hook(name)))
try:
model(sample_input)
except Exception as e:
print(f"Forward pass failed: {e}")
for h in hooks:
h.remove()
return unsupported_ops
6.2 多卡通信原语差异
多卡推理场景下,四家平台的集合通信库差异显著:
- 海光DCU:使用HCCL(基于RCCL定制),API与NCCL高度兼容,多卡推理迁移成本低。
- 摩尔线程:使用自研的MUSA通信库,API设计参考NCCL但部分接口缺失,需手动适配。
- 华为昇腾:使用HCCL,与NCCL API有较大差异,需要重写通信逻辑。
- 寒武纪:使用CNCL,接口与NCCL有一定相似度但通信模式不同。
6.3 显存分配策略差异
不同平台的显存分配器行为不一致,容易导致OOM。特别是PagedAttention等需要细粒度显存管理的技术,在国产GPU上的表现差异较大:
1
2
3
4
5
6
7
8
9
10
11
12 # 海光DCU:设置显存分配策略
export HIP_FORCE_P2J=0 # 禁用强制page迁移
export HIP_VISIBLE_DEVICES=0,1
export GPU_MAX_HW_QUEUES=4
# 华为昇腾:调整内存池策略
export ASCEND_LAUNCH_BLOCKING=1 # 同步执行模式
export TASK_QUEUE_ENABLE=0 # 禁用任务队列优化
export ACL_OP_SELECT_IMPL_MODE=high_precision # 高精度模式
# 通用建议:推理时预留更多显存余量
# gpu_memory_utilization 设置为 0.80-0.85 而非 0.90
七、选型建议与总结
基于以上全维度对比,给出以下选型建议:
1. 如果CUDA代码资产庞大、迁移人力有限:首选海光DCU。HIP兼容层可以让90%的CUDA代码零修改运行,迁移成本最低。适合已有大量CUDA算子库的团队快速国产化。
2. 如果追求最高推理性能和最成熟的软件生态:华为昇腾910B是目前国产GPU中推理性能最接近A100的选择。虽然迁移成本较高,但CANN和MindIE生态的推理优化做得最深入,PagedAttention、Continuous Batching等高级特性支持较好。
3. 如果需要大显存容量、预算敏感:摩尔线程MTT S80提供48GB显存,价格具有竞争力,适合显存需求大但性能要求不极致的场景。需要注意GDDR6带宽限制对大模型推理吞吐量的影响。
4. 如果已有寒武纪生态积累:寒武纪思元590在CV推理场景有较好优化,但大模型推理生态仍在完善中。适合已有Neuware开发经验的团队。

最后需要强调的是,国产GPU软件栈迭代速度极快——海光DTK、摩尔线程MUSA SDK、华为CANN、寒武纪Neuware几乎每季度都有重大更新。本文中的性能数据和迁移成本评估基于2025年底的软件版本,建议在实际选型前获取最新驱动和SDK重新验证。更多国产GPU迁移实战经验,可以参考本站的海光DCU开发实战全攻略和摩尔线程MUSA编程实战详解。
汤不热吧