从 0 到 1:10 分钟跑通第一个 Ascend ACL 推理程序

news2026/5/22 1:59:44
第一次在昇腾 NPU 上跑推理很多人卡在第一步环境装好了ATC 模型转换也成功了一跑推理程序就报aclInit failed或者load model failed。我当年第一次跑 ACL 推理环境装了 3 遍模型转了 5 遍推理程序编译通过但运行就 core dump。最后发现是环境变量没配全——LD_LIBRARY_PATH少了/usr/local/Ascend/nnrt/latest/acllib/lib64导致运行时找不到libascendcl.so。这篇文章把我踩过的坑全部列出来你照着做10 分钟内必能跑通。第一步CANN 环境安装1.1 确认硬件和环境先确认你有昇腾 NPU910/910B/310 都行且系统是 Ubuntu 18.04/20.04 或 CentOS 7.x。# 看有没有 NPU 设备 ls /dev/davinci* # 有输出比如 /dev/davinci0说明驱动装好了没输出先装驱动。去昇腾社区下载对应版本的驱动[https://www.hiascend.com/hardware/firmware-drivers]按文档装完重启。1.2 安装 CANN Toolkit 和 NNRtCANN 有两个包Toolkit开发用含编译工具链和NNRt运行时含 ACL 库。# 下载 CANN 8.0.RC1 版本示例具体版本看你 NPU 驱动版本 # 去 https://www.hiascend.com/software/cann/community-history 下载 # 安装 Toolkit开发机装 ./Ascend-cann-toolkit_8.0.RC1_linux-x86_64.run --full # 安装 NNRt运行机装如果开发运行同一台机器两个都装 ./Ascend-cann-nnrt_8.0.RC1_linux-x86_64.run --full90% 新手都会踩的坑 No.1装完不配环境变量。 装完 CANN 一定要配环境变量否则编译时找不到头文件运行时找不到库。第二步环境变量配置这是最容易出问题的地方。很多人以为/etc/profile里配一次就完事了其实每次开新终端都要 source。创建环境变量配置文件~/.cannrc# ~/.cannrc export ASCEND_HOME/usr/local/Ascend export CANN_HOME$ASCEND_HOME/nnrt/latest export PATH$ASCEND_HOME/toolkit/latest/bin:$PATH export LD_LIBRARY_PATH$CANN_HOME/acllib/lib64:$ASCEND_HOME/driver/lib64:$LD_LIBRARY_PATH export ASCEND_OPP_PATH$ASCEND_HOME/nnrt/latest/opp每次开新终端都要 sourcesource ~/.cannrc或者写进~/.bashrc一劳永逸echo source ~/.cannrc ~/.bashrc验证环境变量是否配好# 看能不能找到 ATC 工具 which atc # 输出应该是 /usr/local/Ascend/toolkit/latest/bin/atc # 看能不能找到 ACL 库 ldconfig -p | grep ascendcl # 输出应该有一行 libascendcl.so90% 新手都会踩的坑 No.2LD_LIBRARY_PATH配了但没生效。 用ldconfig -p | grep ascendcl验证。如果没输出说明库路径没配进去。检查~/.cannrc里的路径是否真实存在比如nnrt/latest是不是软链接有时候装完叫nnrt/8.0.RC1。第三步模型转换ATCACL 推理需要 OM 格式的模型离线模型。你手里的 ONNX/PyTorch/TensorFlow 模型需要先转成 OM。3.1 准备 ONNX 模型如果手头没有 ONNX 模型用 PyTorch 导出一个 ResNet-50# export_resnet50.py import torch import torchvision model torchvision.models.resnet50(pretrainedFalse) model.eval() dummy_input torch.randn(1, 3, 224, 224) torch.onnx.export(model, dummy_input, resnet50.onnx, input_names[input], output_names[output])3.2 用 ATC 转 OMatc --modelresnet50.onnx \ --framework5 \ --outputresnet50 \ --input_formatNCHW \ --input_shapeinput:1,3,224,224 \ --loginfo参数解释解释 WHY 而非 WHAT--framework5ONNX 的格式编号是 51Caffe, 3TensorFlow, 5ONNX, 6PyTorch--input_formatNCHWNPU 要求输入是 NCHW 格式跟 PyTorch 一致--outputresnet50输出的 OM 模型叫resnet50.om自动加.om后缀转换成功会看到ATC run success生成resnet50.om文件。90% 新手都会踩的坑 No.3模型转换成功但推理时报load model failed。 原因ATC 转换时用的 CANN 版本跟推理程序编译时链接的 CANN 版本不一致。解决保证转换和运行用同一个 CANN 版本比如都是 8.0.RC1。第四步写 ACL 推理代码C这是核心。ACL 推理分 5 步初始化 → 加载模型 → 准备输入 → 执行推理 → 解析输出。4.1 目录结构acl_inference/ ├── CMakeLists.txt # 编译配置 ├── main.cpp # 主程序 ├── resnet50.om # 模型文件ATC 转换生成 └── test_image.bin # 输入数据二进制文件4.2 完整 C 代码// main.cpp #include acl/acl.h #include acl/ops/acl_dvpp.h #include iostream #include fstream #include vector // 检查 ACL 返回值的宏不写 try-catch直接判错 #define CHECK_RET(ret, msg) \ if ((ret) ! ACL_SUCCESS) { \ std::cerr msg , ret ret std::endl; \ return -1; \ } int main() { // 第 1 步初始化 ACL aclError ret aclInit(nullptr); CHECK_RET(ret, aclInit failed); // 指定要用的 NPU 设备0 号设备 ret aclrtSetDevice(0); CHECK_RET(ret, aclrtSetDevice failed); // 第 2 步加载 OM 模型 uint32_t model_id 0; ret aclmdlLoadFromFile(resnet50.om, model_id); CHECK_RET(ret, aclmdlLoadFromFile failed); // 获取模型描述信息输入/输出的 shape、数据类型 aclmdlDesc *model_desc aclmdlCreateDesc(model_id); ret aclmdlGetDesc(model_desc, model_id); CHECK_RET(ret, aclmdlGetDesc failed); // 第 3 步准备输入数据 // 读二进制输入文件假设已经把图片预处理成了 1×3×224×224 的 float32 数组 std::ifstream infile(test_image.bin, std::ios::binary); std::vectorfloat input_data(1 * 3 * 224 * 224); infile.read(reinterpret_castchar*(input_data.data()), input_data.size() * sizeof(float)); infile.close(); // 申请 NPU 显存输入数据要从 Host 拷到 NPU size_t input_size aclmdlGetInputSizeByIndex(model_desc, 0); void *input_dev nullptr; ret aclrtMalloc(input_dev, input_size, ACL_MEM_MALLOC_HUGE_FIRST); CHECK_RET(ret, aclrtMalloc failed); // 把 Host 数据拷到 NPU ret aclrtMemcpy(input_dev, input_size, input_data.data(), input_size, ACL_MEMCPY_HOST_TO_DEVICE); CHECK_RET(ret, aclrtMemcpy failed); // 创建输入 datasetACL 要求用 dataset 封装输入输出 aclmdlDataset *input_dataset aclmdlCreateDataset(); aclDataBuffer *input_buffer aclCreateDataBuffer(input_dev, input_size); ret aclmdlAddDatasetBuffer(input_dataset, input_buffer); CHECK_RET(ret, aclmdlAddDatasetBuffer failed); // 第 4 步执行推理 // 创建输出 dataset aclmdlDataset *output_dataset aclmdlCreateDataset(); for (size_t i 0; i aclmdlGetNumOutputs(model_desc); i) { size_t output_size aclmdlGetOutputSizeByIndex(model_desc, i); void *output_dev nullptr; ret aclrtMalloc(output_dev, output_size, ACL_MEM_MALLOC_HUGE_FIRST); CHECK_RET(ret, aclrtMalloc output failed); aclDataBuffer *output_buffer aclCreateDataBuffer(output_dev, output_size); ret aclmdlAddDatasetBuffer(output_dataset, output_buffer); CHECK_RET(ret, aclmdlAddDatasetBuffer output failed); } // 执行模型推理 ret aclmdlExecute(model_id, input_dataset, output_dataset); CHECK_RET(ret, aclmdlExecute failed); // 第 5 步解析输出 // 把输出从 NPU 拷回 Host for (size_t i 0; i aclmdlGetNumOutputs(model_desc); i) { aclDataBuffer *output_buffer aclmdlGetDatasetBuffer(output_dataset, i); void *output_dev aclGetDataBufferAddr(output_buffer); size_t output_size aclGetDataBufferSize(output_buffer); std::vectorfloat output_data(output_size / sizeof(float)); ret aclrtMemcpy(output_data.data(), output_size, output_dev, output_size, ACL_MEMCPY_DEVICE_TO_HOST); CHECK_RET(ret, aclrtMemcpy output failed); // 打印前 10 个输出值真实场景要接后处理比如 argmax 取分类结果 std::cout Output i (first 10 values): ; for (int j 0; j 10 j output_data.size(); j) { std::cout output_data[j] ; } std::cout std::endl; } // 清理资源 ret aclmdlUnload(model_id); CHECK_RET(ret, aclmdlUnload failed); ret aclrtResetDevice(0); CHECK_RET(ret, aclrtResetDevice failed); ret aclFinalize(); CHECK_RET(ret, aclFinalize failed); std::cout Inference success! std::endl; return 0; }4.3 代码关键解释为什么用aclmdlDataset封装输入输出ACL 的接口设计是面向 Dataset的——一个模型可能有多个输入比如 GPT 的input_ids和attention_mask用 Dataset 封装可以一次性传多个输入。为什么输入数据要从 Host 拷到 NPUNPU 只能直接访问自己的显存HBM。Host 内存的数据必须显式拷贝用aclrtMemcpy。为什么aclrtMalloc要用ACL_MEM_MALLOC_HUGE_FIRSTNPU 的 HBM 支持大页内存Huge Page用这个标志申请内存会优先用大页性能好 10-15%。第五步编译写CMakeLists.txtcmake_minimum_required(VERSION 3.10) project(acl_inference) set(CMAKE_CXX_STANDARD 14) # 找 CANN 包装在 /usr/local/Ascend find_package(Ascend REQUIRED) # 包含 ACL 头文件路径 include_directories(${ASCEND_INCLUDE_DIRS}) # 编可执行文件 add_executable(acl_inference main.cpp) # 链 ACL 库 target_link_libraries(acl_inference ${ASCEND_LIBRARIES})编译mkdir build cd build cmake .. make -j90% 新手都会踩的坑 No.4编译通过但运行时报error while loading shared libraries: libascendcl.so。 原因LD_LIBRARY_PATH没配全。运行时的库路径要在~/.cannrc里配好见第二步。第六步运行# 确保环境变量已 source source ~/.cannrc # 把 resnet50.om 拷到运行目录 cp ../resnet50.om . # 运行需要有 NPU 权限加 sudo 或把用户加入 HwAiUser 组 ./acl_inference成功输出Output 0 (first 10 values): 0.0023 -0.0156 0.0089 ... Inference success!为什么模型能转换成功但运行失败这是新手问的最多的问题。我总结了 4 个原因原因 1CANN 版本不匹配ATC 转换时用的 CANN 版本跟推理程序编译/运行时用的 CANN 版本不一致。OM 模型格式可能变了导致aclmdlLoadFromFile失败。排查# 看 ATC 版本 atc --version # 看推理程序链接的 ACL 库版本 ldd acl_inference | grep ascendcl解决统一版本重新转换模型、重新编译程序。原因 2NPU 驱动版本跟 CANN 不匹配CANN 8.0 要求驱动版本 24.1.0。如果驱动太老ACL 初始化就失败aclInit failed。排查# 看驱动版本 npu-smi info解决升级驱动到 CANN 要求的版本。原因 3输入 Shape 跟模型要求的不一致ATC 转换时指定了input_shapeinput:1,3,224,224但推理时输入数据的 shape 不对比如你传了1,3,256,256的数据导致aclmdlExecute失败。排查打印输入数据的尺寸跟 ATC 转换时指定的 shape 对比。解决推理前把输入数据 resize/crop 到模型要求的 shape。原因 4权限问题运行推理程序需要访问/dev/davinci0设备文件普通用户没权限。排查ls -l /dev/davinci0 # 如果 owner 是 root你需要 sudo 或加入 HwAiUser 组解决sudo usermod -aG HwAiUser $USER # 注销重新登录就有权限了90% 新手都会踩的坑完整版坑编号问题描述原因解决方法1装完 CANN 找不到头文件/库环境变量没配写~/.cannrc每次开终端 source2编译通过运行时libascendcl.so找不到LD_LIBRARY_PATH没配全ldconfig -p3模型转换成功推理时load model failedCANN 版本不匹配统一转换和运行用的 CANN 版本4aclInit failed驱动版本太老升级驱动到 CANN 要求的版本5推理输出全是 0 或 NaN输入数据没归一化图片预处理要跟训练时一致比如 ImageNet 的 mean/std排错方法总结遇到问题按这个顺序排查看返回值所有 ACL 接口都返回aclError用CHECK_RET宏检查看环境变量echo $LD_LIBRARY_PATH确认库路径看设备状态npu-smi info确认 NPU 在线看模型信息atc --modedisplay_model_info --omresnet50.om确认模型输入/输出 shape简化复现先跑 CANN 自带的样例比如/usr/local/Ascend/nnrt/latest/samples/inference/modelInference/工程经验第一次跑不通别慌。ACL 的错误码很详细比如ACL_ERROR_INVALID_RESOURCE 107002去昇腾社区搜错误码90% 的问题都有现成答案。https://atomgit.com/cann/runtime https://atomgit.com/cann/asc-devkit https://atomgit.com/cann/cann-samples

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2633291.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

