前言
买了一台 Atlas 服务器,想把 PyTorch 模型跑在昇腾 NPU 上。第一步装什么、环境怎么配、第一个 demo 怎么跑起来,asc-devkit 给你一套完整的工具链。这篇文章手把手从零开始,完整走一遍环境配置到 ResNet50 推理的全流程。
环境准备:驱动和 CANN 版本对应
硬件与软件版本检查
昇腾 NPU 的运行环境有一套严格的版本对应关系:
硬件层:Atlas 训练服务器(Ascend 910)× 8 驱动层:驱动版本 23.0.rc3 CANN层:CANN 8.0.RC3 框架层:PyTorch 2.1.0 + torch_npu 工具层:asc-devkit版本错配是最常见的报错原因。升级之前先去社区查兼容性矩阵。
# 1. 检查 NPU 状态npu-smi info# 预期输出:# +-----------------------------------------------------------------------------+# | NPU 0 Card Type: Ascend 910P8 | 0 Used 32GB | Product: Atlas |# | NPU 1 Card Type: Ascend 910P8 | 0 Free 32GB | Product: Atlas |# +-----------------------------------------------------------------------------+# 2. 检查驱动版本cat/usr/local/Ascend/driver/version.info# 3. 检查 CANN 版本python-c"import acl; print(acl.__version__)"# 或python-c"import torch; print(torch.__version__); import torch_npu; print(torch_npu.__version__)"驱动安装(如果还没装)
驱动安装需要 root 权限,按以下顺序:
# 1. 下载驱动包(从昇腾官网下载对应版本)# 注意:驱动版本必须跟 CANN 版本匹配wgethttps://www.hiascend.com/document/detail/Ascend/Resources/drivepack/ATlas800-9000/...# 2. 安装驱动sudobashAscend-driver-{version}-linux.run--full# 3. 验证安装ls/usr/local/Ascend/driver/# 应该看到 driver/ 目录和 version.info# 4. 检查版本cat/usr/local/Ascend/driver/version.info# 输出示例:Driver Version=23.0.rc3 Build Date=2024-03-15驱动和 CANN 版本对应规则:
| CANN 版本 | 驱动版本要求 | 备注 |
|---|---|---|
| CANN 8.0.RC3 | 驱动 23.0.rc3 | 当前最新 |
| CANN 7.1 | 驱动 22.0.x | 长期支持版 |
| CANN 6.4 | 驱动 21.0.x | 旧版本兼容 |
版本错配会导致 ACL 初始化失败(error code 101)。
CANN 安装
CANN 是昇腾的异构计算架构,包含了算子库、编译器、Runtime 等组件。
# 1. 下载 CANN 包(社区版或商业版)# 社区版下载地址:https://www.hiascend.com/document/detail/Ascend/Resources/cann/wgethttps://www.hiascend.com/document/detail/Ascend/Resources/cann/...# 2. 安装 CANN(社区版不需要 root)pipinstallAscend-cann-community-8.0.RC3-linux.x86_64.run# 3. 设置环境变量source/usr/local/Ascend/ascend-toolkit/set_env.sh# 4. 验证 CANN 安装python-c"import acl; print(acl.__version__)"# 或用命令行atc--version# 预期输出:Ascend CANN 8.0.RC3# 5. 永久写入环境变量(推荐)echo'source /usr/local/Ascend/ascend-toolkit/set_env.sh'>>~/.bashrcCANN 组件说明:
| 组件 | 功能 | 重要目录 |
|---|---|---|
| ACL(Ascend Computing Language) | 统一 API 层 | /usr/local/Ascend/ascend-toolkit |
| HCCL | 集合通信库 | 分布式训练用 |
| GE(Graph Engine) | 图编译器 | 模型转换用 |
| Runtime | 运行时 | 推理执行用 |
| 算子库 | 各类算子实现 | ops-* 仓库 |
asc-devkit 安装
pip 安装(推荐)
# 安装最新稳定版pipinstallascend-mindx-sdk-ihttps://repo.huaweicloud.com/repository/pypi/simple/# 或者从源码安装(体验最新功能)gitclone https://atomgit.com/cann/asc-devkitcdasc-devkit pipinstall-e.# 验证安装python-c"import asc_devkit; print('asc-devkit 版本:', asc_devkit.__version__)"# 如果 import 报错,检查安装路径pip show ascend-mindx-sdkconda 环境隔离(强烈建议)
每个项目用独立的 conda 环境,避免依赖冲突和版本污染:
# 创建昇腾专用环境conda create-nascend-envpython=3.10-yconda activate ascend-env# 安装 PyTorch NPU 版(注意版本对应关系)pipinstalltorch==2.1.0 pipinstalltorch-npu==5.1.rc3-ihttps://repo.huaweicloud.com/repository/pypi/simple/# 验证 PyTorch 识别 NPUpython-c"import torch; print('PyTorch 版本:', torch.__version__)"python-c"import torch_npu; print('NPU 版本:', torch_npu.__version__)"# 确认 NPU 可用python-c"import torch; print('CUDA' if torch.cuda.is_available() else 'CPU')"# 输出应为:NPU(表示昇腾 NPU 被识别)模型转换:.onnx → .om
步骤1:从 PyTorch 导出 ONNX
asc-devkit 支持多种模型格式。这里以 PyTorch ResNet50 为例,先导出 ONNX:
# 1_pytorch_to_onnx.pyimporttorchimporttorchvision.modelsasmodels# 加载预训练模型model=models.resnet50(weights=models.ResNet50_Weights.DEFAULT)model.eval()# 准备输入(标准 ImageNet 预处理尺寸)dummy_input=torch.randn(1,3,224,224)# 导出 ONNXtorch.onnx.export(model,dummy_input,"resnet50.onnx",input_names=["input"],output_names=["output"],opset_version=13,# 推荐 13 或以上dynamic_axes={# 动态 batch size,方便推理时调整"input":{0:"batch_size"},"output":{0:"batch_size"}})print("ONNX 导出成功:resnet50.onnx")步骤2:ONNX 转 OM(Acore 模型格式)
# 2_onnx_to_om.pyimportcann# 模型转换配置config=cann.ModelConvertConfig(input_format="NCHW",input_shape="input:1,3,224,224",output_path="resnet50.om",soc_version="Ascend910P8",precision_mode="force_fp16",# 混合精度,FP16 推理op_debug_level="0")# 执行转换model=cann.ModelConverter()model.convert("resnet50.onnx",config)print("OM 转换成功:resnet50.om")步骤3:ATC 命令行转换(备选)
如果 Python API 有问题,可以用 ATC 命令行:
# 设置环境变量source/usr/local/Ascend/ascend-toolkit/set_env.sh# 执行转换atc\--model=resnet50.onnx\--framework=5\--output=resnet50\--input_shape="input:1,3,224,224"\--soc_version=Ascend910P8\--precision_mode=force_fp16\--op_debug_level=0# 参数说明:# --framework=5 表示 ONNX 格式# --soc_version 芯片型号# --precision_mode 精度模式(force_fp16/auto/force_fp32)推理部署:ACL 接口调用
基本推理流程
# 3_inference.pyimportcannimportnumpyasnpfromPILimportImage# 1. 加载 OM 模型model=cann.model.load_model("resnet50.om")# 2. 图片预处理(ImageNet 标准)defpreprocess(image_path):img=Image.open(image_path).convert("RGB")img=img.resize((224,224))img_array=np.array(img).astype(np.float32)/255.0# 标准化(ImageNet 统计值)mean=np.array([0.485,0.456,0.406])std=np.array([0.229,0.224,0.225])img_array=(img_array-mean)/std# HWC → CHWimg_array=img_array.transpose(2,0,1)# 加 batch 维度returnimg_array[np.newaxis,:,:,:]# 3. 执行推理image=preprocess("test_image.jpg")outputs=model.execute(image)# 4. 后处理(取最大概率类别)pred_class=int(np.argmax(outputs[0]))print(f"预测类别:{pred_class}")批量推理
# 4_batch_inference.pyimportcannimportnumpyasnpimportglob# 加载模型model=cann.model.load_model("resnet50.om")# 批量处理文件夹中的图片image_paths=glob.glob("test_images/*.jpg")batch_size=8foriinrange(0,len(image_paths),batch_size):batch_paths=image_paths[i:i+batch_size]# 批量读取和预处理batch_images=[]forpathinbatch_paths:img=preprocess(path)batch_images.append(img)# 拼接 batchbatch_tensor=np.concatenate(batch_images,axis=0)# 推理outputs=model.execute(batch_tensor)# 批量后处理forj,outinenumerate(outputs):pred=int(np.argmax(out))print(f"图片{batch_paths[j]}: 类别{pred}")性能验证
# 5_performance_test.pyimportcannimportnumpyasnpimporttime model=cann.model.load_model("resnet50.om")# Warmup(第一次有 JIT 编译)_=model.execute(np.random.randn(1,3,224,224).astype(np.float32))# 测试 100 次推理iterations=100times=[]for_inrange(iterations):dummy=np.random.randn(1,3,224,224).astype(np.float32)start=time.time()_=model.execute(dummy)elapsed=(time.time()-start)*1000# mstimes.append(elapsed)# 统计times.sort()print(f"Avg:{np.mean(times):.2f}ms")print(f"P50:{times[iterations//2]:.2f}ms")print(f"P95:{times[int(iterations*0.95)]:.2f}ms")print(f"P99:{times[int(iterations*0.99)]:.2f}ms")# 吞吐print(f"Throughput:{1000/np.mean(times):.2f}FPS")常见错误码和解决方式
错误1:驱动版本不匹配
Error: aclInit failed with error code 101这是最常见的错误。解决方式:
# 检查驱动和 CANN 版本对应关系# CANN 8.0 配 驱动 23.0.rc3# 降级或升级 CANN/驱动到匹配版本# 临时方案:设置忽略版本检查(不推荐生产环境)exportASCEND_SKIP_VERSION_CHECK=1错误2:模型转换 Shape 不匹配
Error: Invalid input shape, expected [1,3,224,224]检查输入数据的实际 shape:
importnumpyasnpprint(f"实际 shape:{input_tensor.shape}")print(f"预期 shape: (1, 3, 224, 224)")错误3:OM 加载失败
Error: Model file not found or format error检查 OM 文件是否损坏:
# 检查文件是否存在ls-lhresnet50.om# 用 ATC 重新转换,开启详细日志atc...--log_level=3错误4:NPU 显存不足
Error: Out of memory in device 0清理显存或减小 batch size:
# 查看显存使用importcann info=cann.rt.get_mem_info()print(f"Used:{info.used/1024**3:.2f}GB")# 减小 batch sizemodel.set_option("batch_size",4)踩坑记录:Atlas 服务器特殊注意事项
Atlas 服务器的环境配置跟普通开发机有些不同:
| 问题 | 原因 | 解决方式 |
|---|---|---|
| 镜像版本选择错误 | Atlas A2/A3 服务器镜像不同 | 社区下载页按机器型号选对应包 |
| 环境变量不生效 | 多用户同时操作互相覆盖 | 每个项目用独立 conda 环境 |
| 推理第一次很慢 | JIT 编译 | Warmup 10 次再正式测性能 |
| batch size 大了 OOM | 默认 batch_size 配置 | 逐步加 batch,观察显存峰值 |
# Atlas 服务器专用检查# 1. 确认机器型号(决定驱动版本)cat/proc/device-tree/model# 2. 确认 NUMA 亲和性(多卡时性能关键)numactl--hardware# 3. 设置 NPU 可见性(8 卡时)exportASCEND_VISIBLE_DEVICES=0,1,2,3,4,5,6,7完整脚本汇总
# 完整流程脚本:run_resnet.sh#!/bin/bashset-e# 环境激活source/usr/local/Ascend/ascend-toolkit/set_env.sh# 1. 推理(已有 OM 文件时)python 3_inference.py# 2. 批量推理性能测试python 5_performance_test.py# 3. 如果需要重新转换模型python 1_pytorch_to_onnx.py python 2_onnx_to_om.pyecho"完成!"总结
asc-devkit 工具链的核心流程:
- 查版本:驱动/CANN/PyTorch 版本对应正确
- 装工具:asc-devkit + torch_npu
- 转模型:ONNX → OM(ATC 或 Python API)
- 跑推理:ACL 接口调用
- 测性能:batch size + 吞吐验证
遇到问题先去社区 FAQ 查,90% 的问题在 FAQ 里有答案。
仓库地址:https://atomgit.com/cann/asc-devkit