尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

Atlas 300V 24G部署YOLOv5全流程:昇腾推理加速卡实战指南

Atlas 300V 24G部署YOLOv5全流程:昇腾推理加速卡实战指南 Atlas这个词做AI模型部署的人这两年应该不陌生。它不是一个单一的硬件而是华为昇腾整个AI计算平台的代号从边缘小盒子到服务器推理卡都有覆盖。我手头这块Atlas 300V 24G就是一张非常典型的PCIe形态AI推理加速卡常用于目标检测、图像分类、OCR这类模型的线上或边缘推理场景。最近两个热词问得很有代表性一个是atlas部署yolo一个是atlas 300v 24g是运算加速卡吗。后者其实是很多第一次接触昇腾的人都会有的疑惑因为这张卡长得像显卡但又不输出画面。我用它跑了一个完整的YOLOv5目标检测流程这篇就把整个过程、遇到的各种坑以及为什么这张卡值得关注一次性说清楚。1. 项目概述Atlas 300V 24G与部署YOLO这件事1.1 atlas 300v 24g是运算加速卡吗——先把结论放前面答案是是的它是一张运算加速卡准确说是一张AI推理加速卡。它和普通显卡的最大区别是不能接显示器也没有视频输出接口它存在的唯一意义就是帮CPU分担神经网络计算。详细点看规格。Atlas 300V 24G基于昇腾310P处理器板载24GB LPDDR4X显存接口是PCIe 4.0 x16整卡功耗控制在72W左右一般服务器插上就能用不需要外接辅助供电。24GB这个显存容量在同级别的推理卡里算比较宽裕的意味着可以跑比较大的batch或者用高分图比如2048x2048做推理。在算力层面它主要支持FP16和INT8两种主流推理精度。INT8的峰值算力明显高于FP16这也是为什么实际部署YOLO时很多人会把它转成INT8模型就是为了吃满这张卡的算力。这个点后面讲实操的时候还会再展开。从使用场景来说300V系列主要面向视频分析、安防、交通、工业质检、智慧园区这类场景。这些场景有一个共同特点对功耗和空间敏感但对端到端延迟的要求又比移动端高得多。用一张300V在服务器里做推理一台2U机器可以塞多张卡单路视频流可以做到多路并发很适合批量部署。1.2 为什么atlas部署yolo能成为热词YOLO系列在目标检测里的地位不用多说它几乎是所有硬件厂商做AI部署适配清单里的第一个模型。原因有三个一是模型结构相对规整卷积、BN、激活、拼接这些算子都是最基础的转换工具容易适配二是精度和速度的平衡点好可以被压缩到很小也可以放宽到高精度三是开源权重和训练生态太成熟随便拉一个yolov5s.pt就能直接用。atlas部署yolo之所以会成为一个高频热搜本质上是因为这个组合真的能打。在服务器CPU上跑一个YOLOv5s640分辨率一般也就二三十帧换成这张卡以后推理部分能做到百帧以上而且整卡功耗只有72W。对于要做一路人看视频流设备或者把现有服务升级成AI版本的开发者来说这个性价比和功耗优势非常直接。所以这篇博文后面讲的所有内容都围绕用一张Atlas 300V 24G把YOLOv5跑起来这一个目标。如果你是第一次接触昇腾照着操作就能把链路打通如果你已经部署过GPU版本这篇里很多转换和调优思路也能复用。2. 整体设计思路为什么部署YOLO要分三步走2.1 PyTorch模型不能被Atlas直接读取这是核心卡点如果你平时用GPU做推理脑子里最容易固化的路径是模型训练好以后直接用Python加载.pth然后就能跑。这套路径在Atlas上走不通因为昇腾的算力芯片不能直接执行PyTorch计算图它只能执行经过自研编译器生成的OM模型。OMOffline Model是昇腾统一的可执行模型格式相当于一个针对昇腾NPU做了一轮深度优化的二进制计算图。编译产物里不仅包含了算子的执行顺序还嵌入了算子的排布策略、内存复用计划、边缘设备上需要预分配的数据布局等等。这跟TensorRT的.engine很像只不过TensorRT的产物依赖特定GPU型号OM依赖特定昇腾芯片型号。所以标准的部署链路是这样把PyTorch权重导出成ONNX中间格式用CANN自带的ATC工具把ONNX编译成OM在推理程序里使用昇腾的运行时APIpyACL或者MindSpore Lite加载OM并执行。这就是整个部署链路最核心的三步走。中间为什么要插一个ONNX因为ONNX是硬件无关的中间表示PyTorch导出ONNX的生态最成熟而且ATC对ONNX的算子覆盖率也比直接吃PyTorch模型好。实际工作中绝大多数人都是走PT - ONNX - OM没有必要尝试把这个chain缩短。2.2 导出ONNX时的几个关键设计决策ONNX的导出并不总是一把梭就行尤其是要把模型送到ATC去编译时有三个决策在动手之前就应该想清楚。第一个决策是到底要不要把NMS非极大值抑制包含进ONNX里。YOLO的原始输出是一堆高密度预测框必须经过解码和NMS才能得到最终检出框。早期版本有人把NMS做成自定义算子塞进ONNX但ATC对NMS这类带逻辑分支的算子支持普遍不好经常报算子不支持。稳妥的做法是导出ONNX时只导出模型的主干和检测头NMS放在主机端用Python或C处理。虽然会多写一点后处理代码但换来的是转换链路稳定排查问题也方便。第二个决策是输入shape。ATC在编译时会把模型固定成一个静态shape所以导出的ONNX最好直接固定输入shape为1x3x640x640。如果你模糊地用动态shape导出是能导出的但ATC转换时十有八九会报错或者性能奇差。动态shape在昇腾上不是不能做但要用到AI CPU动态shape分支配置非常麻烦工程上收益不高新手不建议碰。第三个决策是预处理放哪一侧。YOLO常规的预处理是resize、归一化0到1、RGB转需要的通道顺序。这步可以在主机端用OpenCV做也可以在ATC阶段用AIPP配置做。AIPP是昇腾硬件预处理单元能把缩放、减均值、通道转换这些操作固化到输入之前既省CPU资源又减少host和设备之间的数据搬运。后面我会给一个AIPP配置介于新手阶段可以先用OpenCV处理先把链路跑通再优化到AIPP。2.3 方案选型为什么优先推荐YOLOv5而不是YOLOv8我这次选的是YOLOv5s作为演示模型不是因为它最好而是因为它最适合作为昇腾上第一个跑通的模型。YOLOv5的导出生态、算子种类、官方权重质量都非常稳定。YOLOv8虽然结构更新但检测头里有些解耦头结构个别算子在ATC下编译容易出幺蛾子需要额外修改。如果一开始就想挑战新版本我建议先把YOLOv5这条链路跑通再考虑迁移。另外一个选型点是模型大小。Atlas 300V 24G的显存很大但是算力是有限的。如果一上来就选YOLOv5x或者YOLOv8x虽然内存装得下但推理延迟会明显上升反而把硬件特点浪费了。我这次用的是yolov5s的官方权重方便后续和其他平台对比也方便大家复现。3. 实操过程从零开始把YOLO跑在Atlas 300V 24G上3.1 环境准备驱动、固件、CANN三者缺一不可昇腾环境三步装驱动Driver、固件Firmware、CANN工具包。驱动负责让操作系统识别NPU设备固件负责芯片底层控制CANN是最上层的开发套件里面包含ATC编译器、pyACL运行库以及各种工具。三者的版本之间是强对应的官方每个CANN发布说明里都会写明它配套的驱动和固件版本安装顺序也建议先驱动、再固件、最后CANN。装完以后先验证一下设备是否被识别执行npu-smi info。如果能看到一张300V卡并且显示设备健康状态、芯片信息和驱动版本说明底层的环境已经通了。我自己踩过的一个坑是系统里之前装过一个高版本的CANN后来换了低版本的驱动结果npu-smi能看到卡但ATC编译一直报device not open error。这种问题多半是驱动和CANN版本不匹配重新按照版本矩阵安装一遍即可。CANN的安装路径建议用默认的/opt/ascend目录。安装完成后需要source环境变量CANN会提供一个set_env.sh。在shell里执行source后运行which atc能定位到编译器就说明环境对了。这一步很多人忽略直接跳去转换模型结果系统提示找不到atc命令属于典型的新手问题。3.2 模型转换ATC命令与AIPP配置先导出ONNX。在YOLOv5官方仓库里最省事的方式是python export.py --weights yolov5s.pt --include onnx --opset 11导出时会固定输入维度为batch1、通道3、尺寸640x640输出的是三个检测头的输出不含NMS。导出完成后可以在Python里用onnxruntime加载验证一遍确认输出张量形状分别是1x255x80x80小尺度、1x255x40x40中尺度、1x255x20x20大尺度其中255的计算方式是3 * (5 80)即3个anchor、4个坐标加1个置信度加80个类别。验证这一步很重要后面如果发现OM输出结果不对至少能确定问题出在ATC之前还是之后。接下来是ATC转换。我这里用的命令是atc --modelyolov5s.onnx \ --framework5 \ --outputyolov5s_310p \ --soc_versionAscend310P3 \ --input_shapeimages:1,3,640,640 \ --insert_op_confaipp.cfg \ --output_typeFP32逐个参数说一下。framework5表示输入是ONNX模型。output是生成OM的文件名前缀。soc_version很重要300V系列对应的昇腾芯片是310P不同批次还有P1/P3细分。如果你不确定用npu-smi info查看芯片型号或者直接报错后再根据错误信息调整。input_shape必须和导出ONNX时的shape一致。insert_op_conf指向AIPP配置文件。output_typeFP32是让模型的输出保持FP32精度方便Python后续处理。AIPP配置可以这样写aipp_op { aipp_mode: static input_format: RGB888_U8 src_image_size_h: 640 src_image_size_w: 640 csc_switch: true mean_chn_0: 0 mean_chn_1: 0 mean_chn_2: 0 var_chn_0: 255 var_chn_1: 255 var_chn_2: 255 }这套配置的含义是输入图像按RGB888排列的U8数据固定尺寸640x640不做裁剪开启通道转换均值为0方差为255也就是直接在硬件上完成除以255的归一化。如果你是先做resize再喂给AIPP那么src_image_size_h/w要和实际输入尺寸对应。如果preprocessing用OpenCV做那这段AIPP配置可以暂时不插入直接在Python里做归一化会简单一些。转换成功后会生成yolov5s_310p.om。同时终端会打印出模型输入输出信息工具会给出每一个输出的名称、尺寸、dtype这些信息对后面写推理代码至关重要建议截图保存起来。3.3 pyACL推理代码最小可运行骨架OM拿到手以后写推理代码。昇腾官方的Python接口是pyACL用法思路和CUDA很像也有init、set_device、alloc_mem、memcpy、execute这样的概念。我直接给一个最简骨架# 以下代码是链路示意真实工程里每个tensor都要单独分配设备内存并构造dataset import acl import numpy as np import cv2 # 1. 初始化 acl.init() acl.rt.set_device(0) context acl.rt.create_context(0) device_id 0 # 2. 加载模型 model_id acl.mdl.load_from_file(yolov5s_310p.om) model_desc acl.mdl.create_desc() acl.mdl.get_desc(model_desc, model_id) # 3. 获取输入输出形状 input_size acl.mdl.get_input_size_by_index(model_desc, 0) output_size acl.mdl.get_output_size_by_index(model_desc, 0) # 4. 准备数据 image cv2.imread(test.jpg) image cv2.resize(image, (640, 640)) image image.astype(np.float32) / 255.0 image np.ascontiguousarray(image) in_data acl.util.numpy_to_ptr(image) out_data np.zeros([1, 25200, 85], dtypenp.float32) # 注意实际输出形状以ATC打印的为准这里示例写的是NMS后拉平前的统一形状 # 5. 执行推理 ret acl.mdl.execute(model_id, in_data, input_size, out_data, output_size)这段代码我需要强调两点。第一输出形状不要想当然。ATC转换后日志里会打印每个输出tensor的shapeyolov5s没带NMS时通常输出三个分离的feature map分别是1x255x80x80、1x255x40x40、1x255x20x20而不是一个拉平的25200x85。我这版骨架里用一个25200x85写例子是为了说明流程务必以实际打印为准。第二由于OM的输入是NCHW排列而OpenCV读出来是HWC处理好通道序后再喂给NPU。如果你用了我上面的AIPP归一化配置输入数据不能再做除以255否则就是双重复处理检测结果会异常。推理完成以后输出的特征图在CPU端做decodeyolov5的decode逻辑网上有很多实现核心是按anchor和stride把中心点坐标还原成box坐标过滤低置信度框再做class-wise NMS。这一步用Python写不会太慢因为模型的绝大部分计算已经交给NPU了。3.4 性能实测与数据对比我把跑通以后的数据列一下供大家参考。测试环境是X86服务器一张Atlas 300V 24GCANN 6.3.xYOLOv5s官方权重FP16推理输入640x640batch1。纯模型推理部分不包含Python后处理稳定在140 FPS以上包含decode和NMS的端到端流程大概在90 FPS上下。换成INT8量化模型后纯推理速度还能再提升一截接近200 FPS的量级。同环境CPU对比就更有说服力。同服务器双路CPU用ONNX Runtime跑同一个模型端到端大概只有20 FPS出头。也就是说一张72W的Atlas卡顶掉了整颗服务器CPU的算力功耗却只有三分之一不到。这就是为什么要单独在服务器里加推理卡而不是靠堆CPU实现AI服务。4. 常见问题与排查技巧从转换到运行的避坑指南4.1 转换阶段的高频错误ATC转换失败是大家在昇腾上遇到的第一座大山。排第一的错误是算子不支持或者E19999之类的通用报错。这类错误常见于ONNX里带了NMS、用了较新版本的opset、或者模型里有自定义层。解决思路不是去硬编译而是先把模型里的高风险算子干掉。我遇到最多的情况就是带NMS的YOLO导出换成不带NMS的导出后一次通过。排第二的是soc_version填错。很多人不看设备信息直接抄网上的命令填Ascend310结果报设备类型不匹配。Atlas 300V系列请先npu-smi查型号然后去CANN的文档里确认对应的soc_verison字符串不同批次对应值略有差别。排第三的是shape不一致。ATC编译时报shape error基本就是你input_shape和ONNX内部实际shape对不上。用onnx.load配合onnx.shape_inference先打印一遍输入输出所有信息一目了然。4.2 运行阶段的典型问题模型加载成功了但推理结果全为0或者错得离谱。这类问题的根因十有八九在预处理。要么是归一化做了两次要么是通道顺序错了要么是输入的数据类型不对。用一个输入全等值图像的方式去自测比如全白图、全黑图、纯红色图看输出是否符合直觉这是定位预处理问题最有效的方法。还有一种常见情况是报ACL内存错误比如aclrtMalloc failed或者缓存的指针越界。这类错误多半是因为你用了零拷贝的方式往设备端塞数据但数据长度和模型期望的input_size不一致。最好用acl.mdl.get_input_size_by_index去真正读取模型期望的字节数而不是自己在代码里猜。推理速度比预期慢也要排查。如果发现纯推理只有几fps多半是因为CANN环境变量没有生效程序实际在用CPU的AI CPU模拟算子执行而不是NPU。跑代码之前确认source了set_env.sh并且在日志里能看到设备初始化成功。4.3 问题排查速查表阶段典型现象常见原因解决办法转换报E19999/找不到算子ONNX带NMS或自定义层去掉NMS导出干净ONNX转换soc_version不匹配芯片型号填错npu-smi info确认后改配置转换shape error动态shape或input_shape不一致用onnx.shape_inference核对运行输出全0/全乱预处理重复或通道错误自测全色图逐项核对运行内存错误数据长度不等于模型期望用get_input_size_by_index性能速度极慢环境变量未生效走了CPU算子排查set_env.sh和日志4.4 三条独家调优建议调优阶段我的顺序一般是先用AIPP把预处理从CPU搬到硬件再把batch从1提高到4或8榨干PCIe带宽最后做INT8量化。这三步按顺序做往往能叠出两倍以上的吞吐提升。特别提一下AIPP。AIPP最大的优势不是省CPU而是省时间。host端resize加50%的耗时都很常见硬件预处理单元基本不影响主链路。但AIPP的配置容易把人绕晕尤其是mean和var的数值范围。常规YOLO是除以255AIPP里的var_chn填255就对了。INT8量化要借助AMCT工具链流程比ONNX直接转OM复杂一点。我的建议是如果FP16已经能满足延迟要求就没有必要上INT8。INT8对精度的影响在不同模型上差别很大目标检测这种任务尤其需要重新评估mAP。工程上优先够用而不是追求极限。5. 写在最后的一点个人经验跑通Atlas部署YOLO这件事回过头来看真正难的不是NPU运算本身而是适应一套和GPU完全不同的工程习惯。第一次接触昇腾的人最应该改掉的习惯就是从网上抄一段代码就跑因为CANN的版本差异太大接口也在迭代旧教程里的API很可能已经不适用了。我自己的经验是把官方文档当作第一手资料先把环境版本对齐再用ATC打印的信息反向推导代码里的shape最后再用一个小数据集做端到端验证。这套流程虽然慢一点但每一步都是可控的。另外Atlas 300V 24G这张卡最吸引我的地方不是纸面算力而是24GB容量加上低功耗的组合。很多做多路视频分析的人真正缺的往往不是算力而是显存和单路功耗。24GB意味着可以塞更多路数、更大分辨率72W意味着服务器散热压力小甚至可以多卡插满。如果你手上有长期运行的AI推理服务没有特别强的生态依赖这张卡确实是一个值得认真考虑的选择。
返回列表