SpringBoot-17-MyBatis动态SQL标签之常用标签

文章目录 1 代码1.1 实体User.java1.2 接口UserMapper.java1.3 映射UserMapper.xml1.3.1 标签if1.3.2 标签if和where1.3.3 标签choose和when和otherwise1.4 UserController.java2 常用动态SQL标签2.1 标签set2.1.1 UserMapper.java2.1.2 UserMapper.xml2.1.3 UserController.ja…

wordpress后台更新后 前端没变化的解决方法

使用siteground主机的wordpress网站,会出现更新了网站内容和修改了php模板文件、js文件、css文件、图片文件后,网站没有变化的情况。 不熟悉siteground主机的新手,遇到这个问题,就很抓狂,明明是哪都没操作错误&#x…

网络编程(Modbus进阶)

思维导图 Modbus RTU(先学一点理论) 概念 Modbus RTU 是工业自动化领域 最广泛应用的串行通信协议,由 Modicon 公司(现施耐德电气)于 1979 年推出。它以 高效率、强健性、易实现的特点成为工业控制系统的通信标准。 包…

UE5 学习系列(二)用户操作界面及介绍

这篇博客是 UE5 学习系列博客的第二篇,在第一篇的基础上展开这篇内容。博客参考的 B 站视频资料和第一篇的链接如下: 【Note】:如果你已经完成安装等操作,可以只执行第一篇博客中 2. 新建一个空白游戏项目 章节操作,重…

