ARTICLE DETAIL

资讯详情

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

昇腾Atlas 300V推理卡部署YOLOv5:从模型转换到性能调优

昇腾Atlas 300V推理卡部署YOLOv5:从模型转换到性能调优 最近被问得最多的两个问题一个是“atlas部署yolo怎么搞”另一个就是“atlas 300v 24g 是运算加速卡吗”。我猜很多人是在选型阶段或者刚拿到卡准备跑模型对这张卡的认识还停留在“华为出的一个加速卡”的层面。刚好这段时间我自己完完整整把一张Atlas 300V 24G从拆箱、驱动、工具链到跑通YOLOv5推理走了一遍中间踩了不少坑也把很多网上说得模棱两可的细节给确认了。这篇就把整条链路写清楚从这卡到底是什么到模型怎么转再到推理代码怎么调、常见报错怎么排查一次性讲透。如果你是属于下面这几类人这篇文章应该正好对胃口刚拿到Atlas 300V准备做视频检测的部署工程师正在评估推理卡选型、想知道24G显存到底有没有用的算法负责人以及被要求“把YOLO部署到昇腾上”但还没摸清CANN、ATC、OM这些概念的同学。我会尽量用部署现场的口吻讲少一点官方文档腔多一点实操里能直接用上的东西。1. 先说结论Atlas 300V 24G到底是一张什么卡1.1 “运算加速卡”这个说法不准确准确叫AI推理加速卡直接回应标题里的问题Atlas 300V 24G是运算加速卡但要加一个限定词——它是一张AI推理加速卡不是一张通用的并行计算卡。这个区别很重要。我们平时说的GPU比如NVIDIA的A100、L40S那是通用GPGPU既能做训练也能做推理还能跑CUDA做各种通用计算。Atlas 300V不一样它内部核心是昇腾310P芯片硬件上大量面积给了AI Core这种专用计算单元算力调度逻辑、指令集、内存访问模式都是围绕神经网络算子设计的。你可以把它理解成一个“模型推理专用加速器”跑卷积、矩阵乘法、激活函数这些深度学习算子非常快但你要是真想拿它跑个通用并行任务或者写一段自定义的向量化计算逻辑基本无从下手。所以很多第一次接触Atlas的人会陷入一个思维误区拿它去和GPU做全面对比问“能不能跑CUDA”“能不能兼容PyTorch”。实话说不兼容。PyTorch跑在Atlas上要么通过MindSpore或者torch_npu这类适配层重新编译算子要么得先把模型导成ONNX再转成昇腾自己的OM格式然后调用ACLAscend Computing Language的接口去推理。这套流程我在后面几节里会详细讲这里先记住一个基本认知Atlas 300V不是用来替代你手头GPU的它是给“已经训练好的模型”做固定场景批量推理用的。从应用形态上看Atlas 300V 24G是一块标准的PCIe板卡常见形态是单插槽宽度被动散热或者主动散热都有最大功耗我记得在几十瓦量级和一张动辄两三百瓦的GPU比起来功耗低得非常明显。这意味着什么一台普通的2U服务器里你可以轻松插上四五张甚至更多组成一个高密度推理节点。比如一个需要同时处理几十路摄像头画面的视频分析系统用GPU去跑卡的功耗和成本都会很难受用Atlas 300V这种低功耗推理卡反而很合适——单卡能做的事情不多但堆卡密度高整体吞吐很可观。这一点在后面的性能调优部分我会专门展开。1.2 24G这个容量到底能干什么用很多第一次看到“24G”的人第一反应是“这卡比我的3060显存还大是不是很牛”。要泼一盆冷水Atlas 300V上的24G和我们一般理解里的GPU显存不太一样它的作用是给推理模型存放权重、中间特征图和运行时buffer用的。大容量当然有好处你能同时加载更大的模型、开更大的batch或者同时驻留多个模型但它是“容量”优势不是“带宽”优势。如果你是想在24G里跑大语言模型那思路就错了——Atlas 300V的定位是视觉推理场景最舒服的活是YOLO、ResNet这类CNN模型的目标检测、分类、分割任务。以YOLOv5s举例FP16精度的权重本身只有不到30MB推理一张640x640图片时中间特征图占用的空间也就几百MB。哪怕batch开到16整个模型的运行时内存可能也就占用1~2GB。那么24G是不是浪费不一定。你在实际部署时一个很常见的做法是把多个模型同时加载进内存或者把几路视频流各自建独立的推理实例这种情况下内存就是硬通货。比如同一张卡里挂YOLOv5做检测、挂一个人脸识别模型做特征提取再挂一个分类模型做二次过滤如果把所有模型的推理实例都跑在一个NPU上并发调度24G的余量会给你很大的设计空间。算力方面Atlas 300V 24G官方标称的INT8算力在百TOPS级别FP16大概减半。这个数字放在今天的AI加速卡市场里不算最顶级但考虑到它的功耗能效比确实不错。实际跑YOLOv5s如果前处理和后处理都做了比较充分的优化单卡跑到几百FPS是常见水平。别拿这个数字和张A100比A100跑同样的模型也不是不能跑但你要比的是“每瓦特能处理多少路视频流”Atlas 300V这种卡的优势一下就出来了。2. 部署前环境准备版本永远是最大的坑2.1 硬件确认与驱动安装不管你是买的整机还是只有一张板卡先确认服务器本身没问题。Atlas 300V 24G走的是PCIe 3.0 x16接口理论上近五六年内的x86服务器都有这个插槽。关键是供电有些老的服务器PCIe插槽供电能力弱尤其是插满多张卡之后建议提前确认服务器背板供电规格避免推理时掉卡或者性能不稳定。硬件装好后最优先的一步就是装驱动和固件。华为的昇腾软件栈分成几个层次最下面是HDKHuawei Development Kit里面包含驱动和固件再往上是CANNAscend Computing NN工具链相当于CUDA Toolkit的角色。装驱动的过程我用的是华为官方提供的run包在root权限下执行安装安装时会自动加载内核模块。装完先别急着装CANN先用命令npu-smi info验证一下驱动是否工作正常。如果能看到卡的名称、芯片型号、显存大小、温度这些信息说明底层已经通了这时候再继续往上层走。这里强烈建议装完驱动后做一个记录把npu-smi info里显示的芯片型号抄下来。后面模型转换时要填--soc_version参数这个参数对不上ATC转换必然报错。比如Atlas 300V Pro 24G用的昇腾310P系列芯片不同小步进的soc_version写法不一样常见有Ascend310P1、Ascend310P3等装完驱动npu-smi info里看到的芯片型号是最直接的参考。2.2 CANN工具链的版本对齐装CANN之前先把版本对应关系查清楚。昇腾整个软件栈对版本匹配要求比较严格驱动版本、固件版本、CANN版本三者之间有配套关系如果你随便拿一个旧版本驱动配一个新版本CANN很可能会出现“能装上但跑不通”的情况。我这次踩过最典型的坑就是驱动是旧版本的CANN用了最新的6.x结果模型转换和推理时总是报一些莫名其妙的错误比如runtime初始化失败、设备不存在查了半天最后把所有组件都降到配套版本才解决。安装时建议用一个干净的Ubuntu 20.04或者22.04系统x86_64架构。整个安装流程可以拆成三步# 1. 以root身份安装HDK驱动固件 ./Ascend-hdk-*.run --full --install # 2. 安装CANN toolkit ./Ascend-cann-toolkit_*.run --install # 3. 设置环境变量 source /usr/local/Ascend/ascend-toolkit/set_env.shCANN装好之后ascend-toolkit目录下会有atc、msame等工具。atc是模型转换工具负责把ONNX转成OMmsame是一个简易的推理测试工具后面验证模型用得上。建议装完后顺手建一个环境变量文件把set_env.sh的source语句写进去不然每次新开终端都要手动执行一遍。还有一点如果你的操作系统是CentOS或者其他较老的发行版装之前先确认内核版本是否在官方支持列表内。昇腾驱动是内核模块内核版本和gcc版本不匹配会导致编译失败。真遇到编译失败不用死磕先确认内核头文件是不是已经装了yum install kernel-devel-$(uname -r)这种操作会很常见。2.3 CANN的“系统里到底多了什么”装完CANN后很多人会疑惑这玩意儿装了一大堆东西到底哪些是我用得上的我简单梳理一下几个核心组件atc模型转换编译器。管你把ONNX、TensorFlow的pb、MindSpore的模型转成OM格式转换时可以指定输入shape、AIPP配置、量化参数。msame离线推理验证工具。不需要写代码给定一个OM模型和输入数据跑一次推理输出结果适合快速验证模型在NPU上是否正确运行。pyACLACL的Python绑定。官方提供了一套Python接口绕开C编译的麻烦直接写Python调用推理卡。profiling工具性能分析工具。如果你发现卡上的推理性能达不到预期可以靠它看每个算子的耗时、NPU利用率、带宽瓶颈在哪儿。把这些工具用熟了你部署一个新模型的基本流程就固定了拿到模型权重转ONNX用atc转成OM再用msame或pyACL做推理验证最后按业务场景封装成服务。理解了这个流程你就知道为什么我说Atlas的部署链路虽然麻烦但一旦版本环境理顺了后面换模型其实挺模式的。3. YOLO模型上卡全流程从pt到om再到推理3.1 首先导出一个干净的ONNX在Atlas 300V上跑YOLO前提是得有一个ONNX模型。为什么是ONNX因为ATC目前最稳定的输入格式就是ONNXPyTorch的pt文件不能直接吃TensorFlow的pb也不是最优路径。YOLOv5官方仓库本身带了导出脚本操作起来很直接python export.py --weights yolov5s.pt --include onnx --opset 11这个命令会生成一个yolov5s.onnx。这里要特别注意几个细节第一输入尺寸最好固定。YOLOv5默认训练尺寸是640x640导出时默认就是640x640。你在做推理时如果图片分辨率不固定后面要么通过AIPP做缩放要么在CPU侧做预处理。推理卡在做静态shape的模型时性能是最好的所以强烈建议导出时就固定一个输入尺寸不要使用动态shape。虽然ATC支持动态shape但动态shape意味着NPU运行时需要动态规划内存和计算图往往会对性能产生不小的损耗。第二导出时不要包含后处理。YOLOv5的官方导出脚本默认只导出到检测头之前的网络结构输出是类似[1, 25200, 85]的张量也就是每个anchor框的坐标、置信度和类别概率。很多业务方希望导出端到端的模型把NMS也包进去这样做的好处是部署代码简单但坏处是ATC转换可能失败后处理算子不一定是昇腾的高效算子反而不如把NMS留在CPU上用成熟的OpenCV和NumPy实现来得灵活。我建议的做法是ONNX只包含主干网络和检测头NMS全部留在应用层这样模型的通用性和可调试性都更好。导出后可以用onnx库快速检查一下模型的基本信息import onnx model onnx.load(yolov5s.onnx) print(model.graph.input) print(model.graph.output)确认输入是[1,3,640,640]输出是[1,25200,85]之类就说明模型导出的结构是完整的。3.2 用ATC把ONNX转成OMONNX准备好之后下一步就是用atc做转换。命令长这样atc --modelyolov5s.onnx \ --framework5 \ --outputyolov5s_bs1 \ --input_shapeimages:1,3,640,640 \ --soc_versionAscend310P3 \ --output_typeFP16简单解释几个关键参数--framework5表示输入是ONNX--output是输出OM文件的前缀--input_shape固定输入尺寸和batch--soc_version填型号对应的芯片版本比如Atlas 300V Pro常见的Ascend310P3--output_typeFP16把网络权重转成半精度推理速度和内存占用都会更友好。转换过程可能遇到的主要问题是算子不支持。比如YOLOv5导出时如果opset版本太高某些算子ATC不认识会直接报错。解决办法一般是把opset降到11或12重新导出AT科学在ONNX算子兼容性上对于低版本的算子支持要好很多。如果遇到单个算子不支持的情况就需要通过修改模型结构规避比如替换某些自定义激活函数、把某些特殊上采样方式改成标准Upsample。这一步是最花时间的但成熟模型一般不太需要大改。ATC转换成功后会生成一个.om文件。这个文件可以理解成“针对当前芯片版本的NPU可执行程序”它和具体的soc_version绑定也就是说你在Ascend310P3上转换的OM拿去另一个芯片型号不同的Atlas卡上是跑不了的。这也是为什么前面强调要提前确认芯片型号。3.3 AIPP到底要不要配怎么配AIPP是昇腾里一个容易被忽视但影响很大的概念。简单说AIPP是一套预处理加速机制让你在模型输入之前把图像缩放、色域转换、归一化这些操作从CPU挪到NPU的专用硬件单元里去执行。配置好AIPP后CPU只需要把原始图像数据扔给卡卡在硬件层面上帮你完成resize和RGB/BGR转换能明显降低CPU开销提升整条处理链路的吞吐。AIPP的配置是通过一个单独的cfg文件在ATC转换时用--insert_op_conf参数嵌进OM里。下面是一个常见的AIPP配置示例aipp_op { aipp_mode: static input_format: RGB888_U8 src_image_size_h: 640 src_image_size_w: 640 csc_switch: true rbuv_swap_switch: true }这个配置的含义是输入图像是RGB888格式的原始8位数据尺寸已经是640x640同时做色域转换和R/B通道交换。配置好AIPP后你的预处理就简化成“把图像数据按指定尺寸放好直接喂给卡”剩下的交给硬件。但这里有一个YOLO系列独有的坑LetterBox。YOLOv5在预处理时并不是简单的resize而是先把长边缩放到640再把短边填充到640保证原始宽高比不变。AIPP自带的能力里resize是硬缩放没有letterbox的“等比缩放加填充”这种组合操作。如果你直接把一张1920x1080的图扔给AIPP做resize它会变成变形的640x640推理结果完全不可用。我这次实际采用了两种方案之一第一种如果业务上允许轻微的形变比如车牌识别或者文档检测对这种形变不敏感直接让AIPP做resize推理速度最快第二种如果场景对检测框精度要求高就在CPU侧先完成letterbox转换后的640x640图再交给AIPP做色域转换和归一化AIPP不参与resize。选择哪种方案取决于你对精度的容忍度但你必须清楚AIPP不能自动帮你完成letterbox否则会在预处理上栽大跟头。3.4 推理代码与运行验证模型转好后先别急着写业务代码用msame工具跑一次确认模型在卡上真的能输出正常结果。msame的用法很简单msame --model yolov5s_bs1.om \ --input ./input_data.bin \ --output ./output/输入数据建议用一个预处理好的640x640 RGB raw文件可以用Python先导出一个bin。运行完之后output目录下会有一个二进制输出文件这个文件就是模型的原始输出对应的就是[1,25200,85]格式。能正常输出且数值不为空就说明OM模型本身没问题。如果msame这一步都过不了就不要往后写代码了先回头查转换参数。确认模型OK之后下一步就可以用pyACL写推理脚本了。核心流程稳定且模式化大致是四个步骤初始化设备、加载模型、构造输入输出、执行推理。import acl # 1. 初始化 acl.init() acl.rt.set_device(0) context, ret acl.rt.create_context(0) # 2. 加载模型 model_path byolov5s_bs1.om model_id, ret acl.mdl.load_from_file(model_path) # 3. 准备输入输出简化示意 input_data preprocess_image(test.jpg) # 返回 numpy 数组 # 这里需要把 numpy 转成 ACL 的 Tensor/DataBuffer参数较多建议参考CANN官方sample # 4. 执行推理 ret acl.mdl.execute(model_id, input_buffer, output_buffer) # 5. 释放资源 acl.mdl.unload(model_id) acl.rt.destroy_context(context) acl.rt.reset_device(0) acl.finalize()实际代码会比这个长不少主要在于numpy数组和ACL数据缓冲区的转换、输出后处理这两块但核心思路就是这个节奏。建议不要从零写直接去CANN安装目录下找官方样例一般有resnet50或者目标检测的sample把里面的输入输出处理逻辑抄过来改一改比自己造轮子快得多。推理完成后拿到的是[1,25200,85]的原始张量。后处理要做的事是把位置信息和置信度解析出来然后做NMS去除重叠框。YOLOv5输出格式里最后85个维度的前4个是box坐标第5个是objectness后面80个是各类别分数。你需要先把box坐标按照letterbox变换的缩放比例映射回原图坐标再过滤低置信度框最后做NMS。这部分的优化对整体FPS影响很大我后面会专门说。4. 性能调优与问题排查记录4.1 影响部署体验的三个关键因素模型能跑通只是第一步真正上线关注的是吞吐和时延。在Atlas 300V上部署YOLO我发现影响最终体验的核心因素有三个。第一个是batch size和并发模式。如果你对时延敏感用batch1单发模式单张图片延迟最低如果你对吞吐更在意尽量把多路视频帧攒一起用较大batch一次推理比如batch4或batch8卡上计算单元的利用率会明显提高。实际项目中一个很实用的方案是建立帧缓冲池把多个视频流来源的帧按批凑齐再统一推理吞吐能提升好几倍。第二个是前处理和后处理的位置。AIPP能帮忙分担resize和色域转换但letterbox和NMS这类操作目前基本只能在CPU上跑。在一个多路视频的部署场景里如果每帧图像的分辨率特别大CPU光做resize和letterbox就可能成为瓶颈你就会看到模型在NPU上算得飞快但整体FPS就是上不去原因是CPU被预处理拖垮了。我的建议是先用一个简单的性能剖析工具看看CPU占用如果预处理占用了超过30%的CPU优先考虑把resize挪到AIPP里或者启用多线程处理。第三个是模型量化和精度权衡。FP16推理比FP32快不少内存占用也更低但如果你要追求极致性能可以尝试INT8量化。ATC支持对ONNX做INT8量化和校准量化后的YOLOv5s在Atlas 300V上推理速度会有明显提升精度损失通常可以接受。不过量化需要对验证集做校准不是一步到位的如果精度掉了太多可以先做部分层量化或混合精度也可以直接回到FP16不用死磕INT8。4.2 常见报错与现象排查表部署过程中会遇到各种报错我整理了几个最常见的问题和排查思路现象可能原因排查方向npu-smi info看不到卡驱动未正确加载或PCIe链路异常使用lspci | grep -i ascend查看硬件是否被系统识别modprobe drv_pcie手动加载驱动模块确认BIOS里PCIe slot是否被禁用ATC转换报错E12001或算子不支持ONNX中算子版本与AT科学兼容算子不匹配降低onnx opset版本重新导出用onnxsim简化模型结构把模型里特殊算子替换成标准算子推理输出全为0或结果疯狂预处理与训练时不一致核对AIPP的色域配置、归一化系数、letterbox方式检查输入数据是否BGR/RGB顺序反了逐个尝试不同预处理策略模型推理FPS远低于预期瓶颈在CPU预处理或者batch太小先跑msame测纯NPU推理耗时排除CPU干扰将resize和色域转换挪到AIPP增大batch检查是否有动态shape导致的额外开销加载模型报内存不足24G内存不足或模型太大/驻留太多实例用npu-smi info查看显存占用检查是否有遗漏释放的推理实例降低batch size或同时驻留模型数量推理时随机崩溃或复位供电不足或驱动固件版本不稳定检查PCIe供电和散热升级驱动固件到配套版本查看系统日志中的NPU错误信息这些排查思路能覆盖大部分部署问题。如果遇到上述列表以外的情况最有效的方法是去昇腾社区或者GitHub上搜一下错误码很多问题都是文档里看不到、但社区里已经有人踩过坑并给出解决办法的。4.3 三个值得提前知道的“经验之谈”第一个经验是拿到卡后第一件事是跑通官方sample而不是直接上自己的模型。官方提供的resnet50或者目标检测样例是经过充分验证的环境如果连官方sample都跑不通说明你的驱动、CANN版本或服务器环境有问题这时候不要怀疑自己的模型回头查环境。我这次是先把resnet50的sample跑通再换成YOLOv5s整体路径顺了很多。第二个经验是升级CANN之前先做回归。昇腾的软件栈版本更新频率很快新版本通常会带来性能提升和新算子支持但也会带来兼容性问题。我在部署过程中有一次从CANN 5.1.x升到6.x结果原本能正常转换的ONNX模型突然报错最后只能回退到旧版本。如果你当前环境已经稳定运行不要为了一个“看起来更好”的新版本贸然升级先在一个测试环境里做完整回归确认没有问题再应用到生产上。第三个经验是用profiling工具看数据别用猜。很多人觉得推理性能不够第一反应是“换更高规格的卡”但很多时候瓶颈根本不在NPU。CANN自带的profiling工具能给出NPU占用率、算子耗时、内存带宽等数据用数据判断瓶颈在哪里再决定是优化预处理、增大batch还是调整模型结构比盲目调参要靠谱得多。最后再分享一点我的实际感受几轮折腾下来我的体会是Atlas 300V 24G这类推理加速卡最大的舒适区是“模型已经固定、业务已经定型、需要海量并发推理”的阶段。如果你还在频繁改网络结构、还在做各种实验那GPU或者直接用CPU都比它方便但如果你已经明确要在几十上百路视频流上稳定跑一个YOLO模型那它的低功耗、高密度部署特点就会变得非常明显。一台服务器插几张Atlas 300V一个标准的视频分析节点就搭起来了整体功耗比同级别的GPU方案友好太多。如果你现在正准备做选型或者刚拿到卡我建议你给自己留出至少一周的环境熟悉时间第一天装驱动和CANN第二天跑通官方样例第三天完成自己的YOLO模型转换后面几天专门调精度和性能。不要指望半天时间就能把YOLO跑起来环境问题、版本问题和预处理问题都是需要时间磨的。最后一个小技巧所有关键步骤的命令、版本号、报错信息都记录下来昇腾这套软件栈的排查可以说大半靠版本记录手上有记录遇到问题能少走很多弯路。
返回列表