ARTICLE DETAIL

资讯详情

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

Atlas 300V上部署YOLO:从ONNX到OM的推理全流程实战

Atlas 300V上部署YOLO:从ONNX到OM的推理全流程实战 1. 项目整体拆解1.1 “Atlas 300V 24G 是运算加速卡吗”——先把这个热搜词说透先说结论是的但更准确的说法是它是一张专为AI推理场景设计的加速卡不是通用的图形计算卡GPU。很多人一看到“24G”就下意识联想到上次买的那块游戏显卡想着插上去就能跑CUDA、能炼丹这个认知偏差在第一天上手Atlas板卡时特别容易翻车。Atlas 300V 24G是昇腾生态下的一个产品型号核心芯片是昇腾310P系列板载24GB显存别的什么都可以不查这个G内存是你跑YOLO模型时最需要盯着的指标。24G能干什么以YOLOv5s为例FP16精度转成OM模型之后模型文件大约25MB左右即便加上预处理缓存、后处理输出缓冲、整个MindX SDK推理流水线的常驻内存实际单实例占用通常不超过2GB。这意味着理论上你可以在单卡上并行跑多个实例或者直接上一个更大的模型比如YOLOv7、YOLOv8m甚至带Transformer检测头的变体。但是这里有个容易误解的点Atlas 300V不是给训练用的它的目标场景是推理——也就是模型已经训好了你要把它“部署”到某个业务环节里做实时或批量推理。它没有CUDA核心那一说也不吃你熟悉的PyTorch直接写的模型文件。寄过来的模型得先过一遍模型转换工具链变成昇腾自己的中间格式才能在卡上跑起来。这是很多从GPU阵营转过来的人第一道要过的坎。再说回部署YOLO这件事。在Atlas 300V上跑YOLO本质上是一个“从训练框架到推理硬件”的迁移过程。你需要处理的不是训练技巧而是模型导出、格式转换、算子对齐、推理编排。整条链路捋顺了之后性能其实相当能打单张300V跑YOLOv5s的端到端推理延迟能做到15毫秒以内含预处理和后处理吞吐量在大batch下能有不错的提升具体数字后面会讲。这篇文章就把这条链路从零开始拆开每一步都给你讲清楚为什么这么做、怎么做、踩了哪些坑。1.2 为什么选Atlas 300V做YOLO部署选这张卡做YOLO部署通常不是因为它的跑分数据最漂亮而是因为它切中了几个很实际的场景需求。第一单卡显存大性价比突出。24G显存放在推理卡里算很大了这意味着你可以把整张卡全部交给一个高分辨率模型也可以分给多个实例。尤其是YOLO系列在航拍图、遥感图、高分辨率工业质检图上input size经常要推到1920x1080甚至更大这时候显存就不只是容量问题而是能不能跑起来的问题。第二功耗和散热环境友好。Atlas 300V的设计功耗大约在72W到100W之间不同版本略有差异相比动辄两三百瓦的GPU它对服务器机箱、电源、散热的压力小很多。很多边缘机房、一体机工控机箱里甚至不需要额外改造插上就能跑。第三生态工具链在快速补齐。CANN、MindX SDK、MindIE这一套工具看下来至少对YOLO这种高频模型文档、例程、社区排错帖已经积累到可以照着做而不至于绝望的程度了。当然和CUDA生态比还有明显差距但这是后话后面会展开讲哪些地方能省力、哪些地方只能硬啃。第四也是最重要的一点你手里已经有这张卡或者单位采购了这类硬件。硬件已经在那了与其纠结“为什么不是GPU”不如把这张卡能发挥的性能真正榨出来。这篇文章就是干这个事的。1.3 整体部署架构梳理在Atlas 300V上部署YOLO完整链路可以拆成五个环节每个环节你都可以对照检查自己卡在哪一步模型准备训练好的权重通常是PyTorch的 .pt 文件有时候是 ONNX 文件。模型导出把PyTorch模型转成ONNX这一步要做算子对齐和精度校验。格式转换用ATC工具把ONNX转成昇腾的OM模型格式这是整个流程里最容易出问题的一步。推理编排写推理代码或者用MindX SDK的pipeline把预处理、推理、后处理串起来。上线调优做性能压测调整batch size、并发路数、内存分配策略搞定上线。这五个环节每一步都有它的坑。我见过很多人在第二步和第三步之间反复折腾好几天的也有在第四步莫名其妙发现推理结果全错的。下面的章节我会把每一步的关键点、代码、配置、排查方法全部展开给你一条可以直接照着走下去的实操路径。2. 环境准备与工具选型2.1 硬件确认和环境依赖清单在动手之前先确认你手里的板卡型号和驱动版本。用下面这条命令就能看到卡的当前状态和芯片信息npu-smi info正常输出里能看到芯片型号、显存总容量、当前利用率、温度这些信息。如果系统提示找不到命令说明你还没装驱动或者环境变量没配好需要先把CANN的驱动包安装完整。安装驱动时注意CANN Toolkit的版本和固件驱动版本必须匹配这个在官方文档的兼容性列表里都能查到不要装一个最新版的Toolkit却配了一个老版驱动否则跑ATC转换时会报各种莫名其妙的算子错误。对于部署YOLO这个任务我建议你用MindX SDK 3.0以上的版本配套相关的CANN Toolkit。如果团队里已经用着某个固定版本比如CANN 5.1.RC2也完全可以不一定追新。稳定的版本组合比新版本更重要这一点做生产环境的朋友应该都懂。依赖项大致如下操作系统Ubuntu 18.04/20.04 x86_64或aarch64CentOS 7.6也可以用固件驱动npu firmware和npu driverCANN Toolkit提供ATC转换工具和推理运行时MindX SDK提供推理流水线的开发框架也可以不用它后面细说Python 3.7及以上开发调试阶段用2.2 到底要不要用MindX SDK这是新人最容易纠结的问题我说一下我的选择逻辑。方案一纯Python推理用CANN自带的ACLAscendCL应用开发库直接写推理代码。优点依赖最少流程透明出问题容易排查。缺点预处理、后处理、内存管理的代码全要自己写工程量不小尤其是YOLO的后处理一个NMS写不好会出现大量误检漏检。方案二用MindX SDK开发推理pipeline。优点官方例程多YOLOv5/YOLOv8的pipeline配置文件、插件代码在SDK的样例目录里就能找到改动量小。缺点封装层多出了问题要一层层排查初次上手心理压力大。我的建议是如果是第一次在Atlas卡上跑YOLO从方案二入手先跑通官方例程再逐步拆解理解如果后续要深度定制模型或者做性能优化再考虑切换到方案一。原因很简单MindX SDK已经把“图片输入、放缩预处理、模型推理、后处理NMS、结果输出”这条链路全部模块化你只需要把模型转换好了在pipeline配置文件里指定模型路径和输入输出规格它就自动帮你把流水线搭好了。与其从零造轮子不如先把轮子跑起来理解轮子的结构。2.3 你必须要理解的三个格式pt/ONNX/OM这三者的关系我用一个类比来说明pt文件是模型的“源文件”ONNX是“中间交换文件”OM是Atlas硬件的“可执行文件”。pt文件是PyTorch训练完打包的产物里面包含网络结构和权重但它只能在PyTorch框架里运行。ONNX把网络结构、权重、计算图统一封装成一种跨框架的格式谁都可以读它但谁都不一定可以直接在硬件上执行。OM是昇腾模型转换工具ATC基于ONNX生成的里面包含针对昇腾硬件优化后的算子实现、算子调度序列和内存分配策略是最终要在Atlas卡上执行的文件。所以整条推理链路上的第一步就是先得到干净的ONNX文件。很多人在这一步看到模型能导出就以为万事大吉结果到了ATC转换阶段报一堆算子不支持的错误回头一查才发现是导出ONNX的时候把动态维度写成了静态、或者把不在算子清单上的自定义算子写进了计算图。所以导出ONNX时一定要记住两个原则尽量固定输入尺寸。Atlas推理卡的算子优化是按静态shape做的动态shape也可以但性能会打折扣而且转换时复杂度会翻倍。如果你可以确定业务上YOLO的输入尺寸就是640x640那就老老实实把batch size和输入分辨率都固定下来。关掉训练专用算子和冗余输出。在导出的时候把training相关节点、梯度信息全部移除只保留正向推理图同时如果你只需要推理结果可以在导出时把不必要的中间层输出关掉。下面是一个标准的PyTorch导出ONNX的代码段用YOLOv5作为例子import torch from models.experimental import attempt_load model attempt_load(yolov5s.pt, map_locationcpu) model.eval() dummy_input torch.randn(1, 3, 640, 640) export_onnx_file yolov5s.onnx torch.onnx.export( model, dummy_input, export_onnx_file, opset_version11, do_constant_foldingTrue, input_names[images], output_names[output], dynamic_axesNone ) print(ONNX exported: {}.format(export_onnx_file))这段代码的关键点在于固定了batch size为1固定输入尺寸为640x640关闭dynamic_axes。实测下来这样导出的ONNX在ATC转换时的成功率最高后续做静态batch优化也更省心。3. YOLO模型转换全流程3.1 ATC转换从ONNX到OM的完整命令拿到ONNX文件之后下一步就是用ATC工具把它转成OM模型。这一步的实质是把ONNX的计算图逐节点映射到昇腾的算子实现上生成一个可以在310P芯片上直接调度执行的模型文件。执行ATC转换前先确认环境变量已经加载source /usr/local/Ascend/ascend-toolkit/set_env.sh source /usr/local/Ascend/mindx_sdk/set_env.sh然后使用以下命令进行转换atc --modelyolov5s.onnx \ --framework5 \ --outputyolov5s \ --soc_versionAscend310P3 \ --input_shapeimages:1,3,640,640 \ --input_formatNCHW \ --output_typeFP32 \ --insert_op_confaipp_yolov5.cfg这里逐项解释一下命令里这几个参数踩坑率极高--framework5数字5代表ONNX格式这个参数不能写错写成1是Caffe格式写成3是TensorFlow格式格式不对就直接报错。--soc_versionAscend310P3指定芯片类型300V 24G对应的是Ascend310P系列具体是P3还是P2最好用npu-smi info确认后再填。填错的话转换能过但跑推理的时候会提示不匹配甚至直接崩。--input_shapeimages:1,3,640,640指定输入名称和静态shape。输入名称必须和ONNX导出时的input_names一致也就是“images”。如果这里名称对不上ATC会提示找不到输入张量。--output_typeFP32默认输出是FP32如果你要推理后直接做FP16后处理可以改成FP16但YOLO后处理涉及浮点坐标计算个人建议保持FP32精度更稳。--insert_op_confaipp_yolov5.cfg通过AIPPAtlas Image PreProcessing配置预处理算子的融合。这一步非常关键因为YOLO的预处理包括resize、归一化、RGB转换、减均值除标准差等如果这些操作放在CPU侧做会拖慢整体吞吐而AIPP可以直接在推理卡上把预处理融合进模型计算流减少一次D2H/H2D拷贝和CPU计算开销。一个典型的aipp_yolov5.cfg文件内容大致如下aipp_op { aipp_mode: static input_format: RGB888_U8 src_image_size_w: 640 src_image_size_h: 640 crop: false mean_chn_0: 0 mean_chn_1: 0 mean_chn_2: 0 var_reci_chn_0: 0.003921568627451 var_reci_chn_1: 0.003921568627451 var_reci_chn_2: 0.003921568627451 }这组配置的含义是输入图片按RGB三通道的U8格式进来尺寸直接就是640x640不额外做crop归一化系数用1/255.0也就是0.003921568627451。如果你的YOLO模型训练时用了自定义的mean和std这里要对应修改否则出来的检测结果会偏。AIPP这块是整个转换流程里第一个高频翻车点。最常见的问题是你明明在pipeline里做了resize结果AIPP也做了resize或者AIPP的resize尺寸和模型输入对不上导致推理结果错得离谱。我的建议是如果走MindX SDK的pipeline预处理统一交给AIPP去做不要在pipeline里再写一遍resize逻辑避免双重处理。3.2 转出来的OM模型如何验证是否正常OM模型转出来之后别急着写推理代码。先做一个模型加载和推理测试确认模型本身在卡上没问题。最直接的方式是写一个十来行的Python脚本用ACL库加载OM模型送一张测试图进去看看能不能正常推理并输出结果。这个脚本的核心逻辑是初始化ACLacl.init()和acl.rt.set_device(0)加载模型acl.mdl.load_from_file(yolov5s.om)创建输入输出数据集acl.mdl.create_desc()、acl.mdl.get_input_size_by_index()执行模型acl.mdl.execute_async()同步等待acl.rt.synchronize_stream()这一步的目的不是跑出最终检测框而是确认OM模型能够被正确加载、推理时没有算子报错。如果这一步都过不了整个项目后面所有工作都是白费。3.3 动态shape到底要不要碰我的建议很明确初期不要碰先静态跑通。动态shape意味着ONNX里输入维度的某个轴是变化的ATC转换时要加--dynamic_shape相关参数运行时的内存申请、算子调度、流水线设计都要跟着变复杂。以YOLO为例如果你要支持任意分辨率输入AIPP配置也需要动态化后处理的anchors、坐标映射等等也要跟着动态调整工作量和踩坑概率直接翻倍。实际业务里绝大多数场景YOLO的输入分辨率是固定的最常用的是640x640还有一些场景用1280x1280甚至更高但也是固定值。所以先把静态shape跑通把整个链路摸顺等上线之后确实有多尺寸需求再回来做动态shape也不迟。动态shape和静态shape的性能差距在310P上还是明显的静态batch加多实例并行吞吐量更好拉。4. 推理部署实操4.1 基于MindX SDK构建YOLO推理pipeline模型转好之后接下来就是部署环节。使用MindX SDK的好处是大部分YOLO相关的代码和配置都已经有了现成例子你要做的事情就是“改参数 填路径 跑通自己的图片”。MindX SDK的核心概念是pipeline它用配置文件描述一条数据流输入、预处理、推理、后处理、输出。拿YOLOv5的pipeline举例一个最小可用的配置大致是pipeline: - name: image_decoder plugin: mxpi_image_decoder props: input_format: rgb - name: resize plugin: mxpi_imresize props: resize_w: 640 resize_h: 640 - name: infer plugin: mxpi_tensorinfer props: model_path: ./model/yolov5s.om device_id: 0 output_tensor_names: output - name: yolov5_postprocess plugin: mxpi_yolov5postprocess props: score_threshold: 0.5 iou_threshold: 0.45 class_num: 80 input_width: 640 input_height: 640这里面有几个参数要特别说明mxpi_tensorinfer的model_path必须是转换好的OM模型路径路径要写成实际环境里的绝对路径或相对路径。device_id指定使用哪张卡如果服务器插了多张Atlas卡这里可以按需填0、1、2。yolov5postprocess里的score_threshold和iou_threshold是检测框置信度阈值和NMS的IOU阈值分别控制检测的“灵敏度”和“重叠框去重力度”。class_num表示模型可以检测的目标类别数YOLOv5 COCO预训练模型是80类如果是自己训练的数据集改成你的类别数。配置写好后用MindX SDK的Python API来驱动这条pipelineimport numpy as np import cv2 from mindx.sdk import base # 初始化pipeline pipeline base.MxFactory().CreatePipeline(yolov5.pipeline, yolov5) if pipeline is None: raise RuntimeError(Failed to create pipeline) # 读取图片并送入pipeline img cv2.imread(test.jpg) result pipeline.Process(img) # 解析结果 print(Detected objects:, result)这段代码其实就是官方例程的简化版。实际操作时你大概率需要写一个循环来处理图片目录里的所有图片并且把检测结果画框保存或者输出JSON格式的结构化结果方便后续接业务系统。4.2 不依赖MindX SDK的纯ACL推理方案如果不想用MindX SDK的封装直接用ACL的Python API来推理也可以但代码量会大不少。核心思路是acl.mdl.load_from_file()加载OM模型。为输入输出分配Device侧内存注意要用acl.rt.malloc来分配。拿到输入数据的指针把图片数据拷贝到Device侧。acl.mdl.execute_async()异步执行推理。acl.rt.synchronize_stream()等待结果。把输出从Device侧拷回Host侧做后处理。这个方案的好处是每一步都可控尤其是你要把YOLO后处理完全自己实现、或者要深度优化内存复用的时候纯ACL方案更自由。但代价是你要处理的东西太多内存生命周期、stream同步、数据格式转换、NMS实现、坐标系变换……对于一般业务场景前期先用MindX SDK把链路跑通、验证模型精度比一开始就深挖底层要有价值得多。等真正需要性能优化的时候再往底层钻也不迟。4.3 端到端推理效果的验证方法部署完之后第一件事不是压测性能而是验证推理结果是否正确。这里有一个很实用的验证方法找一张你训练集里带标注的图片跑一遍推理把检测框和置信度打印出来和PyTorch CPU/GPU上跑出来的结果对比。对同一张图PyTorch推理结果和Atlas推理结果在检测框位置上应该基本一致置信度差异应该在0.01以内。如果差距很大优先怀疑以下三点预处理不一致。AIPP里的归一化系数、颜色通道顺序RGB还是BGR是否和训练时一致。输入尺寸不一致。中心点坐标和宽高缩放比例是怎么映射回去的很多人会把resize首尾搞反。ATC转换时FP16精度问题。如果OM模型用了FP16推理且输出层没有做精度补偿在极小目标上可能出现漏检。解决办法是把--output_typeFP32显式指定或者修改后处理阈值来适配。我实际做过的项目里90%以上的“部署后结果不对”案例都出在上面三点而不是模型本身被转换坏了。5. 常见问题与排查技巧实录5.1 问题速查表从“卡识别不到”到“推理结果错乱”下面这张表是我在实际操作过程中整理出来的高频问题每一行的解决办法都是实测有效的现象可能原因排查与解决方法npu-smi info提示找不到设备驱动未安装或固件驱动没加载重新安装对应版本的驱动执行npu-smi info前先source环境变量ATC转换时报“input shape mismatch”ONNX里的输入名和ATC命令里的--input_shape名称不一致用Netron打开ONNX查看实际输入节点名确保名称对应ATC转换时报某个算子不支持ONNX里含有310P无法支持的算子用ATC自带的算子适配工具看日志尝试更换opset_version、简化模型、或手工替换该算子推理结果为空白或全零AIPP的归一化参数不对或输入tensor显存未拷贝成功检查AIPP配置打印中间tensor值确认数据进模型前是否正常检测框位置整体偏移预处理resize后坐标映射时没有按原图比例回推后处理里坐标还原时要按照scale比例换算不能直接用resize后的坐标当原图坐标性能达不到预期单实例串行推理batch size太小按多实例并行或batch推理方式压测找到吞吐拐点这六条基本覆盖了我在Atlas 300V上跑YOLO时遇到的大多数问题。其中“ATC转换时报算子不支持”是最让人头疼的因为报错信息往往只给一个算子名不会告诉你该怎么替换。我的经验是先去官方文档的算子支持列表里查这个算子看是支持精度的问题还是本身不在适配范围。如果不在适配范围优先回到PyTorch侧把模型里的这个部分用等价算子替代重新导出ONNX再试。5.2 显存不足和内存泄漏的排查思路24G显存看着不小但如果在MindX SDK里反复创建和销毁pipeline、或者大量图片并发往里送而不控制并发数还是可能出现显存不足。一个很管用的排查方法是在推理循环里定时打印显存占用npu-smi info如果显存随推理次数增加而持续增长说明存在内存泄漏。排查顺序是检查pipeline是否每次循环都被重复创建如果是改成在循环外创建一次。检查图片数据是否释放及时如果用了Python的numpy数组和OpenCV的Mat注意引用计数。检查后处理返回结果是否存了过多历史数据尤其是画框后的图片不要无脑全部保存到列表里。性能压测时推荐的做法是循环外创建pipeline和上下文循环内只做图片的送入和结果回收这样内存波形是平稳的。5.3 并发和batch size怎么调才能榨出最大性能Atlas 300V在推理场景下的性能调优核心就两条batch和并发实例数。先说batch。YOLO这类卷积模型batch size增大时算力利用率会明显提升但batch太大显存和延迟又会变差。在300V 24G上YOLOv5s的FP32推理我个人测下来batch4到batch8是一个甜点区。batch1时单张延迟大约12到15毫秒batch8时单张平均延迟可能会涨到30毫秒左右但吞吐量涨了几倍。如果业务对延迟敏感就选batch1或者batch2如果是对吞吐量敏感比如离线批量抠图那就batch8直接压满。再说并发实例。最简单的方式是开多个进程每个进程绑定一张卡或一个device。如果只有一张卡可以用多线程或多进程在同一device上跑多个pipeline实例但要控制并发数不然调度开销会抵消收益。实测下来300V上同时跑4个推理实例吞吐量最高继续往上加收益就不明显了。调优时心里要有一本账延迟和吞吐永远是矛盾的。你在意的是单帧延迟就牺牲一点吞吐你在意的是整批图片的处理速度就接受单帧延迟变高。没有“又快又多”的白嫖方案。6. 写在最后的经验与扩展建议6.1 踩了三次坑后我总结出的部署心得在Atlas 300V上部署YOLO我前前后后踩了不少坑现在回头看有三条经验最值得分享。第一先通链路再调性能。很多人一上来就急着压测、优化结果模型加载都报错。正确顺序是先torch.onnx.export导出ONNX再ATC转出OM再写一个最小推理脚本验证结果最后才讨论batch、并发、性能。链路不通后面全是白费。第二配置文件和参数名一定要逐个核对。ATC命令里的--soc_version、--input_shape、ONNX里的输入节点名、pipeline里的模型路径任何一处不一致报错信息都极其难懂。我的习惯是写完配置文件后逐行读三遍确认没有名称笔误再执行。第三多用Netron看模型结构。Netron这个工具看ONNX结构非常好用输入节点名、输出结构、中间算子是啥一目了然。它应该是每个做模型部署的人桌面必备的工具没有之一。6.2 后续可以扩展的方向如果你已经成功在Atlas 300V上跑通了YOLOv5s那后续可以做很多方向的扩展这里提供几个我觉得值得尝试的方向换更大的模型。YOLOv8m、YOLOv7、RT-DETR这些模型同样导出ONNX然后过ATC思路完全一样。把流程跑熟了换模型就是换个文件路径的事。利用24G大显存甚至可以尝试YOLOv8x这在8G显存的老卡上是想都不敢想的。多路视频流并行推理。Atlas卡的推理吞吐在视频流场景下优势明显把pipeline的输入从单张图片改成RTSP视频流接入多路摄像头做实时检测告警是一个很实用的扩展。做模型量化和精度对比。把OM模型从FP32量化成FP16或者更进一步用PTQ训练后量化把权重压到INT8对比精度损失和性能提升。这对工业场景降本增效很有意义也是Atlas卡很擅长的工作。批处理服务化封装。把推理流程封装成一个HTTP服务比如用FastAPI接住图片请求转给Atlas推理再返回检测结果。这一步做完了整个部署方案就能真正交给业务方用了。最后再啰嗦一句工具链更新很快CANN和MindX SDK的版本迭代很频繁遇到问题别死磕旧文档先查当前版本的官方Release Notes和算子适配列表往往能少走很多弯路。部署YOLO这条链路本身不复杂真正复杂的是把每一个细节都照顾到。希望这篇文章能帮你把这条路走顺。
返回列表