IDEA运行Tomcat出现乱码问题解决汇总

最近正值期末周,有很多同学在写期末Java web作业时,运行tomcat出现乱码问题,经过多次解决与研究,我做了如下整理: 原因: IDEA本身编码与tomcat的编码与Windows编码不同导致,Windows 系统控制台…

利用最小二乘法找圆心和半径

#include <iostream> #include <vector> #include <cmath> #include <Eigen/Dense> // 需安装Eigen库用于矩阵运算 // 定义点结构 struct Point { double x, y; Point(double x_, double y_) : x(x_), y(y_) {} }; // 最小二乘法求圆心和半径 …

使用docker在3台服务器上搭建基于redis 6.x的一主两从三台均是哨兵模式

一、环境及版本说明 如果服务器已经安装了docker,则忽略此步骤,如果没有安装,则可以按照一下方式安装: 1. 在线安装(有互联网环境): 请看我这篇文章 传送阵>> 点我查看 2. 离线安装(内网环境):请看我这篇文章 传送阵>> 点我查看 说明&#xff1a;假设每台服务器已…

XML Group端口详解

在XML数据映射过程中&#xff0c;经常需要对数据进行分组聚合操作。例如&#xff0c;当处理包含多个物料明细的XML文件时&#xff0c;可能需要将相同物料号的明细归为一组&#xff0c;或对相同物料号的数量进行求和计算。传统实现方式通常需要编写脚本代码&#xff0c;增加了开…

