ARTICLE DETAIL

资讯详情

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

华为Atlas 300V部署YOLOv5全攻略:从模型转换到性能调优

华为Atlas 300V部署YOLOv5全攻略:从模型转换到性能调优 1. 先搞清楚这块卡到底能干什么1.1 一次把“运算加速卡”这件事说清楚先说结论华为Atlas 300V 24G本质上是一块专门用来做AI推理的加速卡官方叫法是“AI推理加速卡”。它跟显卡长得像但干的事不太一样。显卡是为了把画面渲染出来给你看而这卡是为了把训练好的深度学习模型跑起来快速算出结果比如识别图里有没有人、有没有车、有没有缺陷。很多人第一次接触Atlas 300V是被那个“24G”吸引的。24G代表的是板载内存容量也就是显存但在昇腾的语境里更准确的说法是“存储空间”。24G这个规格在同类型推理卡里算是比较大的意味着它能装下更大的模型或者在同样一个模型下塞进更大的batch一次处理更多张图。然后回答热搜词里的一个核心问题Atlas 300V 24G是运算加速卡吗是但它不是那种通用计算卡它是专用的AI推理卡。也就是说它擅长的是把已经训练好的神经网络模型高效地跑起来而不是像GPU那样既能训练又能渲染还能跑CUDA通用计算。你要拿它去做模型训练也能做但那是“用非所长”你要拿它做线上推理、边缘部署、视频流分析这才是它的主场。这张卡还有个容易被忽略的关键点它的架构是基于昇腾AI处理器的算力单位是TOPS INT8而不是GPU常用的TFLOPS FP32。这意味着它的强项是低精度推理INT8量化后的模型在上面跑性能非常可观。所以如果你手里有YOLO、ResNet、BERT这类模型想找一个功耗低、体积小、单卡推理性能强的方案Atlas 300V是值得认真考虑的对象。1.2 为什么选Atlas而不是其他卡300V 24G的定位我自己同时用过GPU和Atlas做过推理部署感受还挺深的。GPU的好处是生态成熟PyTorch转个TensorRT网上教程一大堆遇到问题随便一搜就有答案。但GPU的缺点是贵、功耗高、不好买尤其是现在这个时间点稍微像样点的卡都要排队。Atlas这边的优势恰好补上了GPU的这些短板。首先是功耗Atlas 300V 24G的功耗大概在70W到90W之间整卡功耗远低于动辄两三百瓦的GPU这意味着它对电源、散热、机箱的要求低很多普通的工作站甚至一些边缘服务器都能直接塞进去。其次是价格同等推理性能下它的价格通常比同级别的GPU卡低不少对企业批量采购来说成本优势非常明显。还有一个很关键的点是Atlas 300V 24G是单宽卡也就是只有一个PCIe插槽的宽度体积小不占空间。你可以在同一台服务器里插多张卡用卡的数量堆推理吞吐。我之前在一台4U服务器里塞了4张300V同时跑4路不同的推理任务互不干扰稳定性也不错。这个体验是很多GPU卡给不了的——大显卡插两张就已经把PCIe插槽和供电接口全占满了。所以Atlas 300V 24G的定位很清晰它是给那些需要做AI推理部署、但不想在硬件上投入太多的人准备的。尤其是做安防监控、工业质检、智慧交通这类场景的开发者YOLO几乎是标配模型这时候用Atlas跑YOLO性价比和实用性都很能打。2. 动手部署前先迈过软硬件准备这道坎2.1 硬件安装与驱动检查如果你刚拿到一张Atlas 300V 24G第一步肯定是把它插到PCIe插槽上。这里我提醒一句先看你的主板PCIe插槽供电能力。300V的功耗虽然不高但依然需要PCIe插槽稳定供电。一些老主板的PCIe x16插槽实际供电能力不足会在高负载时触发降频甚至掉卡。插好卡之后开机进系统先执行lspci | grep -i ascend看看系统有没有识别到设备。正常情况你应该能看到类似Processors、Huawei这样的输出。如果什么都看不到大概率是硬件没有正确识别或者卡没插好重新插拔一下再试。接下来是装驱动。这部分是新手最容易卡住的地方因为Atlas的驱动分成好几个部分不是像显卡那样装一个GeForce Experience就完事。你需要装的是三个东西NPU驱动Ascend HDK的driver包、固件firmware包、以及CANN工具包。这三者的版本必须严格匹配混搭版本会导致各种诡异的问题。我的建议是直接去昇腾社区的软件安装页面下载对应版本的全量包而不是到处去搜散包。下载的时候看好自己系统的架构和操作系统版本。我用的是Ubuntu 20.04 x86_64驱动包名类似Ascend-hdk-xxx.runCANN包名类似Ascend-cann-toolkit_xxx.run。安装过程很简单给run文件加执行权限然后运行就行但安装完成后记得设置环境变量source /usr/local/Ascend/ascend-toolkit/set_env.sh然后验证一下驱动是否正常工作npu-smi info这个命令能列出所有Atlas卡的型号、芯片温度、利用率、内存占用非常实用。我每次部署完第一件事就是跑这个命令确认卡已经被系统正确识别。2.2 CANN工具链的版本匹配关于CANN我多说几句。CANN的全称是Compute Architecture for Neural Networks可以理解成昇腾的“CUDA”它负责把PyTorch、TensorFlow模型转成能在NPU上跑的格式同时也提供了推理时需要的运行库。版本匹配这块是很多人踩坑的重灾区。CANN的版本号和驱动、固件的版本是绑定的。你如果装了CANN 6.3.RC3那么驱动和固件也得是配套的版本。装错版本最常见的表现是推理时报错E10001或者提示Runtime版本跟Driver版本不匹配。这个错很坑因为从报错信息上很难一眼看出是版本问题我一开始还以为是代码写错了。所以我的建议是在你决定用哪个CANN版本之前先去查昇腾社区里的版本配套表找到驱动、固件、CANN三者互相兼容的版本组合然后再下载安装。这个步骤能帮你省下至少两天的排查时间。另外要注意的是CANN还可以选装不同的组件。全量安装需要下载好几个包除了Toolkit之外还可能有NNAE神经网络加速引擎、Kernel算子包等。简单部署推理场景装Toolkit Kernels就基本够用了。如果你需要用PyTorch框架直接迁移模型做推理那还得装Ascend PyTorch适配层。3. YOLOv5模型转换与推理部署实操3.1 从PyTorch权重到ONNX的导出在Atlas上跑YOLOv5跟你在GPU上直接跑完全不一样的地方是你不能直接拿.pt文件往NPU里塞。PyTorch的模型格式是给PyTorch运行时用的NPU不认识它。你得先把.pt转成ONNX再用ATC工具把ONNX转成昇腾的离线模型格式.om。先把YOLOv5仓库clone下来然后准备好你的训练权重执行导出git clone https://github.com/ultralytics/yolov5 cd yolov5 python export.py --weights best.pt --include onnx --opset 11 --simplify这里说几个参数细节。--opset 11是ONNX的算子集版本我用的是11因为CANN对Opset 11的支持比较成熟更高的opset可能会有某些算子无法解析。--simplify会调用onnx-simplifier对模型进行简化去掉一些冗余的算子能让后续ATC转换的失败率低很多。导出完成之后用Netron打开生成的.onnx文件先看一眼模型结构确认输入输出的名称和维度。通常情况下YOLOv5导出的ONNX输入名是images输出是三个对应三个不同尺度的检测头名称是output0、output1、output2。知道这几个名字后面ATC转换时要用到。3.2 使用ATC工具进行离线模型转换ATC全称Ascend Tensor Compiler作用就是把ONNX模型编译成昇腾NPU能直接执行的.om文件。这个转换过程有点像把Python代码编译成二进制可执行文件编译一次到处运行。找到ATC工具的路径source /usr/local/Ascend/ascend-toolkit/set_env.sh which atc然后执行转换命令。我用的YOLOv5s模型转换命令如下atc --modelyolov5s.onnx --framework5 --outputyolov5s_24g --input_shapeimages:1,3,640,640 --input_formatNCHW --output_typeFP32 --soc_versionAscend310P3 --insert_op_confaipp.cfg这里有几个参数值得展开讲。--framework5表示输入模型是ONNX格式这个5是固定的不要改。--output指定输出的.om文件名。--input_shape指定输入图像的形状这里1,3,640,640的意思是batch为1、3个通道、640x640分辨率。如果你的输入图像不是640x640需要提前resize或者在这里修改对应的分辨率。--soc_version是重中之重它指定目标芯片的型号。Atlas 300V 24G对应的soc_version是Ascend310P3。如果你写错了版本虽然转换可能不会报错但生成的.om文件在板上是跑不起来的会报一种“模型与设备不匹配”的错误。--insert_op_confaipp.cfg是让模型里嵌入一个AIPP预处理模块。这个配置的作用是把图像resize、归一化这些操作直接下沉到NPU硬件上执行省去在CPU上做预处理的耗时。aipp.cfg的内容后面我详细讲。转换成功后会在当前目录生成一个.om文件。看到这个文件生成基本上就成功了一大半。3.3 推理代码的编写与数据预处理有了.om文件之后接下来就是写推理代码了。昇腾的推理接口有两种一种是基于aclAscendCL的底层接口另一种是基于aclpy的Python接口。我用Python写的话主要是用acllite或者直接调pyACL的库。先初始化设备上下文然后加载模型、创建输入输出数据集。核心代码的骨架大致是这样的import acl import numpy as np # 初始化 ret acl.init() ret acl.rt.set_device(0) context, ret acl.rt.create_context(0) # 加载模型 model_path yolov5s_24g.om model_id, ret acl.mdl.load_from_file(model_path)然后是数据准备。输入图像要先由OpenCV读进来然后做letterbox缩放把图像变成640x640的方块同时记录缩放比例和填充位置方便后续推理结果还原到原始坐标。这里我用一个简单的letterbox函数def letterbox(img, new_shape(640, 640)): shape img.shape[:2] r min(new_shape[0] / shape[0], new_shape[1] / shape[1]) new_unpad (int(round(shape[1] * r)), int(round(shape[0] * r))) img cv2.resize(img, new_unpad, interpolationcv2.INTER_LINEAR) dw new_shape[1] - new_unpad[0] dh new_shape[0] - new_unpad[1] top, bottom dh // 2, dh - dh // 2 left, right dw // 2, dw - dw // 2 img cv2.copyMakeBorder(img, top, bottom, left, right, cv2.BORDER_CONSTANT, value(114, 114, 114)) return img, r, (left, top)做完之后把图像转成float32并做归一化让像素值从0-255变成0.0-1.0然后transpose成NCHW的排布以便符合模型的输入格式。接下来调用推理接口input_data np.ascontiguousarray(img.astype(np.float32) / 255.0).reshape(1, 3, 640, 640) # 将numpy数组拷贝到设备内存 input_tensor, ret acl.media.dvpp_malloc(input_data.nbytes) acl.rt.memcpy(input_tensor, input_data.nbytes, input_data.tobytes(), input_data.nbytes, acl.rt.MEMCPY_HOST_TO_DEVICE) ret acl.mdl.execute(model_id, [input_tensor], [output_tensor])acl.mdl.execute是同步执行接口调用完之后结果就在output_tensor里了。这里注意模型的输出格式是三个尺度的原始输出每个输出张量是[1, 255, 80, 80]这样的形状。你需要对这三个输出做解码也就是reshape成[1, 3, 80, 80, 85]这种格式然后做置信度过滤、NMS最终得到检测框。这个过程跟PyTorch里做后处理是一样的只是输入数据来自于NPU的推理结果。4. 推理性能调优把卡的潜力榨出来4.1 动态batch与多路并发Atlas 300V 24G最舒服的用法是拿来做多路视频流或者批量图片的并发推理。24G的大显存给了你很大的batch空间。比如YOLOv5s这种小模型单张640x640的输入显存占用大概在几百MB你batch塞到32都完全没问题。batch越大单位时间内处理的图片数就越多但也不是无脑大就好因为batch太大反而会让每一张的平均耗时上升因为硬件算力是固定的一次性塞太多东西等待时间会更长。一个更实用的方案是使用动态batch。ATC转换的时候你可以指定多档输入形状--input_shapeimages:1,3,640,640;images:4,3,640,640;images:8,3,640,640这样生成的模型在推理时可以根据实际的并发数量灵活选择最优的batch。如果你的业务是偶发性的请求比如每次来1到2张图那就用batch 1的档位延迟最低如果是一批一批的图片任务那就用高batch档位吞吐最大。另外如果同一台服务器上插了多张Atlas卡你还可以把不同的请求分发到不同的卡上做到多卡并行。昇腾的npu-smi info可以实时查看每张卡的使用率和显存占用方便你判断负载是否均衡。4.2 AIPP预处理下沉让CPU轻下来我之前提到ATC转换时用--insert_op_conf传了一个aipp.cfg在这里细说一下。AIPP是Ascend Image Pre-Processing的缩写它可以把图像的缩放、裁剪、格式转换、归一化等操作放到NPU上做而不需要在CPU上用OpenCV处理完再把数据拷到NPU。我的aipp.cfg配置长这样aipp_op { aipp_mode: static input_format: RGB888_U8 src_image_size_w: 1920 src_image_size_h: 1080 crop: true load_start_pos_h: 0 load_start_pos_w: 0 crop_size_w: 640 crop_size_h: 640 resize: true resize_output_w: 640 resize_output_h: 640 csc_switch: true 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 }这个配置的意思是输入是RGB888格式的1920x1080原图先裁剪成640x640再缩放到640x640最后做归一化像素值除以255。min_chn_*和var_reci_chn_*就是归一化参数因为YOLO训练时用的是0-1范围所以这里设成1/255。配置好之后推理的时候就只需要把原始图像数据直接拷给NPU剩下的预处理全部在NPU内部完成。这个优化对性能的提升非常明显我实测下来整个预处理链路能省掉大约2到3毫秒而且CPU占用率几乎为零。如果你的推理场景是视频流每一帧都可能需要处理这个优化带来的收益会非常可观。不过要注意AIPP配置一旦嵌入模型输入数据的格式就必须和配置严格一致。比如你配置了src_image_size_w: 1920那么推理时你只能往模型里塞1920x1080的原图不能塞其他分辨率的。如果业务需求突然变了想处理1280x720的视频流那就得重新转一个模型。所以做AIPP配置之前先想清楚你的输入源长什么样。5. 部署过程中的高频报错与排查思路5.1 从驱动到推理全链路的问题集合我整理了一下自己在Atlas 300V上部署YOLOv5时遇到过的典型问题按出现频率排了个序做成速查表希望能帮你少走弯路。报错信息可能原因解决办法E10001设备不存在驱动没装好或PCIe识别失败重新安装驱动固件检查lspci是否识别到设备E20001模型加载失败.om与芯片型号不匹配确认--soc_version是否为Ascend310P3E19999内部错误算子不支持或内存分配失败用--insert_op_conf简化模型检查--input_shape是否匹配Python进程启动时acl.init失败环境变量没source重新执行source /usr/local/Ascend/ascend-toolkit/set_env.sh推理结果全部为0或全NaN输入数据格式不对确认输入是NCHW排布的float32且已归一化到0-1npu-smi info卡住无输出设备被其他进程占用或固件异常重启设备或重新安装固件这里重点说一下E19999这个错误。这个错字面上是“内部错误”特别让人头疼因为报错信息里不会告诉你是哪个算子出了问题。我的排查方法是先把ATC转换时的日志保留下来看日志里有没有warning级别的提示。通常原因是ONNX模型里存在一些CANN不支持的算子比如某些高阶的GridSample变体。遇到这种情况一个有效的做法是在导出ONNX时加--opset 11或者在导出前把YOLOv5的后处理从模型里拆出来只保留主干网络部分的推理后处理全部放在Python里做。我实战中就是这样做的模型转换的成功率一下子提高了很多。还有两个环境层面的细节。一个是ulimit -c unlimited如果你需要排查程序崩溃后的core dump这个必须打开。另一个是export ASCEND_GLOBAL_LOG_LEVEL1这个可以把昇腾运行时的日志级别调成debug报错时的堆栈信息会详细很多。排查完记得改回0否则日志量太大反而影响性能。5.2 排查工具与日志定位昇腾其实自带了不少好用的排查工具很多人不知道。除了npu-smi info能看硬件状态之外还有一个msprof性能分析工具可以对模型推理的每个阶段做profiling能看到数据拷贝、算子执行、后处理各花了多少毫秒。如果你觉得推理速度不对劲用msprof跑一遍瓶颈在哪里一目了然。另外CANN安装目录下的/usr/local/Ascend/ascend-toolkit/latest/data/里放了一些算子精度的对比基线。如果你的推理结果跟GPU上的结果对不上可以拿这些工具做逐层比对看看是哪个算子精度掉得最厉害。这类问题在YOLO模型里偶尔会出现典型的表现是检测框位置正常但置信度整体偏低排查下来往往是某个激活算子的精度误差累积导致的。遇到这种情况最简单的处理是转换模型时指定--output_typeFP16让模型整体用半精度推理通常能把精度拉回来。日志的话CANN的默认日志目录在~/ascend/log/下面里面有运行时的日志文件。排查问题时最常用的就是plog目录下的日志它记录了算子加载、推理执行、内存分配等全过程的明细。报错的时候直接看日志的最后几百行往往能找到真正的原因。6. 最后的几点实际操作心得Atlas 300V这套东西最大的门槛其实不是硬件本身而是软件栈的“陌生感”。用惯了CUDA的人第一次碰CANN会觉得自己像个新手各种术语对不上号。但如果你耐心地按照“驱动装对→版本匹配→模型转换→推理调通”这个路线走一遍后面就会顺畅很多。我个人经验里有几点想单独拿出来说。第一版本锁定非常重要。昇腾的软件栈跟GPU那边不一样不是“最新就是最好”的。如果你跑的是YOLOv5这种常见模型装一个稳定的老版本CANN反而比追新版更省心因为老版本对应的算子支持和生态打磨更成熟。我目前在用的是CANN 6.3.RC3版本搭配对应的HDK驱动稳定性已经经过长时间验证。第二批量推理比单张推理更能体现这张卡的价值。如果你只是偶尔处理一张图片用Atlas可能感觉不到它比CPU快多少因为模型加载和数据拷贝的开销摆在那里。但如果你写一个队列把多张图片攒起来batch地喂给推理卡吞吐量立刻就能上去。所以我最后的工程实现里都是用一个线程池管理图片队列每攒够8张就做一次batch推理整体速度比单张循环至少快了4倍。第三不要把后处理写死在模型里。把NMS这些操作留在Python端做虽然会多一些CPU开销但换来的是极大的灵活性。实际生产环境里检测结果的过滤逻辑经常要调比如阈值改一下、类别屏蔽一下如果每次都要重新转模型那开发效率就太低了。我自己是把模型推理封装成了一个独立服务后处理全部外置任何改动只需要改Python代码不用动.om模型。最后再分享一个小技巧Atlas 300V 24G是一张可以长期稳定运行的卡但它的散热结构比较简单如果机箱风道不好长时间高负载运行芯片温度可能会到80度以上。建议第一次跑长期任务之前用npu-smi info持续监控温度如果超过85度就该考虑加装机箱风扇或者调整卡位了。温度控制好了这张卡跑YOLO跑个一年半载是完全没问题的。
返回列表