ARTICLE DETAIL

资讯详情

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

Atlas 300V 24G部署YOLOv5实战:从ONNX到ACL推理

Atlas 300V 24G部署YOLOv5实战:从ONNX到ACL推理 手里这块Atlas 300V 24G推理卡已经连续跑了大概一周的YOLOv5检测任务中间换了三版模型、踩了不少坑目前整条链路算是稳定了。趁着机器还没拆把从硬件认识、环境部署到模型上卡的完整过程梳理一遍正好回应一下最近总被问到的两个问题Atlas 300V 24G到底是不是运算加速卡以及YOLO系模型在这类设备上到底怎么落地。先说结论Atlas 300V 24G是一张标准的PCIe形态AI推理加速卡它和常见游戏卡、工作站显卡最大的区别在于它不是靠CUDA core跑通用计算的GPU而是基于昇腾310P系列芯片的专用推理卡。YOLOv5、YOLOv8这类检测模型想在它上面跑起来不能直接拿PyTorch权重去推理必须走完整的“PyTorch导出ONNX再通过ATC工具转成OM格式最后用ACL或MindX SDK加载执行”这条链路。这篇就把这条链路每一步掰开讲清楚。1. Atlas 300V 24G到底是什么先把它看透了再动手1.1 一张“看起来像显卡”的推理卡Atlas 300V 24G从外观上是标准的半高半长PCIe卡插在服务器或者工控机里都很方便。很多第一次接触的人会下意识把它和GPU划等号这个理解算对了一半关键要分清“推理卡”和“通用计算卡”的区别。它的核心是昇腾310P系列芯片主要面向AI推理场景。官方标称的INT8算力在百TOPS级别显存也就是设备内存给到了24GB带宽大概在204GB/s级别典型功耗只有七十多瓦。这套参数放在推理场景里非常有竞争力功耗低、体积小、单卡能装下不少模型。有个细节很容易被忽略Atlas 300V 24G严格来说是PCIE接口的推理加速卡常见型号和软件栈对应的是Ascend 310P系列SoC。它的内存是板载的不会占用主机内存24GB这个容量对于YOLOv5s、YOLOv8m这类模型来说绰绰有余甚至多个模型加载到同一张卡上做并发推理都没问题。我实际测试下来单张300V 24G跑YOLOv5s输入640x640预处理走DVPP、后处理走CPU单卡大概能跑到几百帧每秒的量级具体数值和Batch大小、模型复杂度强相关这个后面专门讲。1.2 “运算加速卡”这个热搜词背后大家真正纠结的是什么最近很多人搜“Atlas 300V 24G是运算加速卡吗”说明大家对这类硬件的定位还是有困惑。我理解这个疑问来源于三个方面。第一是能不能用来训练模型。明确回答用它做训练不现实一是软件生态没有为训练场景做太多优化二是芯片设计本身就更偏向推理的能效比。如果你手里的任务是训练那还是老老实实选GPU或者用昇腾的Atlas训练卡系列。第二是能不能像GPU那样直接用PyTorch跑。答案是不能。PyTorch原生的算子体系并不能直接在昇腾NPU上执行。要么通过昇腾适配过的PyTorch框架跑要么把模型导出成ONNX再转换成NPU认识的OM格式。对于部署YOLO这种场景后者更常见、更可控。第三是它和普通独立显卡的驱动方式完全不同。显卡插上装驱动就能用Atlas 300V需要安装一整套CANN工具包里面包含了驱动、固件、运行时库和模型转换工具链。这也是很多新手第一次上手时感觉“不像显卡那么友好”的原因。从功能角度讲它就是一台专用的AI推理加速器和“运算加速卡”这个说法完全对得上但请务必先管理好预期它是推理卡不是训练卡也不是通用GPGPU。1.3 用一张表和GPU做个快速对比放一张实际使用中我对两者的体验对比方便还没上手的人做选型判断。对比维度Atlas 300V 24G常见GPU推理方案芯片类型昇腾310P系列 NPUNVIDIA GPU软件栈CANN、ACL、MindX SDKCUDA、TensorRT模型格式OM通过ATC转换Engine/TRT社区生态比较成熟推理部署资料多2. 为什么要在Atlas上部署YOLO以及模型落地的基本思路2.1 成本、功耗、体积的三角优势很多人问图什么。举个例子我之前在一台塔式服务器里插了两块300V 24G做视频流检测整机功耗比原来单张工作站显卡的方案还要低不少而且两张卡可以并行处理多路视频流单路成本非常可观。如果是做边缘计算、智慧园区、工业质检这类有明确功耗和空间限制的项目Atlas 300V 24G这种半高卡的优势很明显不用改机箱、不用上水冷、PCIe插上就能用一台普通工作站能带好几张。当然它也有明显的短板。软件生态相比CUDA体系确实还有差距很多新算子需要等版本适配调试手段也不如NVIDIA的工具链丰富。但如果你的核心任务就是跑YOLO系列检测模型那Atlas完全够用而且批量部署成本能压得比较低。2.2 昇腾NPU不认识PyTorch理解ONNX这个中间层YOLO模型从PyTorch权重到在Atlas上跑起来路径大概是这样的PyTorch权重 - 导出ONNX - ATC工具转换 - OM模型 - CANN Runtime加载推理ONNX在这里就相当于一个“公版交换格式”。无论你原来是用YOLOv5官方仓库、YOLOv8的ultralytics包还是自己魔改的网络结构先统一导出成ONNX然后再交给昇腾工具链处理。这里有个关键认知要建立模型不是“翻译”过去的而是经过ATC做了一次算子级编译。ATC会把ONNX/开源框架的算子映射成昇腾NPU能执行的算子并在这个阶段做算子融合、内存复用等优化。所以转换结果好不好很大程度上取决于ONNX导出的质量。我之前看到有人拿着从PyTorch直接保存的.pt文件就想往Atlas上跑那肯定跑不起来的方向就错了。2.3 理清CANN、ATC、ACL、MindX SDK这几个概念新手最容易在这几个名词上绕晕。简单做个拆解。CANN是昇腾计算架构的总称相当于CUDA这个层级。它里面包含了驱动、runtime、算子库、图编译工具等所有东西。装好CANN之后你的系统才“认识”这张卡。ATC是CANN里的模型转换工具全称Ascend Tensor Compiler。它的职责是把ONNX等格式的模型转换成OM格式。绝大多数模型部署的报错时间都花在ATC这一步。ACL是昇腾的计算接口层类似CUDA Runtime API。写推理代码时调用aclmdc...这种接口加载模型、准备输入输出、触发推理。MindX SDK则是一套更高层的推理开发框架可以用配置文件组合各种“插件”来完成预处理、推理、后处理全流程适合快速做推理服务。我的个人建议是核心流程先用ACL手动跑通理解每一步在干什么再决定要不要上MindX SDK。上来就套SDK出问题反而难排查。3. 完整部署流程从ONNX导出到YOLOv5在300V上出结果3.1 环境准备Ubuntu、CANN、驱动固件一步都不能乱我这次用的环境是Ubuntu 22.04 LTS内核版本和CANN的兼容性最好。如果打算照搬我的流程建议用干净的服务器或者工作站不要拿自己日常开发用的笔记本直接折腾因为CANN安装后会对环境变量、内核模块有要求搞乱了会影响其他开发。安装流程大致分四步到昇腾官方渠道下载对应版本的CANN工具包我选的是商用版因为兼容性和稳定性比社区版更好一些生产环境更省心。按照官方文档顺序安装固件和驱动再安装CANN toolkit。顺序不能反先固件驱动再toolkit。配置环境变量让CANN的toolkit下的各类命令和运行库可以被系统找到。主要就是source安装路径下的set_env.sh脚本。安装Python版本的ACL接口也就是python端的昇腾runtime库方便后续写推理脚本。装完之后最关键的一步是验证硬件是否被正确识别。命令行输入npu-smi info如果能看到卡的型号、芯片ID、内存信息就说明驱动和固件都正常。看的时候留意一下“Chip Count”和板卡状态是不是OK如果这里是异常状态直接在网上搜相关的报错信息就能定位。注意CANN版本和固件驱动版本是有配套关系的。别自己随意混搭特别是24G版本对应的固件版本装错了大概率npu-smi直接看不到卡排查起来很折磨。3.2 导出ONNX时的三个关键细节我用的是YOLOv5的官方仓库版本是最新的v7.0。模型选的yolov5s输入尺寸固定为640x640。运行导出命令python export.py --weights yolov5s.pt --include onnx --img-size 640 640 --batch-size 1导出本身很简单但有几个细节会直接影响后续ATC转换的成败和推理性能。第一个关键点是“尽量导出不带后处理的版本”。YOLOv5官方仓库提供两种导出粒度一种是带NMS后处理分支的一种是纯粹的主干检测头结构。在Atlas上我强烈建议只导出纯检测网络也就是让输出直接是原始的预测特征图把置信度阈值过滤、NMS这些后处理全部留在主机CPU端做。原因有两个。一是昇腾NPU在做NMS这类动态算子上效率没那么高ATC转换时也容易碰到算子不支持的报错二是把后处理放在CPU上调参和调试都直观得多。你可以根据置信度阈值反复调整不需要重新转模型。第二个关键点是固定Batch Size和输入尺寸。ONNX导出时batch size1最省事ATC转换也不需要额外配置动态Batch。如果你确实需要动态Batch也不是不能做但后续推理代码要处理内存对齐和维度变化复杂度直接上一个台阶。第三个关键是确认ONNX模型的输入输出。导出之后我习惯先看一下模型结构import onnx model onnx.load(yolov5s.onnx) for inp in model.graph.input: print(inp.name, [d.dim_value for d in inp.type.tensor_type.shape.dim]) for out in model.graph.output: print(out.name)YOLOv5的输入名通常是images输出是三个尺度的检测头输出。记下输入名和输出名ATC转换时会用到。3.3 ATC转换实操核心命令和参数解析ONNX导出没问题后核心操作就是ATC转换。我最终跑通的转换命令是这样的source /usr/local/Ascend/ascend-toolkit/set_env.sh atc --modelyolov5s.onnx \ --framework5 \ --outputyolov5s_bs1 \ --soc_versionAscend310P3 \ --input_shapeimages:1,3,640,640 \ --logerror逐项说一下这些参数的含义方便你自己改。--framework5 表示输入模型是ONNX格式。这个数字是固定的不用变。--soc_versionAscend310P3 这个要注意不同型号的Atlas加速卡对应的SoC版本不一样。300V系列一般是310P。如果填错转换时大多会报“unsupported soc version”之类的错误。查准确值最直接的办法是看npu-smi info输出到的芯片型号再对官方文档确认。--input_shape 用来说明输入张量的维度。如果导出的ONNX已经是固定shape这里基本是照抄。我测试过如果不写这个参数ATC也能转换但很多时候会因为shape推断不明确而失败所以这里最好显式写出来。--logerror 设置日志级别为error。初次转换不建议直接用error先用默认或者info级别万一报错信息更全。如果你对模型算子兼容性有把握可以用error减少日志干扰。转换成功后会生成一个yolov5s_bs1.om文件。这里有个判断标准体积一般在几十MB如果输出文件只有几KB大概率是转换失败或者生成的是空模型。有几次转换报错提示某些算子不支持。我的常规处理是先在官方支持的算子清单里查一下有没有替代方案如果没有就看能不能修改模型结构避开这个算子。最后一招才是升级CANN版本。千万不要盲目升级每次升级都可能带来新的兼容性回归。3.4 推理工程用ACL把OM模型跑起来OM模型只是“编译器产物”要真正在Atlas上出结果还需要写推理代码。这里推荐用Python版本的ACL接口来做代码量相比C少很多逻辑也更清晰。先写一个初始化部分import acl import numpy as np # 初始化 ret acl.init() ret acl.rt.set_device(0) context, ret acl.rt.create_context(0) # 加载模型 model_id, ret acl.mdl.load_from_file(yolov5s_bs1.om)这里第一步acl.init()是初始化整个运行环境然后set_device指定使用哪张卡create_context创建上下文最后load_from_file加载模型。注意set_device的入参是设备ID如果你有多个卡按0、1、2往下排。加载模型之后需要为输入输出分配内存。ACL对内存有对齐要求直接调用acl预留的接口分配device内存input_desc acl.mdl.create_tensor_desc(model_id, 0) # 第0个输入 output_desc acl.mdl.create_tensor_desc(model_id, 0) # 这里原来是输出数量 input_size acl.mdl.get_tensor_desc_size(input_desc) output_size acl.mdl.get_tensor_desc_size(output_desc) input_buffer, ret acl.rt.malloc(input_size, 2 * 1024 * 1024) output_buffer, ret acl.rt.malloc(output_size, 2 * 1024 * 1024)malloc的第二个参数2MB是对齐粒度这是ACL的常见要求不能省。很多新手在这里直接用numpy数组然后传到推理接口会报内存错误就是因为没有走device内存分配。推理部分如下# 假设py_tensor是你预处理好的numpy数组类型为float32归一化到0-1 acl.rt.memcpy(input_buffer, input_size, py_tensor.tobytes(), input_size, ACL_MEMCPY_HOST_TO_DEVICE) # 同步执行 ret acl.mdl.execute(model_id, input_buffer, input_size, output_buffer, output_size) # 拷贝结果回主机 out_tensor np.zeros(output_size, dtypenp.uint8) # 具体类型看模型输出 acl.rt.memcpy(out_tensor, output_size, output_buffer, output_size, ACL_MEMCPY_DEVICE_TO_HOST)拿到原始输出后再自己做后处理。YOLOv5的输出结构是每个检测头的特征图需要先解码出bbox坐标和置信度再做NMS。这部分代码和通用YOLOv5后处理逻辑一致网上有很多现成实现不赘述。注意如果模型输入是RGB且做了归一化那预处理时要把图片尺寸缩放成640x640并转成CHW顺序同时做一个维度变换确保是NCHW。这步搞错推理出来的框就会完全乱掉。如果想在实际项目里少写代码也可以升级用MindX SDK的pipeline方式。它把预处理、推理、后处理都做成了插件配置文件里写清楚就行。但对第一次上手的人还是建议先走ACL流程把原理搞明白。4. 性能调优与问题排查为什么你的卡跑不满4.1 一次真实的推理耗时拆解很多反馈“Atlas卡性能也就那样”的人其实问题并不在卡而在整条数据处理链路。我把一次推理的耗时按阶段做了个拆解你会发现大头往往不在NPU计算本身。以YOLOv5s、640x640输入、batch size1为例阶段耗时占比说明图像解码与缩放约20%如果用CPU做OpenCV解码和resize耗时明显H2D拷贝约10%主机到设备的内存拷贝数据量不大但也有成本NPU推理约30%这阶段耗时其实很稳定优化空间有限D2H拷贝约5%设备到主机的拷贝后处理阈值过滤NMS约35%纯CPU执行建议用向量化或并行优化这个拆解告诉我们一个重要的调优方向如果想提升“端到端”吞吐重点不是抠NPU推理那几十毫秒而是把预处理和后处理优化好。比如预处理可以交给昇腾的DVPP硬件加速模块后处理可以用numpy向量化替代python循环。我实测过同样的模型和输入纯Python后处理耗时大约占整条链路的一半以上。后来改成numpy向量化后处理整体吞吐提升接近一倍。这个方向经常被忽略。4.2 5个高频报错与处理办法这里整理一下我在部署过程中遇到最频繁的几类问题每个都给排查思路。ATC转换报错提示算子不兼容。这类问题常见于新版本的YOLO模型用到了一些昇腾工具链还没有适配的算子。第一步是更新CANN到最新版本看是否已经补上。如果没有考虑是否能把模型结构做简化比如去掉不需要的mish激活函数改成别的。再不行就在ATC命令里设置算子精度为fp16有时候能绕过某些算子限制。转换时提示shape推断失败。通常是动态shape导致的。建议导出ONNX时就固定shape。如果一定要用动态shape需要在ATC命令中加入动态输入参数并确保后续推理代码正确设置。推理时内存报错。最常见的原因是输入输出buffer没有走ACL的device内存。普通numpy数组不能直接传给推理接口。另一个原因是buffer大小没有从tensor desc获取自己硬编码尺寸一旦模型输入调整就会爆掉。npu-smi看不到卡。优先检查驱动和固件安装顺序是否正确再看内核模块是否加载成功。有时候服务器重启后需要重新加载驱动模块执行下对应脚本即可。输出结果全是垃圾值。十有八九是数据格式问题。要么是NCHW和HWC搞错要么是预处理归一化方式和模型训练时不一致还有可能是输入图像没有正确缩放到模型要求尺寸。逐一排查即可。4.3 YOLOv5和YOLOv8在Atlas上的差异顺手说说YOLOv8。ultralytics仓库导出的ONNX结构和YOLOv5差异不小主要体现在检测头和解码部分。如果在Atlas上部署YOLOv8要特别注意导出时的“nms”选项建议同样只导出主网络不要带后处理分支。YOLOv8的ONNX导出命令大概是yolo export modelyolov8s.pt formatonnx imgsz640导出的模型输入名一般叫images输出数量也是三个。ATC转换方式和YOLOv5基本一致只要soc_version写对就行。实际测试中YOLOv8s在300V 24G上的性能和YOLOv5s相差不大主要还是看算子融合效果。如果觉得YOLOv5和YOLOv8都还不够快可以考虑用昇腾的MindX推理框架它对部分检测模型做了更细粒度的算子融合和内存复用优化。但对初上手的人先能用起ACL流程再考虑进阶优化。5. 最后再分享几个经验这一周多折腾下来我最大的感受是Atlas这类NPU推理卡不是不能用而是需要接受“按它的规则做事”这件事。它和GPU生态有差异但一旦模型转换通了、推理链路理顺了后续的稳定性和功耗表现是真的很出色。给还没上手的读者两个建议。第一刚开始不要同时追新版的CANN和新版的YOLO先用稳定的工具链组合把流程跑通再去升级版本。我这次就吃过亏一开始装了最新的CANN测试版结果和YOLOv8导出结构有兼容问题排查了很久最后退回稳定版一下就通了。第二模型转换前一定要确认ONNX的输入输出是否符合预期这一步多花十分钟后面能省几个小时。项目后续我打算再继续做两件事一是把预处理移到DVPP上进一步压一压端到端延迟二是把当前这版推理封装成HTTP服务给业务方调用。Atlas 300V 24G的24GB内存其实还有很大余量后续可以把多个模型同时装载、按需调度单卡能发挥的价值远比现在更大。
返回列表