首页 / 资讯中心 / 文章详情

Atlas 300V 24G实战:YOLO模型部署与推理优化全指南

Atlas 300V 24G实战:YOLO模型部署与推理优化全指南 ★ FEATURED ARTICLE
聊聊Atlas 300V 24G。最近总有做视觉检测的朋友问我这卡到底是不是“运算加速卡”还有不少人一上来就问怎么把YOLO模型部署上去。这两个问题其实指向同一件事在昇腾推理卡上把目标检测模型真正跑起来。我手上正好有一张Atlas 300V 24G前后折腾了快两个月从一张白卡到YOLOv5、YOLOv8都能稳定出框中间踩了不少坑。这篇文章就把硬件定位、环境搭建、模型转换、推理代码、性能调优和典型报错一次讲清楚给准备上Atlas的朋友一份能直接对着做的参考。1. Atlas 300V 24G是什么定位的加速卡1.1 先回答热搜问题它是不是运算加速卡是但严格说它是一张专用的推理加速卡不是用来做训练的那类加速卡。这个区别很重要因为它直接决定了你能拿它干什么、不能干什么。Atlas 300V 24G从硬件形态上看是一张PCIe接口的加速卡插在x86或ARM服务器上就能用。它内部用的是昇腾310P系列的AI芯片主打的是推理场景下的高能效比。和训练卡不同它不会去承担反向传播、梯度更新这类重负载计算而是把已经训练好的模型拿过来做前向推理也就是把图片、视频流送进去把检测框、分类结果吐出来。很多朋友容易把“加速卡”三个字理解成“什么都能加速”结果买回去想跑训练发现编译模型的时候一堆算子不支持或者训练速度远不如预期。这是正常的因为它的硬件设计和软件生态从一开始就是奔着推理优化的。1.2 和GPU推理卡相比它的特点是什么拿常见的NVIDIA T4或者RTX系列推理卡来对比Atlas 300V 24G有几个明显不同的地方第一算力类型偏重INT8和FP16。这张卡在INT8精度下的算力表现非常突出官方给的INT8算力在百TOPS级别FP16的算力相对低一些。这意味着如果你的模型能做INT8量化跑起来的速度会非常可观。我实测YOLOv5s在FP16下能做到几十毫秒一帧INT8量化后还能再快一截。第二卡上直接集成了视频编解码能力。它有专用的DVPP模块可以用来做图片缩放、格式转换、视频解码。这一点对做视频流的应用特别友好。以前用GPU卡做视频检测CPU要先解码视频帧再把帧数据拷贝到显存这一套流程在并发路数高的时候非常吃CPU。而Atlas 300V 24G可以把解码、缩放这些预处理全部下沉到卡上CPU占用率能降得非常低。第三功耗和散热比较友好。这张卡的典型功耗在70多瓦比很多动辄两三百瓦的训练卡温和得多。几张卡插在一台服务器里不需要特别夸张的散热改造。我自己的测试机上插了两张风冷就能压住。1.3 一张卡能做什么适合谁用从实际落地的角度来看Atlas 300V 24G适合这几类场景工业视觉质检。产线上拍出来的图片做缺陷检测单张图延迟要求不高但对并发吞吐有要求一张卡可以同时跑多个模型实例。安防和智慧园区。视频流接入后做实时人车物检测这时它的视频解码能力优势就体现了。边缘服务器推理。机房空间有限、供电有限需要把AI算力塞到小机箱里这张卡的功耗和算力比很合适。高校和科研机构的算法验证。很多实验室想用国产算力跑YOLO系列模型这张卡是入门成本相对可控的选择。如果你是做训练的比如要微调一个大模型、要从零训一个检测器那应该去看昇腾的Atlas 800训练服务器或者带训练卡的型号而不是这张卡。这个定位问题如果搞反了后面所有步骤都会很别扭。2. 部署YOLO前的环境准备2.1 驱动、固件、CANN安装顺序不能乱把Atlas 300V 24G插到服务器上之后第一件事不是急着跑模型而是把底层软件栈装好。昇腾的软件栈分三层驱动和固件、CANN工具包、行业SDK或推理框架。这个顺序是硬性的装反了会出现各种奇怪的问题。驱动和固件官方叫法叫Ascend HDK里面包含了设备驱动和芯片固件。这一层装好以后操作系统才能识别到卡。装完后在终端敲npu-smi info如果能看到卡的型号、温度、功耗和显存信息说明驱动已经正常工作了。CANN是昇腾的计算架构类似NVIDIA的CUDA。它的版本必须和驱动版本匹配这个匹配关系在华为官方的版本配套表里有明确说明。我建议的做法是先查好CANN版本对应的驱动版本然后统一安装不要各自装最新的。我自己第一次装的时候CANN用了7.0驱动用了比较旧的版本结果模型转换工具直接报错后来对齐版本才解决。安装方式上推荐用root用户跑安装脚本不要用桌面版那种图形界面方式在服务器上不实用。2.2 开发者套件和运行环境的区别CANN有两种形态开发环境和运行环境。简单理解开发环境包含了模型转换工具、算子编译工具、编译器这类东西用来把ONNX、TensorFlow的模型转换成昇腾的OM格式运行环境只包含推理运行时、驱动依赖这些用来跑已经转换好的OM模型。如果你是纯部署只需要把模型从二进制文件加载起来做推理那装运行环境就够了。如果还要自己做模型转换、算子调试就要装开发环境。我的习惯是开发机上装完整版把模型转换好之后再拿到只有运行环境的部署机器上去跑。这样做的好处是生产环境的东西少出问题的面就小。2.3 用npu-smi确认卡状态正常驱动装好之后建议养成一个习惯每次跑模型之前先敲一下npu-smi info看卡的状态。重点关注几个指标芯片温度、当前功耗、显存占用、AI Core利用率。这里有一个容易误判的点显存占用高不代表卡在干活。有时候模型虽然加载到了卡上但推理没有跑起来显存占用也会有几GB。要看真正的算力使用情况得看AI Core的利用率。利用率长期是0%说明推理代码可能没有真正调用到NPU资源或者卡在数据拷贝阶段。另外npu-smi其实和nvidia-smi用法很像参数也是一脉相承的风格。如果你之前用过NVIDIA的卡上手昇腾的管理命令基本没有学习成本。3. 模型转换从PyTorch/ONNX到昇腾OM格式3.1 为什么不能直接跑PyTorch的模型这个问题几乎每个刚接触昇腾的人都会问。原因很简单昇腾NPU不认识PyTorch的权重格式它需要的是经过编译器优化过的OM格式文件。OM文件里面不仅包含了模型的权重和结构还包含了算子在NPU上的调度方案、内存分配策略、算子融合信息。你可以把它理解成是为NPU量身定制的一份“可执行文件”。现在社区里也有人用MindSpore直接训练再导出模型但现实情况是大多数人手里的YOLO模型还是PyTorch训练的。所以标准的转换路径是PyTorch模型导出成ONNX再用ATC工具把ONNX转成OM。3.2 导出ONNX时最容易忽略的细节用YOLOv5做例子官方仓库里自带导出脚本但默认导出出来的ONNX直接拿去转OM十有八九会出问题。我在实操中总结出几个关键点第一动态维度的问题。YOLOv5默认导出是动态shape输入尺寸可以是任意值。昇腾的ATC工具对动态shape的支持比较麻烦会显著增加转换复杂度和运行时的内存开销。所以部署时尽量固定输入尺寸。我这里用--dynamic参数导出固定尺寸的ONNX比如输入固定为1x3x640x640这样后续转换简单很多。第二算子的兼容性。YOLOv5里的一些操作比如Focus模块在老版本PyTorch导出ONNX时会被拆成多个切片加拼接的操作在昇腾上转换效率不高。比较新的版本已经把Focus改成了普通卷积问题不大。如果你的模型是老版本建议先重写结构再导出否则后面转换时会需要手动搭算子映射。第三输出节点。YOLO模型的输出一般有三个尺度的特征图导出ONNX时要确保输出的名称能被记录下来。ATC转换时可以通过--out_nodes指定输出节点如果这里搞错后处理解析数据时会对不上。这是最简单的方式一行命令导出ONNXpython export.py --weights yolov5s.pt --include onnx --imgsz 640 640 --batch-size 1 --dynamic False3.3 ATC转换命令与关键参数ONNX有了接下来用ATC工具转OM。ATC工具的路径一般在CANN安装目录下的bin目录里安装好了之后需要source一下CANN的环境变量脚本比如source /usr/local/Ascend/ascend-toolkit/set_env.sh环境的shell脚本路径取决于你的CANN安装位置每个人可能不一样我这里以默认路径为例。source完成之后再执行转换命令atc --modelyolov5s.onnx \ --framework5 \ --outputyolov5s_bs1_fp16 \ --soc_versionAscend310P3 \ --input_shapeimages:1,3,640,640 \ --output_typeFP16 \ --loginfo逐个解释一下这些参数这些参数是转换的核心--framework55代表ONNX模型这是ATC工具里ONNX对应的编号。--soc_version这个参数很关键必须和你芯片的型号完全对应。Atlas 300V 24G对应的是Ascend310P系列具体是Ascend310P1还是Ascend310P3要看卡的具体型号。我这张是Ascend310P3所以填这个。填错的话转换工具会提示找不到对应的soc版本。--input_shape固定shape时这里输入必须是具体维度格式是“输入名:维度”。输入名要和ONNX里实际的名字保持一致。YOLOv5的输入名一般是images。--output_typeFP16指定模型在卡上运行的精度。FP16是精度和速度的平衡点。如果你后续要做INT8量化现在不用管这个参数。如果转换过程中报算子不支持的错误不要慌大多数情况下是ONNX导出的问题回到上一步调整模型结构或者算子版本。3.4 用MindX SDK快速搭一条推理pipelineOM模型转换成功之后接下来有两个路线可以走一是直接用ACLAscend Computing Language写推理代码灵活度最高二是用MindX SDK把预处理、推理、后处理这些环节用配置文件串成一条流水线代码量少很多。MindX SDK适合做视频流接入和图像处理流水线。它的核心概念是plugin每个plugin负责一件事情比如解码插件负责把视频流变成图片图像处理插件负责缩放推理插件负责加载OM模型做推理。用配置文件把这些插件串起来推理程序只需要读取配置并启动pipeline。我自己在做一个实时视频检测Demo时用的就是MindX SDK。配置文件大致长这样{ pipeline: [ { streamName: detection, plugins: [ { pluginName: video_decode, pluginType: VideoDecoder }, { pluginName: image_resize, pluginType: ImageResize, params: { width: 640, height: 640 } }, { pluginName: yolov5_infer, pluginType: ModelInfer, params: { modelPath: yolov5s_bs1_fp16.om } } ] } ] }实际使用中还要加很多参数这里只是示意。它的好处是pipeline里的数据流都是零拷贝的解码出来的数据直接进缩放模块缩放完直接进推理不需要在CPU和NPU之间反复拷贝性能损耗小。对于想快速验证效果的朋友我建议先用这个方案把整体流程跑通再决定要不要用ACL做深度优化。4. 基于ACL的推理代码实现4.1 初始化资源与加载模型如果你不想依赖MindX SDK想自己掌控每一个环节那就用ACL。ACL提供了C和Python两套接口Python版本适合快速原型验证C版本适合生产环境追求极致性能。我这里以Python接口为例来讲解整体流程。ACL推理的固定套路是初始化 - 加载模型 - 准备输入输出 - 执行推理 - 解析结果 - 释放资源。第一步初始化代码是固定的流程固定先初始化ACL再设置设备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} # 创建上下文 context, ret acl.rt.create_context(0) assert ret 0, facl.rt.create_context failed, ret{ret}这里有一个容易踩的坑ACL的Python接口很多函数返回的是一个元组第一个值是返回值第二个值才是你需要的数据。比如acl.rt.create_context(0)返回的其实是(context, ret)顺序不要搞反了。加载模型用acl.mdl.load_from_file加载成功后会返回模型ID后面所有推理调用都要用到这个IDmodel_id, ret acl.mdl.load_from_file(yolov5s_bs1_fp16.om) assert ret 0, facl.mdl.load_from_file failed, ret{ret}4.2 数据预处理与推理调用加载完模型之后要做的就是准备输入数据。ACL推理要求输入数据是一块连续的内存而且数据的内存地址必须是设备侧可访问的地址。这里要区分清楚普通numpy数组是在主机侧内存里的不能直接喂给ACL推理。需要用acl.rt.memcpy把数据拷贝到设备侧或者用acl.util.numpy_to_ptr这类接口先把numpy数组转换成指针。数据预处理这一步YOLO的输入需要做letterbox缩放、归一化、转成CHW格式。这些操作用OpenCV和numpy在CPU上做就行因为预处理本身计算量不大瓶颈通常不在这一块。真正耗时的是推理本身以及后面要讲到的数据拷贝。推理调用的核心是acl.mdl.execute它需要传入输入数据指针和输出数据空间。写法类似这样# 假设input_data已经是预处理好的连续numpy数组 input_ptr acl.util.numpy_to_ptr(input_data) # 输出数据需要预先申请空间 output_size 1024 * 1024 * 128 _, output_ptr acl.rt.malloc(output_size, 2 * 1024 * 1024) # 执行推理 ret acl.mdl.execute(model_id, input_ptr, input_size, output_ptr, output_size) assert ret 0, facl.mdl.execute failed, ret{ret} # 把输出从设备侧拷贝回主机侧 output_np np.zeros(output_size, dtypenp.uint8) acl.rt.memcpy( acl.util.numpy_to_ptr(output_np), output_size, output_ptr, output_size, acl.const.COPY_DEVICE_TO_HOST )这里input_size的大小不是随便写的需要根据模型的输入shape计算。比如输入是1x3x640x640的FP32数据那就是1 * 3 * 640 * 640 * 4字节。4.3 输出数据解析YOLO的后处理怎么做推理完成之后输出数据是一个原始的内存块需要根据模型的输出结构来解析。YOLOv5的ONNX转换之后输出一般是一个1x25200x85的矩阵25200是三个尺度特征图的anchor数量总和85是坐标、置信度和类别数的总和。把输出从设备拷贝回来后这是一个(1, 25200, 85)的numpy数组接下来的NMS、过滤低置信度框这些操作用普通的numpy或者PyTorch CPU逻辑就能完成。不需要NPU参与这部分计算原因有两个一是后处理逻辑复杂且动态性强不适合在NPU上静态执行二是输出数据量不大后处理耗时通常只有几毫秒构不成瓶颈。一个小技巧YC和类别数如果固定不变可以把后处理的代码先向量化比如用numpy的布尔索引一次性过滤低置信度的框而不是用for循环遍历25200个框性能差距很大。4.4 多路并发的工程化改造单路推理能跑通了接下来就是常见的多路视频流并发。Atlas 300V 24G的算力完全足够同时跑多路YOLO推理关键是怎么把并发做好。第一步确定batch size。如果一路视频对应一个检测任务可以用batch size等于1靠多线程并发多个推理任务来吃满算力如果一路视频可以多帧打包那就用大batch单次推理多张图算力利用率更高。实测下来处理多路RTSP视频流时每一路保持batch size 1然后用线程池并发提交效果比一路一个大batch要好因为每路的帧率不同大batch会导致某些路延迟增大。第二步避免频繁申请和释放内存。推理过程中输入输出内存反复malloc和free会带来不小的开销。正确做法是启动时提前分配好一批内存块推理时循环复用用队列来做生产者消费者模型。这样推理链路的稳定性会明显提升。第三步控制线程数量。NPU上的推理任务提交之后是异步的不要每路视频都无限创建线程。线程数量建议控制在和卡上的AI Core数量一个量级太多反而会因为上下文切换导致性能下降。5. 性能调优与问题排查实录5.1 性能瓶颈定位方法有朋友跑通了模型但发现帧率上不去于是拿来问我怎么优化。我一般先让他做三件事把瓶颈定位清楚再动手不要上来就乱调参数。先看算力利用率。用npu-smi info持续观察AI Core利用率。如果利用率长期低于30%说明模型没有把卡吃满瓶颈可能在数据预处理、数据拷贝或者后处理上。再看耗时分布。在代码里对每一步打点计时统计预处理耗时、数据拷贝耗时、推理耗时、后处理耗时各占多少。我见过最夸张的情况是推理只用了5毫秒数据从主机到设备拷贝花了30毫秒那不管你怎么调模型都是白费劲。最后看并发表现。单路跑不满利用率是正常的因为单路数据供需不够密集。试着把并发路数加上去看利用率是否跟着上升。如果升上去了说明卡的性能没问题优化方向是增加并发如果始终上不去就要考虑模型本身算子效率的问题了。5.2 实测有效的几种优化手段把我试过并且有效的手段列在这里按收益从大到小排序AIPP预处理下沉。Atlas的AIPP功能可以把减均值、除以标准差、缩放、归一化这些操作直接写进模型里在NPU上完成不需要在CPU上预处理。这样既能降低CPU占用也减少了主机和设备的拷贝量。实测这一项优化就能把端到端时延降低10毫秒以上。固定shape避免动态shape。动态shape推理时NPU的内存调度是按最大可能shape预留的而且算子图不会做极致优化。固定shape之后算子融合更彻底内存布局更紧凑推理速度有明显提升。使用DVPP做图像缩放。OpenCV在CPU上做缩放一张1080P图缩到640可能要2到3毫秒多路并发时CPU就会成为瓶颈。把缩放操作交给DVPP后CPU基本上就解放了。INT8量化。在精度允许的情况下用AMCT工具做INT8量化推理速度能再提升30%以上。但要注意量化需要准备校准数据集且某些层敏感度很高量化后精度可能会掉得厉害。多stream并行。在单模型、单设备的情况下创建多个推理stream可以让不同请求在不同的AI Core上并行执行提升整体吞吐。5.3 常见报错与排查速查表把这段时间遇到的典型报错和排查思路整理成一个速查表方便大家对照处理。报错现象可能原因解决方法npu-smi info看不到卡驱动未安装或模块未加载重新安装驱动执行npu-smi info前先lsmod检查drv_pcie模块ATC转换时报E40000: soc_version not supported--soc_version填错确认芯片实际的soc版本用npu-smi info或ascend-dmi查询ATC转换时报算子不支持错误ONNX导出不干净或有动态shape重新导出ONNX固定输入shape升级PyTorch和ONNX版本运行时报acl.mdl.load_from_file failedOM文件路径不对或CANN版本不匹配确认OM文件存在确认ONNX转换时使用的CANN版本和推理时一致推理结果全为0输入数据内存没有正确拷贝到设备侧检查acl.rt.memcpy的方向参数是否用了COPY_HOST_TO_DEVICE推理结果框位置偏移预处理时letterbox参数和训练时不一致检查缩放比例和填充值是否和训练时的预处理一致多路并发时CPU占用率飙高预处理或后处理全在CPU上跑把缩放下沉到DVPP把归一化下沉到AIPP报显存不足同时加载的模型或请求过多检查模型大小和并发路数适当降低batch size还有一个非常隐蔽的问题值得单独说一下多个进程同时初始化ACL可能会出现设备抢占失败。每个进程在访问设备之前会获取一个锁如果锁没有释放其他进程就会报错。解决方案是确保每个进程退出时正确调用acl.finalize()和acl.rt.reset_device()进程异常崩溃时要手动清理残留进程否则下次启动会莫名其妙地失败。5.4 关于Atlas 300V 24G性能的一个参考数据最后给一个参考数据方便大家有个心理预期。我这边用YOLOv5s模型、输入分辨率640x640、FP16精度、batch size 1的情况下单路推理耗时大概在12到15毫秒之间也就是单路可以跑到70帧左右。如果开启多路并发比如4路视频流同时检测每路的延迟会略微上升但整体吞吐量能稳定在每秒120帧以上。这个数据和你的驱动版本、CANN版本、服务器CPU性能、图片内容复杂度都有关系不用纠结具体数字关键是看优化的方向对不对。我见过有人拿着这个卡跑YOLOv5x模型权重本身很大推理延迟自然就上去了这跟卡的好坏无关是模型选型的问题。部署的时候选什么规格的YOLO模型要根据你的实际时延要求来定不要一味追求精度。我个人在实际操作中最大的体会是Atlas 300V 24G这张卡能不能跑好YOLO七分在转换和预处理三分在推理代码。很多人花大量时间纠结推理接口的一个参数却不重视ONNX导出时固定shape、不改动预处理逻辑这些前面的环节最后效果自然不好。如果你正准备上手这张卡我建议先把模型转换和预处理这两块吃透再去研究怎么并发、怎么调优这条路会顺很多。
阅读完成 · 觉得有帮助?
咨询建站