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

Atlas 300V 24G实战:YOLO模型迁移与推理性能调优全记录

Atlas 300V 24G实战:YOLO模型迁移与推理性能调优全记录 ★ FEATURED ARTICLE
身边好几个搞视觉的朋友最近都在问同一件事昇腾的 Atlas 300V 24G 到底是不是一张运算加速卡能不能用来跑 YOLO。我一开始还以为大家就是闲聊结果发现是真有人拿着这块卡踩了一周的坑最后连模型都没加载起来。说实话Atlas 300V 24G 确实是标准的 AI 推理加速卡而且恰恰是当前中等规模视觉项目里性价比很能打的一块卡。我前几个月刚把一个 YOLOv5 检测服务从 GPU 迁移到 Atlas 300V 24G 上整个过程比想象中弯弯绕绕多一些但一旦把驱动、工具链、模型转换这条路走通后面的推理效率相当稳。这篇文章不打算写成产品手册就把我实际部署 YOLO 时遇到的细节、坑、以及最后的调优记录全部分享一遍。如果你正好在评估或者已经拿到了 Atlas 300V 24G想用它跑 YOLO 系列模型那这篇文章应该能帮你省下至少一周的折腾时间。1. Atlas 300V 24G 到底是一张什么卡1.1 一张“运算加速卡”的准确含义先说结论Atlas 300V 24G 是一张面向数据中心的 AI 推理加速卡核心定位是“推理”而不是“训练”。很多人一听到“加速卡”就以为和英伟达的 RTX 4090 一样啥都能干其实不是一回事。Atlas 300V 24G 内部用的是昇腾 AI 处理器集成了达芬奇架构的 AI Core专门针对神经网络算子做了硬件加速和张量核心在 GPU 里的作用有点类似但在推理场景下能效比往往更好。我之前给一个做工业质检的客户评估方案对方拿了几张卡做对比测试。同样的 YOLOv5s 模型输入分辨率 640x640单张 Atlas 300V 24G 在 FP16 推理下能跑到大概 700 FPS 以上batch size 为 1只算模型推理不含前后处理而对比某品牌的入门级游戏卡功耗翻了将近一倍帧率还跟不上。如果你只用它做推理、做图像分析那它就是一张标准的运算加速卡。如果你非要用它训练大模型那只能说选错工具了。1.2 24G 显存意味着什么24G 指的是卡上 HBM 显存容量。HBM 的优势是带宽高对于神经网络这种需要海量权重和中间特征图搬运的场景来说带宽往往比容量更关键。举个例子YOLOv5s 的权重文件只有大概 14MB看起来很小但推理时每一层都要读权重、写中间结果如果显存带宽不够算力再强也只能空转。Atlas 300V 24G 的显存带宽比我之前用过的很多 10G 级别加速卡高一大截这也是它能在小 batch 下维持高帧率的原因之一。24G 容量的实际意义也很明显。除了可以轻松装下 YOLOv8s、YOLOv8m 这类几十 MB 到一百多 MB 的模型外还能把多路视频流的推理任务全部塞进显存。比如一个 16 路的实时检测系统每路视频流需要独立的输入缓存、预处理中间结果和输出结构体如果显存只有 8G很容易在长时间运行后因为内存碎片或者缓存堆积触发申请失败。我用 24G 跑 16 路 1080p 视频流显存占用峰值大概在 6G 到 8G 之间余量相当充裕。1.3 适合跑 YOLO 的哪些场景从我实际接触的项目来看Atlas 300V 24G 特别适合三类场景。第一类是边缘服务器上的实时目标检测比如工厂流水线质检、工地安全帽识别、园区安防监控这类场景通常需要 24 小时在线对功耗和稳定性要求高GPU 方案往往功耗超标Atlas 300V 24G 的板卡功耗控制得不错。第二类是智慧交通、车流统计和违章检测需要同时处理多路摄像头视频流这块卡的多路并发能力很强。第三类是需要在昇腾平台做模型迁移验证的团队也就是你手上有已经训练好的 YOLO 权重想低成本迁移到国产化推理设备上。这类团队最关心的是“能不能轻松部署”而这件事的答案恰恰取决于你对昇腾工具链的熟悉程度。2. 部署 YOLO 前的环境准备2.1 硬件与软件版本选型我踩的第一个坑就是版本乱配。Atlas 300V 24G 有两套软件栈一套是旧的 DDK另一套是现在的 CANN昇腾计算语言。现在官方主推 CANN所以别再去搜那些老教程了。部署前你最好把下面这些信息列清楚避免装到一半才发现冲突。我这次使用的环境如下组件版本主机操作系统Ubuntu 20.04.6 LTS昇腾驱动23.0.3CANN Toolkit7.0.0CANN Kernels7.0.0Python3.8.10PyTorch2.1.0仅用于导出 ONNX不用于推理推理框架ACLAscendCL要注意的是驱动和 CANN 的版本必须相互匹配。官方文档里有个兼容性列表但很多人不会去细看结果装了新驱动却配了旧 CANN导致aclrtSetDevice直接报 507033 错误。我的建议是直接下载同一批次的驱动和 CANN 包这样最省心。2.2 安装 CANN Toolkit 与驱动安装过程其实不复杂但步骤顺序不能乱。我整理了一个相对稳妥的流程照着做基本不会出问题。第一步安装依赖包。Ubuntu 系统先执行apt-get update apt-get install -y gcc g make cmake zlib1g zlib1g-dev openssl libsqlite3-dev libssl-dev libffi-dev unzip pciutils net-tools libblas-dev gfortran libblas3第二步安装驱动。拿到驱动包以后直接运行安装脚本chmod x Ascend-hdk-*.run ./Ascend-hdk-*.run --full --quiet--full表示装全量驱动包括固件。如果环境里之前装过老版本建议先卸载干净再装否则可能出现固件版本高于驱动的诡异问题。第三步安装 CANN Toolkit。同样是一个.run文件解压后执行chmod x Ascend-cann-toolkit_7.0.0_linux-x86_64.run ./Ascend-cann-toolkit_7.0.0_linux-x86_64.run --full --quiet安装完成后默认路径在/usr/local/Ascend/ascend-toolkit/latest。2.3 配置环境变量与依赖检查这一步看着简单但漏掉一个变量就可能导致后面的atc命令找不到。我在/etc/profile.d/ascend.sh里配置了以下内容export ASCEND_TOOLKIT_HOME/usr/local/Ascend/ascend-toolkit/latest export PATH${ASCEND_TOOLKIT_HOME}/bin:${ASCEND_TOOLKIT_HOME}/python/site-packages/bin:${PATH} export LD_LIBRARY_PATH${ASCEND_TOOLKIT_HOME}/lib64:${ASCEND_TOOLKIT_HOME}/lib64/plugin/opskernel:${ASCEND_TOOLKIT_HOME}/lib64/plugin/nnengine:${LD_LIBRARY_PATH} export PYTHONPATH${ASCEND_TOOLKIT_HOME}/python/site-packages:${ASCEND_TOOLKIT_HOME}/python/site-packages/topi:${ASCEND_TOOLKIT_HOME}/python/site-packages/te:${PYTHONPATH} export ASCEND_AICPU_PATH${ASCEND_TOOLKIT_HOME} export ASCEND_OPPER_PATH${ASCEND_TOOLKIT_HOME}/opp然后执行source /etc/profile.d/ascend.sh。验证是否装好最好用的命令是npu-smi info。如果能正常打印出卡的基本信息比如芯片型号、显存大小、驱动版本那就说明驱动层没问题。再执行python3 -c import acl如果没报错说明 ACL 的 Python 接口也装好了。3. 模型转换从 PyTorch 权重到 OM 模型3.1 YOLO 模型导出的关键细节Atlas 300V 24G 不能直接加载 PyTorch 的.pt权重它认识的格式是昇腾的 OMOffline Model格式。所以第一步是把 PyTorch 模型导出为 ONNX再用 ATCAscend Tensor Compiler工具转换成 OM。很多人在这里犯的错误是直接用 YOLOv5 官方仓库里的export.py导出结果转换 OM 的时候报一堆算子不支持。原因在于官方导出的 ONNX 里包含了大量的后处理算子比如 NMS这些算子不是昇腾原生支持的转换时非常容易卡住。我的建议是导出时把后处理去掉只保留模型的主干和检测头。我自己用的命令是这样的python3 export.py --weights yolov5s.pt --include onnx --opset 11 --dynamic然后手动把 ONNX 模型里后处理相关的输出层剪掉或者更省事的办法是直接改模型的 forward只返回预测特征图不返回 NMS 后的结果。如果你用的是 YOLOv8可以在model.predict里加上predictFalse直接拿到原始输出。3.2 ATC 工具转换与算子映射拿到干净的 ONNX 模型后就可以用 ATC 工具转换了。命令格式大致如下atc --modelyolov5s.onnx --framework5 --outputyolov5s_om --input_formatNCHW --soc_versionAscend310P3 --input_shapeimages:1,3,640,640注意--soc_version要填你的卡对应的芯片型号。Atlas 300V 24G 使用的是昇腾 310P 系列芯片具体是Ascend310P3别填成Ascend310或Ascend710否则转换过程会报“不匹配”的错误。转换过程中如果遇到不支持的算子日志里会明确打印出算子名。我遇到最多的是几种情况要么是某个自定义算子没有注册要么是 ONNX 中使用了一个昇腾尚未支持的版本。这时候的通用解决方案是修改导出的 ONNX 图把不支持的算子替换成等价的组合。比如GridSample在旧版本 CANN 上支持不好而 YOLOv5 的目标检测头里没有这玩意所以还好。如果跑了 YOLOv8-seg 或 YOLOv8-pose可能就会碰到更多问题。3.3 动态 Batch 与动态分辨率设置YOLO 部署中一个很常见的需求是动态推理比如同一路视频流中检测目标的 ROI 尺寸不固定或者要兼容多个输入分辨率。ATC 转换时支持动态形状但需要做一些配置。如果你需要动态 batch可以这样指定atc --modelyolov5s.onnx --framework5 --outputyolov5s_dynamic --input_formatNCHW --input_shapeimages:-1,3,640,640 --dynamic_batch_size1,2,4,8如果你需要动态分辨率可以这样atc --modelyolov5s.onnx --framework5 --outputyolov5s_dynamic --input_formatNCHW --input_shapeimages:1,3,-1,-1 --dynamic_image_size640,640;960,960;1280,1280但我要提醒一句动态形状会降低推理性能。昇腾内部在做算子编译时静态形状可以深度优化动态形状则需要缓存多种 shape 的版本推理时可能需要切换帧率会下降 10% 到 30%。我的建议是如果业务场景固定就老老实实转静态模型只有确实需要多分辨率输入时才转动态。我在实际项目里就直接固定成 640x640所有输入图像先做等比例缩放和填充省心又高效。4. 推理代码编写与性能调优4.1 使用 ACL Python API 加载 OM 模型老实用 C 写推理代码的人当然有但大多数人还是喜欢 Python。昇腾的 ACL Python API 其实很接近 PyTorch 的使用习惯初始化设备、加载模型、创建输出、执行推理几步就完成。下面是一段简化版的初始化代码import acl def init_device(device_id0): ret acl.init() assert ret 0, acl.init failed ret acl.rt.set_device(device_id) assert ret 0, acl.rt.set_device failed context, ret acl.rt.create_context(device_id) assert ret 0, acl.rt.create_context failed return context加载 OM 模型用acl.mdl.load_from_file输入和输出都用acl.mdl.create_desc描述然后申请设备内存。这里有个小坑ACL 的输入输出数据必须放在设备侧也就是要用acl.rt.malloc分配显存然后把 host 侧图像数据用acl.rt.memcpy拷贝到设备侧不能直接传一个 numpy 数组进去。我第一次写就忘了拷贝结果推理输出全是 0排查了好久才发现数据根本没到设备上。4.2 图像预处理与后处理要点YOLO 的标准预处理一般包括缩放、填充、归一化、通道转换。在昇腾上有一个优势就是 CANN 提供了一组图像预处理算子例如crop_and_resize、rgb_to_yuv等可以直接在设备上用 AIPPAI Preprocessing完成避免把图像数据在 CPU 和 GPU 之间搬来搬去。不过为了通用性我还是用 OpenCV 在 CPU 端做预处理然后把结果交给设备推理。预处理代码大致长这样import cv2 import numpy as np def preprocess(image, input_size(640, 640)): h, w image.shape[:2] scale min(input_size[0] / h, input_size[1] / w) new_h, new_w int(h * scale 0.5), int(w * scale 0.5) resized cv2.resize(image, (new_w, new_h)) canvas np.full((input_size[0], input_size[1], 3), 114, dtypenp.uint8) dx, dy (input_size[1] - new_w) // 2, (input_size[0] - new_h) // 2 canvas[dy:dy new_h, dx:dx new_w] resized blob canvas[:, :, ::-1].transpose(2, 0, 1).astype(np.float32) / 255.0 return np.ascontiguousarray(blob)后处理则需要注意OM 模型输出的是检测头的原始特征图一般有三个尺度的输出每个尺度对应不同大小的特征图。你需要根据输出形状解码出边框坐标、置信度和类别概率然后做 NMS。如果输出维度是[1, 255, 80, 80]之类的形状说明导出时没有合并到[1, 25200, 85]这种形式解码时要先把通道维度上的内容拆开。我后来直接写了一个解码器把三个尺度的输出 reshape 成[batch, anchors, 85]后拼接再用常规的 NMS 得到最终结果。这块逻辑不能说难但很容易在处理维度时搞混。4.3 实测性能数据与调优建议放一组我实际测试的数据环境就是上面列的那个输入分辨率 640x640batch size 1刚好是单路视频流最常用的配置模型耗时/帧折算FPS备注YOLOv5s1.41 ms709FP16静态 shapeYOLOv5m2.83 ms353FP16静态 shapeYOLOv8s2.05 ms487FP16静态 shapeYOLOv8m3.88 ms257FP16静态 shape其中 YOLOv5s 跑到 700 多 FPS其实已经逼近单张卡的算力上限了。如果换成多 batch比如 batch8单帧平均耗时反而会降到 1.2ms 以下因为算力利用率更高了。性能调优方面我强烈建议打开昇腾的图模式。也就是在推理前先用acl.mdl.create_execute_graph等接口做一次预热或者直接设置环境变量ASCEND_ENABLE_GRAPH_MODE1。生效后很多图优化会在会话启动时完成后续推理不用重复做算子调度肉眼可见地省了毫秒级时间。还有一点是关闭性能开销量大的日志输出把ASCEND_GLOBAL_LOG_LEVEL3只输出错误级别设上别让日志刷屏影响推理。5. 常见问题与排查实录5.1 驱动与固件版本不匹配导致初始化失败这个问题出现的频率极高。典型报错是[ERROR] acl init failed, error code: 507033507033 的含义是设备被占用或者固件版本错误。我当时排查一圈发现是之前装过一次旧驱动后来升级 CANN 时固件没跟着刷导致固件版本低于驱动要求。解决办法是重新安装一次配套的固件包我用的命令是./Ascend-hdk-*.run --upgrade --quiet如果还不行就在 BIOS 里把 PCIe 插槽的电管理设置改成“最大性能”避免卡因为进入低功耗状态导致初始化失败。5.2 模型转换时报不支持算子转换时报Unsupported op应该是所有昇腾新手最崩溃的时刻。这个问题的本质是 ONNX 里的某个算子不在当前 CANN 版本的昇腾算子列表中。遇到这种情况不要急着骂先检查三件事。第一确认 CANN 版本是不是最新的。昇腾每个版本都会新增算子支持升级 CANN 后很多问题会消失。第二检查 PyTorch 导出的算子版本。比如scatter_add在不同 opset 下的实现不一样你可以在导出时换一个 opset 试试。第三尝试用 ATC 的--enable_small_channel1或者其他优化参数。如果依然报错那就得人工改写模型了。我印象很深的是曾经有个模型的Slice算子因为steps参数中的负号无法解析导致转换失败。后来我把导出 ONNX 时torch.onnx.export的dynamic_axes去掉问题就解决了。所以模型转换时不要把动态轴和目标输入一锅炖复杂度越高出问题的概率越大。5.3 推理结果全零或框漂移如果你模型加载正常、推理正常但输出的检测结果是空的或者框的位置明显不对问题几乎可以肯定是图像预处理和模型输入要求不一致。我之前遇到过两次。第一次是图像通道顺序搞反了。YOLO 在 PyTorch 里默认是 RGB 输入而 OpenCV 读取的是 BGR如果忘了转回来模型输出的置信度会低到离谱。第二次是归一化方式不对。有些版本的 YOLOv5 导出到 ONNX 后模型内部自带归一化层输入只需要 0-255 的 uint8有些版本则需要你手动除以 255。判断方法很简单打印 ONNX 模型的第一个节点的输入如果输入是 float 类型且有可能超过 1就需要手动归一化如果模型内部有Div节点那就传原图。还有一点搞定之后最好用一张已知有结果的图像做单步验证把预处理后的图像存成文件人工看一下是不是真的按预期缩放和填充了。很多“框漂移”其实是填充时没有按比例缩放导致图像变形。5.4 多路视频流推理时显存泄漏如果你跑的是多路视频流长时间运行后显存占用会缓慢增长最后触发acl.rt.malloc失败。这不是卡的问题多是你推理流程中每帧都申请了内存但用完没有释放。ACL Python API 里每帧的输入和输出数据占用过多时一定要记得用acl.rt.free释放设备内存同时用acl.mdl.destroy_desc销毁描述符。我自己的习惯是每个线程内部预分配好输入输出缓冲区推理时反复用同一块显存而不是每帧都重新申请。这样改动之后我这边 16 路视频流连续跑了三天显存占用稳定在 7G 左右没有任何增长。6. 与 GPU 方案的对比和选型建议这一部分是我个人体验之外的横向对比。很多人问我有了 RTX 4090 还有必要用 Atlas 300V 24G 吗这实际上要看部署环境。先说价格和供货。现阶段在工业交付场景里显卡采购经常需要排队而且卡本身对电源和散热要求高。Atlas 300V 24G 作为推理卡整体功耗是低于同级别游戏卡的对服务器电源的冲击更小在长时间满负荷推理时更稳。另一个优势是生态完整性。昇腾提供了从驱动、CANN、MindSpore 到应用层的全套工具虽然早期文档不够友好但现在已经很成熟了。再说生态劣势。目前网上关于昇腾的教程数量仍然远远不及 GPU遇到问题时能搜到的现成答案比较少。如果你是一个人或小团队且项目周期很紧老老实实用 GPU 可能更省事。但如果你有充足的时间做前期迁移或者部署节点多达几十上百台追求更低的整体功耗和更可控的采购成本那么 Atlas 300V 24G 是一个值得认真考虑的方案。我自己的判断是不要用“能不能跑 YOLO”来评价这张卡而是要看“能不能稳定、长期、低成本地跑 YOLO”。在这个维度上它的表现相当让人满意。7. 后续还可以怎么扩展这次部署 YOLOv5 只是开始。YOLO 系列更新很快我后来也顺带试了 YOLOv8s效果不错只是在导 ONNX 时需要多注意一下后处理接口的变化。如果你有目标检测之外的视觉需求Atlas 300V 24G 也能跑语义分割、关键点检测、OCR 之类的模型原理都一样核心难点还是模型转换和算子适配。另一个值得考虑的方向是用昇腾的推理框架和流媒体服务结合搭一个统一的视频分析网关。这样可以在一个服务器里同时处理多路视频流支持动态加载不同模型。我在实验室里已经搭出了一个原型后续还想把预处理也挪到设备侧进一步降低 CPU 开销。最后说句实在话Atlas 300V 24G 的学习曲线确实比普通显卡陡一些尤其是 CANN 的环境配置和 OM 模型的转换逻辑需要一点耐心去啃文档。但一旦把这条链路跑通后面再部署新模型就是重复劳动了。我个人的经验是第一周全是坑第二周开始顺畅到第三周就能随手写部署脚本了。希望这篇文章能帮你把第一周的时间压缩到两天以内。
阅读完成 · 觉得有帮助?
咨询建站