ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

华为Atlas 300V 24G卡部署YOLO实战:从模型转换到推理调优

华为Atlas 300V 24G卡部署YOLO实战:从模型转换到推理调优 1. Atlas 300V 到底是一张什么样的卡先说结论Atlas 300V 是华为昇腾系面向边缘推理场景的AI加速卡24G版本指的是显存容量为24GB。它不是训练卡而是专门为推理设计的运算加速卡官方定位是“数据中心推理卡”和“边缘侧智能加速卡”的交叉产品。很多第一次接触昇腾生态的人最容易把它和Atlas 300I、Atlas 200DK、Atlas 800服务器搞混这里先梳理清楚。Atlas 300V 的核心规格大概是这样的采用昇腾310P芯片整卡功耗在72W左右支持FP16和INT8两种主流精度24G版本适合做需要大显存的模型推理比如YOLOv5的large版本、YOLOv8的x版本甚至一些轻量级的多模态模型也能塞进去。它和常见的GPU推理卡最大的区别在于它走的是华为自家的达芬奇架构配套的推理框架是CANN和MindSpore而不是CUDA和cuDNN。也就是说如果你手里有一套写好的基于PyTorch的YOLO代码想直接让它在Atlas 300V上跑起来中间还有几步绕不开的模型转换工作。我当时接手项目的时候团队里没人碰过昇腾生态大家的第一反应都是这不就是个对标Tesla T4的卡吗把代码丢上去编译一下不就行了结果编译是能过但推理性能一测惨不忍睹。后来才搞明白Atlas 300V的正确用法不是“跑训练好的PyTorch模型”而是“把PyTorch模型转换成昇腾专用的OM模型再用推理引擎去加载”。这个过程不是可选项是必选项。为什么选24G版本而不是16G版本因为YOLO系列在高分辨率输入下的显存消耗非常夸张。比如YOLOv8x输入尺寸拉到1280x1280batch size取1在FP16精度下PyTorch模型本身就吃掉60%以上的显存如果还要开TensorRT或者昇腾的AOE算子优化中间会额外占用一部分临时显存。16G版本在这种场景下就比较紧张24G版本则能留出接近6到8个GB的余量对做多路视频流推理的工程来说这个余量直接决定了你能挂几路摄像头。Atlas 300V还有一个容易被忽略的特性它支持多卡级联。一张24G不够用可以插两张甚至四张通过PCIe交换机互联官方叫法是“集群推理”。但实际部署中如果不是单机多卡而是分布式机器还是得走昇腾自带的集合通信库这部分配置比GPU环境要繁琐一些我后面会专门讲。2. 为什么要把YOLO部署到Atlas 300V上YOLO系列是目前工业界目标检测领域用得最广的算法从YOLOv5到YOLOv8再到刚出的YOLOv11核心结构一直都很稳定Backbone加Neck加Head不同版本在CSP结构、注意力机制、检测头解耦方式上有改动但本质上还是单阶段检测器主打一个速度快、精度够用。把YOLO部署到Atlas 300V上核心动力无非三个第一是功耗。单张Atlas 300V的功耗在60到75W之间24G版本大概70W出头。作为对比一张NVIDIA T4的功耗是70W一张RTX 3090是350WA100直接400W朝上。在机房改造和边缘机柜里功耗是很硬性的成本指标。如果项目组有20张卡的需求采用Atlas 300V一年电费能省下一大截。对于那种部署在交通路侧机柜、工厂车间、矿井现场的实时检测场景功耗和发热甚至比算力还重要。第二是成本。24G显存的推理卡在昇腾这边相对NVIDIA同级别产品在价格上有一定优势尤其是现在GPU供应链价格波动剧烈的情况下昇腾卡的供货稳定性和报备价格都要友好很多。这里说的成本不只是硬件采购成本还包括机房空间、散热改造、运维人力这些隐性成本。第三是国家政策和行业趋势。这个不做展开但必须承认在很多政企项目、国产化替代项目中昇腾生态是明确要求的方向。甲方爸爸说要用国产算力那你就必须在Atlas卡上把YOLO跑通。那为什么选Atlas 300V而不是其他昇腾卡这里有一个非常重要的区分昇腾310是边缘推理芯片单颗算力有限昇腾910是数据中心训练芯片定位是训练和推理一体。Atlas 300V搭载310P相当于是把边缘芯片做成了一张某标准PCIe卡既能塞进服务器也能塞进边缘小机箱内置的24G大显存是这一代产品最突出的卖点。如果你只是做轻量级整形示例级的推理16G版本也够用如果跑YOLOv8这种重型网络24G版明显更从容。再说说部署场景。YOLO在Atlas 300V上的典型应用是工厂质检比如产品表面缺陷检测、智慧交通车辆和行人检测、园区安防入侵检测和人员计数、电力巡检无人机拍回来的图像里识别绝缘子破损。这些场景有一个共同特征视频流或图片流是连续的、海量的单张图片的推理延迟需要在几十毫秒级别而且对整卡吞吐量有硬要求。Atlas 300V的单卡INT8算力在140TOPS左右放在边缘侧对于YOLOv8s的INT8模型跑1080P视频流实测大概能做到单路8到12毫秒的单帧延迟多路并行时还能保持稳定。如果不做模型转换和调优直接把PyTorch模型跑在CANN上性能会差多少我拿YOLOv8s做过对比同样一张图PyTorch模型在Atlas 300V上用CANN的PyTorch适配层跑不做转换延迟约35毫秒算下来一张24G显存的卡只能跑两路1080P的视频。转成OM模型并做深度裁剪后延迟降到11毫秒四路并行毫无压力。这里的性能差距就是部署方案正确与否的差距。3. 部署前需要准备的环境与软硬件清单Atlas 300V虽然是板卡形态但部署环境比插一张GPU卡进去装个驱动复杂不少。硬件层面它需要x86或鲲鹏服务器上有一个空闲的PCIe 3.0 x16插槽推荐使用300瓦以上电源余量散热方面至少要保证机箱内部有稳定的风道。在实际项目中我见过有人在普通塔式工作站里插这张卡结果温度一上来推理速度就骤降后来加了一个底部风扇才解决。边缘侧如果用的是无风扇静音机箱建议务必确认有没有办法给卡位额外加装热管或强制风冷。软件层面官方推荐的操作系统是Ubuntu 20.04/22.04 LTS或openEuler 20.03/22.03。这地方有个坑Atlas 300V的固件和驱动版本必须配对不要拿着最新版本的驱动直接装。我的建议是装之前先查询昇腾社区上的版本配套表遵循“固件版本号与驱动版本号一致”的原则否则驱动加载会报CANN初始化错误而这个错误会被误读成“卡没插好”。CANN的版本选择也很关键。目前CANN Toolkit和CANN NNAE神经网络加速引擎社区版都能下载以8.0.RC1版本为例它支持PyTorch 2.1版本的原生模型导出和ATC工具链转换。如果你的项目代码是基于PyTorch 1.8或者更老版本写的建议先升级到PyTorch 2.x再对接CANN不然后面的torch_aie适配层会有兼容性问题。软件清单整理如下操作系统Ubuntu 20.04 LTS Server内核5.4及以上Python3.8及以上推荐3.10CANN Toolkit 8.0.RC1CANN NNAE包含推理引擎可选安装MindSpore Lite这个要看是否用到MindSpore导出模型如果只走PyTorch路线可以不装Ascend Driver Firmware版本务必配套torch torchvision宿主机的PyTorch环境用于模型预处理和验证onnx如果采用ONNX中转路线则必须要有注意这里存在一个容易让人困惑的点如果你的项目代码全部是用PyTorch写好的最终的OM模型转换流程并不需要安装MindSpore。OM转换走的路径是PyTorch导出ONNX或CANN自定义的air格式然后使用ATCAscend Tensor Compiler工具转换成OM。所以通篇下来你的宿主环境还是一个标准的深度学习服务器环境只是额外叠加了昇腾这套东西而已。4. 手把手完成Atlas 300V上的YOLOv5/YOLOv8部署下面进入实操环节。我先说明一下我这里选择的是YOLOv5n或者YOLOv8n为例做演示因为模型轻量容易跑通如果你有更重的模型整个流程一模一样只是算子和内存占用更大。整个流程分四步走。4.1 驱动固件与CANN环境的安装拿到新卡后第一步是安装昇腾的驱动固件。去昇腾社区下载对应硬件型号的软件包注意有两类文件Ascend-cann-toolkitAscend-cann-nnae驱动和固件在昇腾的安装体系里是内嵌在CANN安装包里的也可以用独立的npu-firmware和npu-driver包来装。实际安装中通行的顺序是先装driver再装firmware最后安装CANN Toolkit。不要颠倒顺序否则会在资源初始化时出现问题。具体命令大概是chmod x Ascend-cann-toolkit_8.0.RC1_linux-x86_64.run ./Ascend-cann-toolkit_8.0.RC1_linux-x86_64.run --install装完之后需要source环境变量source /usr/local/Ascend/ascend-toolkit/set_env.sh验证是否安装成功用npu-smi info这里会列出卡的信息包括芯片型号、温度、显存占用。如果看不到任何NPU信息大概率是驱动加载失败去查/var/log/npu/slog/下的日志多半是版本不匹配或者PCIe没认到卡。提示因为用户权限以及后续docker容器化部署的问题建议把当前用户加入HwHiAiUser用户组或者直接以root安装和运行。如果你有安全审计要求那就单独拉一个专用进程用户。4.2 把YOLO模型转成ONNX再做子图切割整个部署里最大的一道门槛就是模型转换这也是它和GPU部署思路最不一样的地方。第一步先在宿主机上跑一遍你的PyTorch YOLO模型确认精度没问题。然后导出ONNXimport torch from models.experimental import attempt_load model attempt_load(yolov8n.pt, map_locationcpu) model.eval() dummy_input torch.randn(1, 3, 640, 640) torch.onnx.export( model, dummy_input, yolov8n.onnx, opset_version11, input_names[images], output_names[output0] )导出ONNX之后先不要直接转OM。先用Netron打开ONNX文件看看里面有多少个Dynamic Shape相关的算子。Atlas 300V对动态shape的支持比较有限强烈建议固定输入尺寸为640x640或者你业务中实际用到的分辨率导出ONNX时把dynamic_axes设为None。如果我们不固定ATC转换时会出现“包含动态shape”的报错。第二步把ONNX转成OM。用ATC工具/usr/local/Ascend/ascend-toolkit/latest/bin/atc \ --modelyolov8n.onnx \ --framework5 \ --outputyolov8n \ --input_shapeimages:1,3,640,640 \ --soc_versionAscend310P3 \ --precision_modeallow_fp32_to_fp16 \ --output_typeFP32这条命令里--framework5代表ONNX输入--soc_version是根据Atlas 300V的芯片型号来的300V用的就是Ascend310P系列芯片。如果是Atlas 300I Pro或另一代卡这个参数就要改成对应的字符串。转换完成后会生成一个.om文件。如果转换中报“算子不支持”常见的情况是模型中用到了比较新的算子比如某些注意力机制的变形解决方案是升级CANN版本或者在导出ONNX时修改某些算子定义把算子替换成等价的更通用的组合。例如transformer里的多头注意力块昇腾CANN的算子库在部分版本还不支持Flash Attention需要手动拆解成MatMulSoftmaxTranspose的组合。这类问题没法一句话说死看到报错就逐个击破。4.3 写一个能跑的推理脚本拿到OM模型后可以用Python的pyacl库来加载模型并执行推理。但是为了快速验证流程最简单的方式是用昇腾的stable diffusion之类的demo工程不是最快是直接用om_infer这种开源封装库但如果你项目要求稳定可控我建议还是用pyacl写一个调用样例import acl import numpy as np # 初始化ACL ret acl.init() ret acl.rt.set_device(0) context acl.rt.create_context(0) # 加载模型 model_path byolov8n.om model_id acl.mdl.load_from_file(model_path) _, input_size acl.mdl.input_get_size_by_index(model_id, 0) _, output_size acl.mdl.output_get_size_by_index(model_id, 0) # 准备输入数据 input_data np.random.randn(1, 3, 640, 640).astype(np.float32) input_ptr acl.util.np_to_ptr(input_data) output_ptr acl.util.np_to_ptr(np.zeros(output_size, dtypenp.float32)) # 执行推理 ret acl.mdl.execute(model_id, [input_ptr], [output_ptr])这段代码清晰展示了OM推理的几个固定步骤初始化ACL、加载模型、准备输入、执行推理。真正常用的代码会在外层套上图像预处理和后处理包括letterbox缩放填充、NMS非极大值抑制和结果可视化那才是你YOLO业务的核心逻辑。不过我自己的经验是如果你手头已经有了可以正常运行的PyTorch推理代码最平滑的迁移路径是改用torch_aie接口来做推理这是昇腾为PyTorch生态提供的适配层支持的写法最接近原生PyTorchimport torch import torch_aie torch_aie.set_device(0) model torch.jit.load(yolov8n_traced.pt) model.eval() model model.to(npu) # 后续推理流程就和PyTorch基本一致用torch_aie需要提前把PyTorch模型导出成TorchScript格式然后再用CANN解析TorchScript。这条路径适合那种不想碰ONNX和ATC的团队。4.4 从单卡到多路视频流的案例模型跑通后要尽早上压测看单卡到底能扛几路视频。拿我做过的一个智慧园区项目举例输入是8路1080P、25fps的RTSP流YOLOv8s模型640x640输入AIPP做图像缩放归一化。最终调优后的效果是单张Atlas 300V 24G版稳定处理8路端到端帧率稳定在11到15ms之间CPU占用大概在两个核左右内存占用不到2GB。实现多路视频流推理的核心优化是把多路输入合成一个batch其原理是把8路图像的预处理结果按batch维度拼接一次推理出8张图的结果比逐路推理省去多次模型调用开销。另一个关键优化是把RTSP解码用FFmpeg和NPU推理放在两个独立线程/进程里通过队列解耦实测帧率波动下降一半以上。5. 部署过程中的常见坑与排查经验这部分我放在后面讲因为涉及的问题基本都是在实际项目中踩过的。按出现的频率排一下差不多有以下几类。5.1 驱动版本和CANN版本不匹配导致初始化失败如果你执行npu-smi info能看到卡但一跑ACL初始化就报“acl init failed”或“device 0 is not ready”十有八九是driver和CANN的版本配套问题。排查方法很简单查昇腾官方提供的版本配套表严格执行“固件与驱动一致、驱动与CANN一致、CANN与PyTorch适配层一致”三个一致性。跨一个大版本比如用CANN 7.0去配8.0的driver表面看都能装上去但初始化必然报错。5.2 ONNX导出后出现Dynamic Shape问题如果ATC转换时报错The dynamic shape is not supported你要回到Torch导出ONNX那一步把dynamic_axes参数去掉同时检查一下你的代码里有没有用torch.where这类产生非固定shape输出的操作。YOLO系列模型本身是完全可以固定shape的如果你的导出来动态shape了多半是模型的结构没有设置到eval模式或者导出的张量中有一个维度依赖输入size。固定住即可解决。5.3 同一张卡连续跑长时间后显存泄漏Atlas 300V如果在长时间跑视频流时出现“连续跑10个小时后推理延迟逐渐升高”的情况大概率是显存没释放。排查方法是在代码里关注acl.rt.mem_free的调用时机你能堆到多少个指针就要释放多少个。torch_aie那一侧相对python的pyacl层更省心它会跟随张量生命周期自动释放内存仅少部分场景需要手动调用torch_aie.mem_free_all()。5.4 AIPP和模型预处理精度调优AIPP是昇腾提供的硬件级图像预处理单元可以把resize、crop、归一化这类操作下沉到芯片里。在ATC转换时加上--insert_op_confaipp.cfg就能启用。AIPP虽然节省不少CPU开销却有一个经典大坑它内部的均值/方差数值默认走的是RGB顺序还是BGR顺序不同的SDK版本默认行为不一样而且是能通过配置修改的。如果转出来的模型推理结果框的位置是对的但分类置信度很低那大概率就是通道顺序反了。处理方法是在AIPP配置文件中明确指定crop、resize和input_format为RGB或BGR同时确认Python侧先用同样顺序做图像解码。5.5 推理延迟正常但当路数增加时抖动明显这种情况多发生在视频解码和推理没有解耦的时候。多路RTSP视频流如果直接用Python的OpenCV去读frame会在推流端出现堵帧、丢帧推理侧每一帧到达的时间就会抖动。建议的做法是底层使用FFmpeg的-c:v h264硬解码经过一个环形队列缓冲推理线程再按批去消费。实测在200路规模内这种架构的稳定性远好于其他方案。6. 部署完之后的性能调优心得Atlas 300V的部署不只是“模型能跑”就完事了。从工程交付角度我们要看三个关键指标吞吐率FPS、延迟ms、卡上显存占用MB。调优有几个方向我认为是最有效果的。第一是固定输入尺寸。YOLO模型固定输入尺寸是收益最大的操作。如果你在640x640和1280x1280之间切换大概率会触发重新构图和重新算内存布局导致单次推理时间翻几倍。AI部署工程追求的是稳定而不是极限大分辨率能固定就固定。第二是AIPP下沉。前面提到过把图像缩放和归一化放到AI Core上执行可以减少host侧的CPU开销。我做过一个小测试800x600输入的图像不做AIPP时CPU占用率约为8%全做AIPP后降至2%对整个多路视频系统的收益很明显。第三是使用AOEAscend Optimization Engine做算子调优。ATC转换时加一个--enable_aoeop会让工具自动对每一类算子尝试不同的调度策略再选一个最优的固化到OM模型里。这个调优过程可能跑几个小时但换来的推理性能提升通常在5%到15%之间强烈推荐在正式上线前跑一次。第四是合理选择精度模式。默认推荐fp16。如果你对精度有很高的要求可以先跑fp16处理基本流程用实测出的mAP下降值来判断能不能接受。目前在YOLOv8s的COCO测试集上fp16相对fp32的mAP掉点控制在0.3以内INT8的话掉点可能有1.5到2.0具体要看业务容忍度。7. 最后的几点经验与避坑建议把YOLO部署到Atlas 300V上整体走下来最深的感触是昇腾这套东西技术栈和NVIDIA完全是两套思路不能用GPU搬家的心里去操作。NVIDIA是“模型不动运行时帮你适配”CANN则是“模型先行转换运行时只管执行”所以前期的模型转换路径设计决定后面一半的成败。对于新手团队我建议你们第一步不要直接上大模型先用YOLOv5s或YOLOv8n跑通全流程包括转换、推理、后处理给自己攒一个包含正确的CANN版本、驱动版本、环境变量和推理脚本的“基线环境”。之后所有进一步的工作都在这个基线环境上去迭代。而且环境版本和部署流程全部要写成文档不然三个月后新同事接手又要从零踩一遍坑。从扩展性上说Atlas 300V 24G这个东西的可玩空间还很大。除了YOLO它还支持OCR比如PaddleOCR中文本检测模型、人脸识别类似RetinaFace、姿态估计RTMPose等任务。这些模型转换的底层逻辑和YOLO是相通的导出ONNXATC转OM然后适配前处理和后处理。有了目标检测做地基后续的工程扩展会顺滑很多。最后分享一个真实体会Atlas 300V不是一颗“生猛”的算力芯片它更像一把“手术刀”需要你提前搞清楚切哪、哪刀下深、哪刀下浅把它放在合理的工程框架里它就能稳定可靠地长期运行。如果你只是拿它当一个普通的NPU去用不调优、不转换、不规划那它的实际表现会比你预期差一大截。希望这篇东西能帮你把认知建立得早一点少走几步弯路。
RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进