LBE-LEX系列工业语音播放器|预警播报器|喇叭蜂鸣器的上位机配置操作说明

LBE-LEX系列工业语音播放器|预警播报器|喇叭蜂鸣器专为工业环境精心打造&#xff0c;完美适配AGV和无人叉车。同时&#xff0c;集成以太网与语音合成技术&#xff0c;为各类高级系统&#xff08;如MES、调度系统、库位管理、立库等&#xff09;提供高效便捷的语音交互体验。 L…

(LeetCode 每日一题) 3442. 奇偶频次间的最大差值 I (哈希、字符串)

题目&#xff1a;3442. 奇偶频次间的最大差值 I 思路 &#xff1a;哈希&#xff0c;时间复杂度0(n)。 用哈希表来记录每个字符串中字符的分布情况&#xff0c;哈希表这里用数组即可实现。 C版本&#xff1a; class Solution { public:int maxDifference(string s) {int a[26]…

【大模型RAG】拍照搜题技术架构速览:三层管道、两级检索、兜底大模型

摘要 拍照搜题系统采用“三层管道&#xff08;多模态 OCR → 语义检索 → 答案渲染&#xff09;、两级检索&#xff08;倒排 BM25 向量 HNSW&#xff09;并以大语言模型兜底”的整体框架&#xff1a; 多模态 OCR 层 将题目图片经过超分、去噪、倾斜校正后&#xff0c;分别用…

