ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

Atlas 300V推理卡部署YOLO全流程:从环境配置到性能调优

Atlas 300V推理卡部署YOLO全流程:从环境配置到性能调优 说个真实情况我经常在技术群里看到有人问“Atlas 300V 24G 是运算加速卡吗”紧接着第二句基本都是“这东西能不能跑 YOLO”。这个问题很典型因为 Atlas 在华为昇腾产品线里其实是指一整个系列有人以为它是显卡有人觉得是 NPU还有人干脆把它当成一个带大显存的盒子。我陆陆续续在 Atlas 300V 上折腾过几轮 YOLO 部署从一脸懵到能稳定跑视频流推理中间踩了不少坑。这篇文章就把这卡到底是什么、怎么在上面把 YOLO 跑起来、以及那些文档里通常不会写的调优和排错经验一次性讲透。不管你是刚接触昇腾生态的算法工程师还是准备做边缘端视频分析落地的开发只要手上有一张 Atlas 300V尤其是 24G 版本想跑 YOLOv5/YOLOv8 这类检测模型这篇文章应该能帮你少走至少一周弯路。1. Atlas 300V 到底是一张什么卡1.1 先回答是运算加速卡但它的“24G”不是你想的那种显存直接说结论Atlas 300V 是一张 AI 推理加速卡也叫智能加速卡本质上是基于昇腾芯片的专用计算单元。这里有个关键点它不是 GPU没有图形输出接口不能插显示器也不是拿来跑 CUDA 的。那它是什么它是给数据中心服务器或边缘服务器做神经网络推理用的加速卡核心优势在于功耗低、体积小、国产化生态成熟。24G 这个参数很多人第一反应是“这不就是显卡的 24G 显存吗”其实它指的是板载内存规格是 LPDDR4X位宽和带宽跟 GPU 上的 GDDR 显存不是一个套路。但它的用途是一样的在推理时存储模型参数、中间特征图以及输入输出数据。24G 版本最大的实际意义是“能在不依赖 Host 内存交换的情况下同时加载多个模型或者塞进一个较大的动态维度模型”这一点我在后面讲多路并发时会再展开。有一点必须明确Atlas 300V 是推理卡不是训练卡。你想在这上面从零训练一个 YOLO那是找错工具了。训练还是得用 GPU 或者昇腾 910 系列训练卡300V 的定位是“把训练好的模型高效地跑起来”。1.2 为什么选 Atlas 300V 跑 YOLO 而不是用 GPU这几年轻量级推理卡的行情我一直有关注GPU 的价格和功耗让很多边缘场景吃不消尤其是一些做安防、智慧园区、工业质检的项目对单机功耗、机箱空间、采购成本都非常敏感。Atlas 300V 有很明显的定位优势标准半高半长 PCIe 卡大多数服务器直接插上就能用不需要额外的供电接口功耗大概在 72W 左右。如果你在一个有 8 个 PCIe 插槽的服务器上插满 8 张卡峰值功耗也只有 600W 不到而同等算力下 GPU 方案可能翻好几倍。更关键的是Atlas 系列在边缘场景的国产化适配做得早很多项目的信创要求会直接指定昇腾平台YOLO 这种目标检测模型在昇腾上的部署路径也已经非常成熟。当然我也得把丑话说在前头Atlas 300V 的软件生态跟 CUDA 完全两个世界。你之前写的torch.cuda全家桶在这上面基本失效凡是依赖 GPU 的算子都要换成昇腾的推理框架来跑。第一次接触的人会觉得“怎么这么麻烦”但习惯之后你会发现它其实有自己的一套清晰流程而且踩坑点相对固定。2. 部署 YOLO 前必须搞清楚的软件栈和生态2.1 从 CANN 到 ACL 再到 MindSpore Lite谁是谁很多新人一上来就想“把模型塞进去”结果被昇腾的软件栈直接绕晕。先花两分钟把这些英文缩写的关系理顺。CANN昇腾计算架构这个名字你会在华为官网反复看到。它是一整套东西的集合从底层驱动到上层中间件都包在里面。Driver 和 Firmware驱动和固件装 CANN 之前必须先装好负责让操作系统识别这张卡。装完之后用npu-smi info能看到卡的状态。AscendCLACL昇腾计算语言是底层 C/C API类似 CUDA Runtime后面我们写推理代码就是直接调用它。也有 Python 接口即 pyACL。MindSpore Lite华为的轻量化推理框架你也可以通过它加载.ms格式模型来推理相当于你之前用的 TensorRT。OM 模型离线模型文件是 ATC 工具把 ONNX/Caffe/TensorFlow 模型转换之后生成的文件运行时由 ACL 加载。YOLO 的部署流程可以概括为PyTorch 训练得到.pt- 导出成 ONNX - 用 ATC 工具转换成 OM - 在 Atlas 300V 上用 ACL 或 MindSpore Lite 加载 OM 推理。这条链路是目前我用下来最顺的。2.2 版本配套关系是最大的坑没有之一昇腾生态有一个显著特点版本之间强耦合。CANN 版本、Driver/Firmware 版本、MindSpore Lite 版本、PyTorch 适配版本它们之间有严格的配套关系。不是你随便下个最新版就能跑的。我见过太多人“卡在第一步”最后查下来全是版本问题。这里直接给一套我实测稳定运行的组合以当前主流版本为参考组件推荐版本示例操作系统Ubuntu 20.04/22.04 x86_64固件与驱动CANN 配套驱动包如 23.0.3CANN 工具包CANN 7.0.0或 6.3.xMindSpore Lite与 CANN 匹配的配套版本PyTorch导出用1.11~2.0仅需要在开发机上装提示装完驱动后第一件事就是跑npu-smi info确认系统能正确识别到 Atlas 300V 的芯片型号和显存容量。如果这里都没信息后面全白搭。2.3 开发机和部署机分开准备效率最高我在做这类项目时习惯把环境拆成两台机器一台有 GPU 的开发机用来训练模型和导出 ONNX另一台是插了 Atlas 300V 的部署机用来做 ATC 转换和推理验证。为什么这么拆因为 ATC 转换工具通常装在部署机上它安装的时候依赖 CANN如果部署机没有 GPU也没关系。这样最干净不会因为 CUDA 版本污染了昇腾环境。如果你只有一台机器又是直装 Ubuntu那我建议至少用 Docker 或 Conda 虚拟环境分开 Python 依赖不要在主环境里乱装包否则后面排查问题的时候你会想把电脑砸了。3. Atlas 300V 部署 YOLO 全流程实操3.1 安装驱动和 CANN两条命令确认环境可用环境准备阶段我按安装顺序来。首先装固件和驱动不同系列卡对应的安装包前缀不一样Atlas 300V 系列一般会在 CANN 软件包的“驱动固件”目录里。我用的是Ascend-hdk-...-aarch64/x86_64.run格式的包。# 解压安装包后进入驱动目录使用 root 执行 ./Ascend-hdk-*.run --full --quiet安装完成后重启或者重新加载驱动然后验证npu-smi info如果能列出类似“昇腾 310P”或者具体芯片型号、内存 24G 的信息驱动就 OK 了。注意如果之前装过其他版本驱动最好在安装前卸载干净./Ascend-hdk-*.run --uninstall。接下来装 CANN 工具包# 解压 CANN 包进入安装目录 ./Ascend-cann-toolkit_*.run --install --quiet安装完 CANN 之后需要 source 一下环境变量脚本source /usr/local/Ascend/ascend-toolkit/set_env.sh如果想每次终端自动生效可以把它追加到~/.bashrc里。这里要特别强调请务必确认驱动、固件、CANN 三者来自同一个版本目录。你说你驱动用了 23.0.RC2CANN 却下了 7.0ACL 初始化多半会报错。这种问题你排查半天都不一定能想到是版本不配套。3.2 PyTorch 模型导出 ONNX三个操作少一个都跑不通这一步是在开发机上做的。以 YOLOv5 为例官方export.py可以直接导出 ONNX但有几个地方要改。第一是启用 opset 版本。昇腾对 ONNX 算子支持范围有限我建议把 opset 固定在 11 到 13 之间。新版 YOLO 有些自定义算子会发现导出后有奇怪的节点转 OM 的时候报“Unsupported op”。第二是固定输入尺寸。尽量把模型输入固定成你推理时用的尺寸比如640x640。虽然 ATC 也支持动态维度的dynamic_dims但在 Atlas 300V 上动态维度会牺牲一部分性能而且配置起来麻烦。如果你只需要固定分辨率直接在导出时把宽高写死省心很多。第三是注意 batch 维度。你可以导出成 batch1 的模型多路并发时用多个推理实例Stream来处理。如果你确实需要动态 batchATC 配置要加--dynamic_batch_size但我在 300V 上实测动态 batch 切换会带来额外的资源申请开销小 batch 场景下收益不大。导出命令示例python export.py --weights yolov5s.pt --include onnx --opset 11 --imgsz 640 640导出后先用onnxsim优化一下能删掉很多冗余算子后面转 OM 的成功率会高不少pip install onnx-simplifier python -m onnxsim yolov5s.onnx yolov5s_sim.onnx3.3 ATC 转换从 ONNX 到 OM 是核心一步把简化后的 ONNX 拷贝到安装好 CANN 的部署机上开始转换。ATCAscend Tensor Compiler工具在 CANN 安装目录里# 切换到运行环境 source /usr/local/Ascend/ascend-toolkit/set_env.sh atc --modelyolov5s_sim.onnx \ --framework5 \ --outputyolov5s_640 \ --soc_versionAscend310P3 \ --input_shapeimages:1,3,640,640 \ --insert_op_confaipp.cfg \ --output_typeFP32解释几个关键参数framework5表示 ONNX 模型固定值别乱改。soc_version这是你芯片的型号。Atlas 300V 的芯片平台一般是 Ascend310P 系列你可以先跑npu-smi info看具体型号然后填对应的 SoC 字符串。填错会直接报错或转换出来的模型无法运行。insert_op_confAIPP 配置文件用来把图片缩放、减均值、归一化这些预处理算进模型里。这样做能让预处理和后处理分离在 CPU 侧省很多时间后面推理性能会更好。output_typeFP32模型输出保持 FP32后处理时精度损失小。如果你的推理场景对性能极敏感可以尝试 FP16但检测框的精度可能会有轻微下降。AIPP 配置文件aipp.cfg长得像这样aipp_op { aipp_mode: static input_format: RGB888_U8 src_image_size_w: 640 src_image_size_h: 640 csc_switch: false rbuv_swap_switch: false min_chn_0: 0.0 min_chn_1: 0.0 min_chn_2: 0.0 var_reci_chn_0: 0.003921569 var_reci_chn_1: 0.003921569 var_reci_chn_2: 0.003921569 }如果你的 YOLO 训练时用的是 COCO 数据集的归一化方式就用min_chn0和var_reci1/255。如果你用了自定义均值方差比如 ImageNet 的mean[0.485, 0.456, 0.406]还要在配置里写均值减法和方差除法不然模型精度会崩。转换成功的标志是当前目录下出现.om文件。转换失败的时候错误日志一般会告诉你哪个算子不支持。遇到这种情况优先回 ONNX 侧做算子替换或者改 opset别在 ATC 参数上死磕。3.4 用 AscendCL 写推理代码一套能直接抄的 Python 模板加载 OM 模型推理最推荐的方式是 pyACL。下面这个模板是我反复用到的基本换个模型路径就能跑。import acl import numpy as np # 初始化 ACL ret acl.init() assert ret 0, facl.init failed, ret{ret} # 设置设备0 号设备 ret acl.rt.set_device(0) assert ret 0, facl.rt.set_device failed, ret{ret} # 加载离线模型 model_path b./yolov5s_640.om model_id None ret acl.mdl.load_from_file(model_path, 0) assert ret 0, facl.mdl.load_from_file failed, ret{ret} model_id ret # 获取模型描述创建输入输出数据集 desc acl.mdl.create_desc() ret acl.mdl.get_desc(desc, model_id) input_size acl.mdl.get_num_inputs(desc) output_size acl.mdl.get_num_outputs(desc) print(finputs: {input_size}, outputs: {output_size})这里我只是展示了初始化和加载流程真正跑一次推理还需要创建acl.mdl.create_dataset、申请 device 内存、把数据拷贝进 device 内存再调用acl.mdl.execute最后取回输出。完整代码比较长建议直接参考华为官方的 pyACL 样例。实际开发中我用 pyACL 时最大的体会是它本质上就是在和“内存”打交道。什么时候申请acl.rt.malloc什么时候acl.rt.memcpy从 Host 到 Device什么时候释放这些如果没做过 C 系开发的人一开始会比较吃力。我的建议是直接用官方 example 改成自己的流程不要自己从零造轮子。3.5 后处理NMS 还是老一套但要留意输出张量顺序YOLOv5 的 ONNX 导出默认输出形状是[1, 25200, 85]以 640x640、COCO 80 类为例。但进入 OM 模型之后由于 AIPP 做了归一化输出解析时的置信度和坐标含义不变只是你的输入若是 RGB 顺序就别在代码里再转成 BGR不然颜色通道就乱了。后处理里的 NMS 我建议直接用 PyTorch 版校准过的算法逻辑然后把 NMS 放在 CPU 上跑。Atlas 300V 的强项是卷积/矩阵运算NMS 这类非算子上不会快把大部分目标框的筛选、排序放到 numpy 反而更灵活。如果你对性能要求高可以考虑在模型里内嵌部分后处理算子比如把 sigmoid、阈值过滤、甚至 NMS 都放到 ONNX 里导出再转 OM。但这种做法泛化性差我建议初期先把整条链路跑通性能优化放在后面。4. 性能调优与问题排查实录4.1 性能调优三板斧AIPP、批量推理、多实例并发先给一个我实测过的直观数字在一块 Atlas 300V24G上跑 YOLOv5s输入 640x640不做 AIPP、直接传 BGR 图像数据单线程推理大约在 10~15ms 一帧把 AIPP 预处理配好、并把 batch 提到 4 后等效速率能压到 5ms 以内一帧按 4 帧总耗时 20ms 计算。这数字拿来参考不同 CANN 版本、不同固件版本差异可能很明显但趋势是一致的。AIPP 的收益最大把图像 Resize、减均值、归一化全部下沉到硬件预处理单元后CPU 就被解放出来了而且 Host 端传输的数据量也更小。这属于“配置一次、永久受益”的优化。批量推理batch的收益次之Atlas 300V 的达芬奇架构在批量输入时算力利用率明显更高。但要注意显存占用24G 看着大YOLOv5s 一个模型才占不到 1G你可以放心把 batch 调到 8 或 16。不过 batch 越大预处理排队造成的延迟也会越高实际项目中要平衡。多实例并发是我最推荐压榨这张卡的方式。Atlas 300V 上可以创建多个推理 Stream每个 Stream 里加载一份模型副本然后让多个视频流任务各用各的 Stream互不阻塞。24G 内存的优势在这个场景下体现得淋漓尽致你甚至可以加载 YOLOv5s、YOLOv8m 两个模型做级联检测。4.2 新人最容易踩的 5 个坑按破坏力排序我把自己和周围同事踩过的坑整理成一张速查表按破坏力排序列出来问题现象原因解决版本不匹配ACL 初始化报错npu-smi info正常驱动/固件/CANN 版本不配套统一使用同一版本目录下的所有组件SoC 型号填错ATC 转换报错ATC 参数里的soc_version与芯片不符用npu-smi info确认芯片型号动态维度性能差batch 1 推理莫名其妙很慢输出层用了动态 batch 或动态分辨率固定输入尺寸必要时动态 batch 改为多 StreamAIPP 归一化配置错检测框偏了或置信度极低均值方差不匹配训练配置在 Python 本地先模拟 AIPP 预处理对比输出显存泄漏跑了几小时后卡死推理循环没有释放 ACL 输出内存检查每个acl.rt.malloc是否有对应acl.rt.free第一个坑是“隐藏信息”最多的。很多新手遇到报错就在网上问但其实翻一下/usr/local/Ascend/ascend-toolkit/latest/下的版本说明或者看 CANN 安装包名里的版本号大多数问题都能定位。4.3 实测经验一个视频流推理项目的完整复盘我之前帮一个智慧工地项目做人员安全帽检测优化客户现场服务器就是一张 Atlas 300V24G要同时跑 8 路 1080P 视频流检测算法为 YOLOv5s。整个方案的架构很简单用 FFmpeg 从 RTSP 拉流解码成 640x640 的 RGB 帧之后送入预处理的队列队列消费者从绑定的 Stream 里做模型推理再把结果画的框叠加到原始帧上回调给业务平台。一开始我直接用了 8 个线程每个线程各加载一个模型实例结果模型加载时间长达几十秒内存也吃紧。后来改成只加载一次模型用多 Stream 并发推理stream_list [] for i in range(8): stream acl.rt.create_stream() stream_list.append(stream)每个视频流对应一个 Stream任务提交到不同 Stream 上执行。实际测试下来 8 路 1080P 视频每路都能跑到 15FPS 以上CPU 占用只有 20% 左右。整卡几乎没有瓶颈如果视频路数再多一些还可以通过 batch 进一步压推理耗时。这个项目让我对 Atlas 300V 的定位有了更生动的认识它不像 GPU 那样适合做“单任务吃满卡”的暴力计算而是特别适合“多路并发、低功耗、低延迟”的工业视觉场景。4.4 定位优化方向时的经验技巧最后分享一个我个人很受用的技巧。当我觉得推理性能不达预期的时候我一般会做一次“分段时间统计”分别统计图像解码、Host 到 Device 拷贝、模型执行、结果拷贝回 Host、后处理这几段的耗时。昇腾在这一点上做得不错acl.mdl.execute可以和 Host 线程异步执行通过acl.rt.synchronize_stream做事件同步进而精确测量模型执行时间。如果发现耗时主要在数据拷贝上那优化方向就是 AIPP 和像素格式转换如果耗时在模型执行上那就调 batch 和 Stream 并发如果耗时在 NMS那就优化后处理比如提前做置信度阈值过滤减少进 NMS 的候选框数量。这个“分环节采样”的思路比单纯猜结果高效得多。我个人在实际操作中的体会是Atlas 300V 这套东西耐心花一两天把环境和转换流程理清后面就很顺了。最怕的不是踩坑而是遇到问题就怀疑卡坏了、怀疑模型不行、怀疑文档错了结果兜兜转转还是在版本和配套上打转。你只要按“驱动固件 - CANN - ONNX 导出 - ATC 转换 - ACL 推理”这个主线走每一步都验证到基本都能跑通。另外再留一个小建议跑通之后把npu-smi info的记录、CANN 版本、ATC 命令和推理脚本放到一个项目 README 里以后换机器、换环境或者给同事交付的时候会感谢现在的自己。
返回列表