ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

Atlas 300V 24G部署YOLO全指南:推理卡实操与避坑

Atlas 300V 24G部署YOLO全指南:推理卡实操与避坑 Atlas 300V 24G 是运算加速卡吗这个问题最近被问了很多次尤其是准备在服务器上做 YOLO 部署的同学。我的答案很简单是但它不是你想的那种“加速卡”。很多人第一反应是拿它当 GPU 用想着装上就能跑 PyTorch、跑 CUDA结果一上手就发现根本不是那么回事。我在这张卡上完整做完一轮 YOLOv5/YOLOv8 的部署之后算是把这套流程吃透了。这篇就把 Atlas 300V 24G 到底适合干什么、如何从零部署 YOLO、中间会踩哪些坑一次讲清楚。内容不吹不黑全是实操。1. Atlas 300V 24G 到底是什么卡别把它当 GPU 用1.1 一张“推理专用”的 PCIe 加速卡Atlas 300V 24G同系列也叫 Atlas 300V Pro是昇腾生态里专门面向推理场景的加速卡核心芯片用的是昇腾 310P 系列板载 24GB HBM 显存PCIe 4.0 接口插在标准 x86 服务器上就能用。它确实叫“运算加速卡”但加速的是深度学习的推理计算而不是训练计算。这类卡的设计目标非常明确你不是拿它来从头训练模型的而是把已经训练好的模型部署上去做高并发、低延迟的预测。所以它的硬件资源分配、算子库优化、甚至驱动固件的默认配置都是冲着推理去的。这就解释了为什么很多人刚开始看 24G 显存觉得“挺大”下意识就和 RTX 3090、4090 这类显卡比。实际上这两者完全不是一个赛道。显卡是通用并行计算 图形渲染的综合体Atlas 300V 24G 则是专职做神经网络推理的专用芯片。我从实际部署的角度说几个核心区别驱动的 API 完全不同GPU 生态用 CUDA、cuDNNAtlas 用 CANN昇腾计算语言底层是 ACLAscend Computing Language。你没办法把现成的 CUDA 代码拿过来直接跑。模型格式不兼容GPU 上常见的 TensorRT engine、torchscript、ONNX Runtime 的 CUDA 后端在 Atlas 上都不能直接用。最终一定要转化成昇腾专用的.om格式。训练能力偏弱虽然理论上能跑训练但昇腾的优化重心在推理。如果你想在 Atlas 上从头训练 YOLO不是不行只是效率大概率不如用 GPU。正确姿势是“GPU 训练Atlas 推理”。1.2 和 GPU 相比它的优势到底在哪说了这么多“不能直接用”那为什么还要用它我实际用下来最明显的感受是单位功耗的吞吐量确实高。一张 Atlas 300V 24G 的功耗在 70W 到 80W 左右而一块主流推理显卡的功耗动辄 200W 以上。在数据中心里机柜的供电和散热是硬成本。同样是跑 YOLOv5s 这种轻量模型Atlas 300V 24G 在 INT8 精度下能做到很可观的并发推理路数而且卡和卡之间还能组成集群。另外昇腾卡对视频解码有硬件支持。做视频流实时目标检测时可以把解码、缩放、归一化这些预处理放到硬件管线里CPU 负载会明显降下来。这一点在做 YOLO 监控项目、智慧园区项目时非常实用。我画一张简单的对比表方便你理解它的定位对比项Atlas 300V 24G常见 GPU如 RTX 系列核心定位AI 推理加速通用并行计算 / 训练 / 推理软件生态CANN / ACL / MindSporeCUDA / cuDNN / TensorRT模型格式OM由 ONNX/PB 转换TensorRT engine / ONNX / TorchScript训练能力支持但非强项强推理能效比高中高可开发难度需要学一整套新工具链生态成熟资料多所以如果你手头已经有 Atlas 300V 24G又想做 YOLO 检测核心工作就是把正常的 PyTorch/YOLO 流程“翻译”成昇腾能识别的流程。2. 部署 YOLO 之前环境搭建决定了你后面要踩多少坑2.1 软硬件环境清单我先说我这边的部署环境给你一个参照服务器双路 x86 服务器64 核256GB 内存加速卡4 张 Atlas 300V 24G操作系统Ubuntu 20.04昇腾驱动Ascend HDK 对应版本CANNCANN 7.0Python3.9训练框架PyTorch用于导出 ONNX不用于训练昇腾这套东西的软件栈分几层最底层是驱动和固件HDK负责让系统识别卡、管理设备往上是 CANN Toolkit里面包含了算子库、图编译工具 ATC、推理运行时的 ACL再往上是各种框架适配层比如 torch_npu、MindSpore。你执行npu-smi info能正常看到卡说明驱动和固件没问题。但环境没问题不只是“看到卡”还得保证驱动固件版本、CANN 版本、甚至 Python 版本能对得上。不然经常会出现“npu-smi 能看到卡但一执行 ATC 就报 CANN 内部错误”的情况。2.2 版本搭配照着选通常最稳这里我直接给一套经过验证的稳定搭配新手照着来就行操作系统Ubuntu 20.04.5 x86_64Python3.8 或 3.9昇腾驱动固件Ascend HDK 23.0.rc3CANN ToolkitCANN 7.0.RC1PyTorch1.11.0 torch_npu 对应版本ONNX1.12.0为什么要把版本卡这么死因为昇腾的算子和图编译工具对 ONNX 的opset版本、PyTorch 导出的算子版本是有限制的。新版本的 PyTorch 导出的 ONNX 可能会带一些昇腾算子库还没适配的节点转换时就报“算子不支持”。这不是说昇腾垃圾而是闭源生态和开源生态的迭代节奏不一样你只能去迁就它。安装顺序也有讲究我的建议是# 1. 先装驱动和固件 ./Ascend-hdk-*.run --full # 2. 再装 CANN Toolkit ./Ascend-cann-toolkit_7.0.RC1_linux-x86_64.run --install # 3. 设置环境变量 source /usr/local/Ascend/ascend-toolkit/set_env.sh装完之后先执行npu-smi info。输出里能看到类似以下字段就说明卡已经正常------------------------------------------------------------------- | npu-smi 23.0.rc3 Version: 23.0.rc3 | ----------------------------------------------------------------- | NPU Name | Health | Power | | Model | HBM Memory | Temp | -----------------------------------------------------------------看到 4 张卡都显示Healthy之后再继续下一步。3. YOLO 模型转换与推理全流程实操3.1 导出 ONNX 这一步直接影响后面能不能转成功这里我用 YOLOv5 和 YOLOv8 都举例说明因为这两个是目前最常见的。YOLOv5 导出 ONNX 的标准命令python export.py --weights yolov5s.pt --include onnx --opset 11 --batch-size 1YOLOv8 导出 ONNX 的命令yolo export modelyolov8s.pt formatonnx opset11 imgsz640 dynamicFalse simplifyTrue你们肯定会问为什么一定要opset11因为我实际测试下来CANN 7.0 对 ONNX opset 11 的支持最成熟。opset13或更高也不是完全不行但一旦遇到新结构报错的概率会高很多。所以保守一点选择 opset 11。还有一个容易被忽略的地方dynamicFalse。如果你导出了动态 batch 或动态分辨率的 ONNX后面用 ATC 转换时就要额外配置动态维度非常麻烦。对于固定场景的目标检测强烈建议固定输入尺寸比如 640x640batch 先设成 1。另外YOLOv5/v8 原始导出模型里通常只包含主干网络和检测头后处理比如 NMS不在 ONNX 图里。这反而好因为昇腾的算子库对 NMS 这类复杂算子的支持并不稳定后处理放到 CPU 上用 Python 做性能和可控性都更好。3.2 用 ATC 工具把 ONNX 转成 OM核心命令接下来是这个流程里最关键的一步把.onnx转成昇腾专用的.om。以 YOLOv5s 为例命令如下atc --modelyolov5s.onnx \ --framework5 \ --outputyolov5s_310p3 \ --input_shapeimages:1,3,640,640 \ --soc_versionAscend310P3 \ --insert_op_confaipp.cfg \ --output_typeFP32参数说明--framework5表示输入模型是 ONNX。1 是 MindSpore2 是 TensorFlow5 是 ONNX。--output输出文件名会生成yolov5s_310p3.om。--input_shape这里要和 ONNX 的输入名、输入尺寸严格对应。YOLOv5 的输入名一般是imagesYOLOv8 是images。--soc_version这个特别重要。不同芯片的型号名字不一样写错直接报错或者转出来的模型用不了。Atlas 300V 24G 是 310P 系列一般写Ascend310P3。不放心的话用npu-smi info看卡型号或者问供应商。--insert_op_confAIPP 配置文件用于把图片预处理放到 NPU 上做。--output_typeFP32输出数据类型后续做后处理时一般用 FP32省得转类型。再看一下 AIPP 配置aipp.cfg这是很多新手容易忽略的地方。它可以把 resize、减均值、除以 255 这些操作全部固化到转换后的模型里。举个例子aipp_op { aipp_mode: static input_format: RGB888_U8 src_image_size_w: 640 src_image_size_h: 640 crop: 1 load_start_pos_h: 0 load_start_pos_w: 0 crop_size_w: 640 crop_size_h: 640 min_chn: 0.0 var_reci_chn: 0.00392156862745098 }配置完成后运行 ATC。如果转换成功会输出一行类似ATC run success的消息目录下出现yolov5s_310p3.om。如果失败大概率会直接告诉你哪个算子不支持、哪一层报错。转换完成后我建议先用工具看一下模型结构确认输入输出符合预期。可以用 CANN 自带的atc或直接跑一个最小推理测试。3.3 用 ACL Python API 写最小推理 Demo昇腾的推理接口叫 ACLPython 版本叫python-aclCANN 自带。下面是一个最基本的单张图片推理框架import acl import numpy as np import cv2 # 初始化 ACL acl.init() # 设置设备0 表示第一张卡 ret acl.rt.set_device(0) # 加载模型 model_path yolov5s_310p3.om model_id acl.mdl.load_from_file(model_path) # 获取模型输入输出的描述信息 input_desc acl.mdl.get_input_desc(model_id, 0) output_desc acl.mdl.get_output_desc(model_id, 0) # 准备输入数据 img cv2.imread(test.jpg) # 这里要和 AIPP 的输入格式对应一般 BGR 转 RGB img_rgb cv2.cvtColor(img, cv2.COLOR_BGR2RGB) img_resized cv2.resize(img_rgb, (640, 640)) img_np img_resized.astype(np.uint8) # 转换为 NCHW input_tensor np.expand_dims(img_np, axis0).transpose(0, 3, 1, 2).copy() # 这里需要申请 device 内存把数据拷贝到设备侧 # 实际开发建议用 acl.rt.memcpy 完成 host2device 传输 # 定义输出空间假设输出是 [1, 25200, 85] output_np np.zeros((1, 25200, 85), dtypenp.float32) # 执行推理 # 需要传入模型输入输出的 device 指针 ret acl.mdl.execute(model_id, input_tensor, output_np) # 拿到结果后做后处理 NMS # ... # 释放模型 acl.mdl.unload(model_id) # 重置设备 acl.rt.reset_device(0) acl.finalize()上面这个代码我故意省掉了一些内存管理细节因为直接用acl.mdl.execute时有些版本对输入输出点的封装不同。真正写工程代码时必须处理acl.rt.malloc、acl.rt.memcpy、acl.rt.mem_advise这一整套流程。建议初期直接用昇腾官方的pyacl示例代码作为底座把 loading 模型和执行推理的部分改造成适合自己的封装。有一点要注意OM 模型的输出 shape和原始 ONNX 的输出不一定完全一样。YOLOv5s 原始输出通常是1,25200,85但转换后如果 AIPP 动了图像预处理输出排布可能变成1,3,84,8400YOLOv8 的样子或别的格式。所以正式写后处理之前一定要先打印一下模型输出的 shape 和几个数值确认格式再动手。3.4 后处理如何写才不至于成为性能瓶颈后处理通常包括解码输出、过滤低置信度框、NMS 去重。这些操作在普通 CPU 上也能做但数据量一大比如视频流 25 路并发后处理的 CPU 占用会非常可观。我的经验是后处理尽量向量化避免 for 循环尤其是避免 Python 层逐框循环。用 NumPy 批量算速度能快几十倍。YOLOv8 的输出1,84,8400和 YOLOv5 的1,25200,85后处理代码差别很大但核心逻辑都是先做置信度筛选再对剩余框做 NMS。如果单卡要处理多路视频流建议这样设计解码线程只负责把帧读出来放到队列里。推理线程一次取多帧组成一个 batch送入模型。NMS 用多线程并发处理充分利用 CPU 多核。这里有个很实用的建议为了减少 CPU 后处理压力可以让模型输出端尽量简单。比如在 ONNX 导出阶段就用onnx_graphsurgeon把置信度阈值过滤加进去把置信度低于 0.25 的检测结果直接置零。这样模型输出张量依然是大小的但里面大量无意义的框会被提前清掉NMS 阶段的计算量会小很多。这不影响精度只是把后处理中的一部分计算放到了 NPU 的算子里。4. 常见问题与性能调优实录4.1 模型转换报错问题基本集中在三处我在部署过程中遇到最多的 ATC 报错整理成表格你们直接照着排查报错关键字原因解决方案XXX OP is not supported某个 ONNX 算子昇腾当前版本不支持升级 CANN或修改模型结构或用opset11重新导出E1001: input shape not match--input_shape和实际模型输入不匹配用 Netron 打开 ONNX确认输入名和 shapeThe soc_version is not supported--soc_version写错执行npu-smi info查看卡型号确认是310P3还是别的ATC run failed with error codeCANN 内部错误通常是版本不匹配检查 CANN 和驱动版本重装到推荐版本其中“算子不支持”是重点。YOLOv8 的某些模块可能会用到GridSample、DeformConv2d这类算子310P 的算子库不一定覆盖。所以我在 3.1 节强调导 ONNX 时尽量用simplifyTrue做图优化能去掉很多冗余算子。还有一个隐蔽的坑ATC 默认会做算子精度选择如果检测到某些算子可以用 FP16 而模型是 FP32可能会混精度。结果就是你转换成功但推理出来的框和 GPU 上有微小偏差。如果项目对精度要求严格用--output_typeFP32并且可以在转换时指定--enable_auto_mix_precisionfalse强制不走混合精度。4.2 推理速度慢先自查这三个环节很多人转换成功、也能出结果但就是速度不理想。我觉得 80% 的情况出在下面几个地方没用 AIPP预处理全在 CPU 上跑。我见过一个案例跑一帧图 CPU 预处理要 30msNPU 推理只要 5ms整体速度被预处理拖垮。解决办法就是把 resize、归一化、色域转换全部写进 AIPP让硬件负责。batch size 太小。Atlas 300V 24G 这种推理卡批量小的时候算力根本喂不满。如果业务能攒一批再推理尽量把 batch 提到 4 或 8。我实际测过YOLOv5s batch8 时单帧平均延迟反而比 batch1 低很多因为算力利用率上来了。用了同步推理而不是异步推理。ACL 提供同步acl.mdl.execute和异步接口acl.mdl.execute_async。如果做实时视频分析强烈建议走异步 多线程流水线。一组线程负责预处理和送入另一组负责接收输出让 NPU 一直处于“有活干”的状态。调优时可以先跑一下npu-smi info观察AI Core利用率。如果利用率很低但延迟高多半是预处理或排队问题如果利用率很高但延迟高那就要从模型本身结构上去优化了。4.3 显存占用不合理模型越大不一定越难处理Atlas 300V 24G 有 24GB 显存听起来很多但跑模型时如果设置不当很容易爆显存。我踩过一个坑用 ATC 转换时默认会把一些中间结果都保留下来模型显存占用会莫名其妙的涨。后来在 ATC 命令里加了--buffer_optimizeon情况好很多。另外推理完每一批数据一定要记得释放显存。很多人用 Python 写循环深度学习框架的内存管理器会自动回收但 ACL 的显存不会。每一次acl.rt.malloc都必须有对应的acl.rt.free。否则跑一段时间后显存逐渐被吃满最后报错。多卡场景下注意acl.rt.set_device(id)的切换。如果 4 张卡分别做不同任务进程里要管理好设备上下文避免反复切换导致性能抖动。更专业的做法是用 ACL 的流Stream机制让多张卡并行执行。4.4 视频流 YOLO 部署别忘了硬件解码如果用 Atlas 做视频流实时检测不要只盯着模型推理。视频解码也是一个大头。一个 1080p 25 帧的视频流纯软件解码 CPU 占用可能超过 30%。如果你有 10 路视频CPU 直接被解码吃满后处理就没资源了。昇腾卡自带硬件解码能力常见做法有两种通过 CANN 的 DVPP 接口直接做视频解码、抠图、缩放。使用 FFmpeg 挂载昇腾硬解码插件把解码帧送到 NPU 前处理。DVPP 的接口比较底层但能拿到最佳性能。如果项目时间紧可以用 FFmpeg 硬解方案它把解码后的数据直接给到 AIPP链路简单很多。两种方案我都试过最终线上用的 FFmpeg AIPP 批量推理的组合因为维护成本低性能也够用。这个方向的详细代码量很大以后单独写一篇。今天先给一个思路视频流项目不要只优化模型解码、收流、推理、后处理是一条完整流水线瓶颈经常在你看不见的地方比如内存拷贝、CPU 解码、队列阻塞。最后再分享一个经验Atlas 300V 24G 这套卡和我之前用 GPU 的思维惯性完全不同。刚上手那几天真的非常难受想跑的模型跑不起来能跑起来的又不知道怎么加快。但熬过前面这一段搞懂模型转换、AIPP、异步推理这几件事之后它能发挥出来的推理吞吐量确实很夸张尤其是做高并发视频流检测这类场景。我个人的体会是别把 Atlas 当成 GPU 的替代品而要把 Atlas 当生产环境里的一台“推理引擎”。在训练侧继续用你熟悉的 PyTorch在部署侧严格按照昇腾的规范做转换和优化。二者分工明确才是这套硬件最舒服的用法。如果你也正准备把 YOLO 部署到 Atlas 300V 24G 上建议第一步先把模型转换跑通哪怕只是跑通一张图也别急着做多路视频流。把链路打通后再逐步加 batch、加并发你会看到性能提升远超预期。最后再提一个很实用的小技巧多张卡协同工作时不要让进程绑定在某一张卡上而是启动后动态查询npu-smi选择当前空闲的一张卡来跑。这样整体吞吐会均匀很多不容易出现“一张卡跑到冒烟、另一张卡闲着”的尴尬情况。
返回列表