【Axure高保真原型】引导弹窗

今天和大家中分享引导弹窗的原型模板&#xff0c;载入页面后&#xff0c;会显示引导弹窗&#xff0c;适用于引导用户使用页面&#xff0c;点击完成后&#xff0c;会显示下一个引导弹窗&#xff0c;直至最后一个引导弹窗完成后进入首页。具体效果可以点击下方视频观看或打开下方…

接口测试中缓存处理策略

在接口测试中&#xff0c;缓存处理策略是一个关键环节&#xff0c;直接影响测试结果的准确性和可靠性。合理的缓存处理策略能够确保测试环境的一致性&#xff0c;避免因缓存数据导致的测试偏差。以下是接口测试中常见的缓存处理策略及其详细说明&#xff1a; 一、缓存处理的核…

龙虎榜——20250610

上证指数放量收阴线&#xff0c;个股多数下跌&#xff0c;盘中受消息影响大幅波动。 深证指数放量收阴线形成顶分型&#xff0c;指数短线有调整的需求&#xff0c;大概需要一两天。 2025年6月10日龙虎榜行业方向分析 1. 金融科技 代表标的&#xff1a;御银股份、雄帝科技 驱动…

观成科技:隐蔽隧道工具Ligolo-ng加密流量分析

1.工具介绍 Ligolo-ng是一款由go编写的高效隧道工具&#xff0c;该工具基于TUN接口实现其功能&#xff0c;利用反向TCP/TLS连接建立一条隐蔽的通信信道&#xff0c;支持使用Let’s Encrypt自动生成证书。Ligolo-ng的通信隐蔽性体现在其支持多种连接方式&#xff0c;适应复杂网…

铭豹扩展坞 USB转网口 突然无法识别解决方法

当 USB 转网口扩展坞在一台笔记本上无法识别,但在其他电脑上正常工作时,问题通常出在笔记本自身或其与扩展坞的兼容性上。以下是系统化的定位思路和排查步骤,帮助你快速找到故障原因: 背景: 一个M-pard(铭豹)扩展坞的网卡突然无法识别了,扩展出来的三个USB接口正常。…

未来机器人的大脑:如何用神经网络模拟器实现更智能的决策?

编辑&#xff1a;陈萍萍的公主一点人工一点智能 未来机器人的大脑&#xff1a;如何用神经网络模拟器实现更智能的决策&#xff1f;RWM通过双自回归机制有效解决了复合误差、部分可观测性和随机动力学等关键挑战&#xff0c;在不依赖领域特定归纳偏见的条件下实现了卓越的预测准…

Linux应用开发之网络套接字编程(实例篇)

服务端与客户端单连接 服务端代码 #include <sys/socket.h> #include <sys/types.h> #include <netinet/in.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <arpa/inet.h> #include <pthread.h> …

华为云AI开发平台ModelArts

华为云ModelArts&#xff1a;重塑AI开发流程的“智能引擎”与“创新加速器”&#xff01; 在人工智能浪潮席卷全球的2025年&#xff0c;企业拥抱AI的意愿空前高涨&#xff0c;但技术门槛高、流程复杂、资源投入巨大的现实&#xff0c;却让许多创新构想止步于实验室。数据科学家…

深度学习在微纳光子学中的应用

深度学习在微纳光子学中的主要应用方向 深度学习与微纳光子学的结合主要集中在以下几个方向&#xff1a; 逆向设计 通过神经网络快速预测微纳结构的光学响应&#xff0c;替代传统耗时的数值模拟方法。例如设计超表面、光子晶体等结构。 特征提取与优化 从复杂的光学数据中自…