ARTICLE DETAIL

资讯详情

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

Atlas 300V 24G推理卡部署YOLO:从ONNX到OM完整实战

Atlas 300V 24G推理卡部署YOLO:从ONNX到OM完整实战 1. 先搞明白Atlas 300V 24G 到底是什么卡1.1 一张推理卡别拿它干训练的活先说结论Atlas 300VPro24G 是一张专为推理场景设计的 AI 加速卡。很多人一看 24G 显存第一反应是“这不就是一张大显存显卡吗能训练吗”——不仅新手会这么问有些做算法的同事第一次拿到板卡也会下意识地去跑训练脚本然后被坑得一头包。从定位上看华为昇腾体系里的 Atlas 300 系列是标准的推理卡它和训练卡是两条产品线。训练卡一般叫 Atlas 800/900 训练节点或者昇腾 910 这类高性能芯片而 Atlas 300V Pro 用的是昇腾 310P 芯片主打的就是高能效比、低功耗、大并发推理。最大功耗大概 72W 左右和一张 RTX 4090 动辄 450W 的功耗完全不是一个量级。换句话说这张卡的设计初衷是“让边缘设备、视频分析服务器等场景跑得起模型推理”而不是“帮你从零开始训练一个大模型”。那你可能会问24G 显存这么大不训练是不是浪费了并不浪费。推理阶段的大显存通常意味着两件事一是能塞下更大的模型比如 YOLOv8 的 x 版本、一些轻量化的 transformer 模型二是能支撑更高的并发路数。很多视频分析项目里一张卡要同时处理 8 路、16 路甚至 32 路视频流每路跑一个检测模型显存不够根本撑不住。所以 Atlas 300V Pro 的 24G 是为了“多路并发 大模型”服务的不是给你当训练显存用的。1.2 24G 显存和 140 TOPS 算力什么水平官方参数里Atlas 300V Pro 的 INT8 稠密算力大约是 140 TOPS24GB LPDDR4X 显存带宽大约 204.8GB/s。单独看数字可能没概念放实际场景里感受一下跑 YOLOv5s 或者 YOLOv8s 这种轻量级检测模型单路视频流 1080p 输入处理一帧大概在 5ms 到 15ms 之间轻松跑满 60FPS 以上如果拿来做批量图片检测配合昇腾的推理引擎能压出很恐怖的吞吐量。算力这块140 TOPS 是 INT8 精度下的理论峰值。实际上跑模型的时候很多算子不一定能跑满再加上数据搬运、后处理这些环节实际吞吐量大概能到理论值的三成到六成。不同模型差异很大卷积占比高的模型跑得更好而如果模型里有大量小算子、频繁的 reshape 和 concat昇腾处理器反而不太擅长。这一点后面讲模型转换的时候还会提到。插一嘴电源和卡型的事。Atlas 300V Pro 是无主动散热或被动散热的卡安装的时候要注意机箱风道尤其是放在多卡服务器里散热设计不好很容易导致降频。之前我在一台工作站里塞了两张卡结果第二张卡的 PCIe 位置正好卡在电源风道旁温度直接飙到 80 多度推理延迟也上去了后来重新规划了风向才恢复正常。部署物理设备这种事情真的不是插上就能用的。1.3 和常见 GPU 对比你该怎么选很多人手里可能已经有 NVIDIA 显卡比如 3080、4080、4090或者 Tesla T4、L4 之类的推理卡。选型的时候到底上 Atls 还是继续用 GPU主要看几个维度对比项Atlas 300V Pro 24GNVIDIA RTX 3080NVIDIA Tesla T4定位专用推理卡消费级 GPU数据中心推理卡显存24GB LPDDR4X10GB/12GB GDDR6X16GB GDDR6INT8 算力约 140 TOPS约 58 TOPS稀疏接近翻倍约 65 TOPS稀疏约 130功耗约 72W约 320W约 70W模型生态需要转成 OM 格式PyTorch/TensorRT 直接跑TensorRT 生态典型价格区间数千元存量盘源常更低二手市场数千到上万上万到几万不等平平无奇一张表但背后信息量很大。如果你是做 POI 级别的推理项目比如园区安防、工业质检、智慧零售这类要把几十路视频同时处理功耗和单卡并发是关键那 Atlas 300V Pro 性价比非常明显。如果只是研究阶段用 PyTorch 改模型、调网络结构还是老老实实用 NVIDIA GPU 更方便因为调试链路短社区资料也多。我的建议是确认项目交付形态后再选卡。如果项目要求国产化、或者现场只允许使用低功耗卡再考虑 Atlas如果只是算法验证那就别折腾昇腾了用 NVIDIA 卡快速跑通逻辑再说。2. 部署 YOLO 之前的准备工作CANN 工具链2.1 驱动、固件与 CANN Toolkit 的关系拿到 Atlas 300V Pro 之后第一件事并不是急着装驱动而是先把昇腾的软件栈理解清楚。很多人卡在第一周就是因为搞不清“驱动”“固件”“CANN Toolkit”“CANN 算子包”这几个东西的关系。简单类比一下驱动就是操作系统认得这张卡的最基本条件没有驱动设备都枚举不出来固件是板卡内部底层系统负责芯片初始化、内存管理这些一般和驱动配套发布CANN Toolkit 是昇腾的计算平台相当于 CUDA toolkit 的角色里面包含运行时、编译器、图引擎等核心组件。另外有个叫“CANN 算子包”的东西它包含已经编译好的算子实现可以理解为 cuDNN 一样的存在。后面的模型转换工具 ATC 也集成在 CANN 里。所以正确的安装顺序是先装固件 驱动然后装 CANN Toolkit最后根据需要装算子包。不同版本的 CANN 对应不同版本的驱动和固件官方发布了一个兼容性列表安装前一定要去查。我见过不少人把 CANN 5.1 的包配到驱动 23.0 的机器上然后报一堆奇奇怪怪的算子执行错误最后排查半天发现是版本对不上。安装命令通常是 .run 可执行文件官方文档推荐用默认路径安装比如/usr/local/Ascend。装完之后可以执行npu-smi info查看板卡状态这个命令和 NVIDIA 的nvidia-smi用法差不多。2.2 开发环境与运行环境的区别昇腾的软件栈分得很细少了容易让人头大这里我用大家更熟悉的概念来解释。开发环境就是你用来做模型转换、写推理代码、编译程序的环境。它需要完整安装 CANN Toolkit并且一般建议和板卡在同一台机器上因为 ATC 转换工具在转换某些带动态 shape 的模型时可能需要上板做算子调优。运行环境就是最终跑推理任务的环境。它只需要 CANN 的运行时部分不需要装 ATC 编译器。如果你交付的是一个边缘盒子盒子上只需要运行时相关组件就够了开发环境的组件可以不装减少体积和潜在冲突。实际项目里我通常在一台开发机上完成“模型导出 - 转换 - 精度测试”再把 OM 模型文件和推理程序部署到目标机器上。目标机器是另外一张卡驱动、固件装上CANN 的 runtime 装好就能直接跑开发工具链可以不装。这样一套流程既省事又干净不会出现“开发机好好的目标机起不来”的奇怪问题。2.3 系统依赖与内核配置Atlas 300V Pro 官方支持的操作系统主要是 Ubuntu、CentOS、EulerOS 这类 Linux 发行版。我用得比较多的是 Ubuntu 20.04 和 22.04。安装前要确认内核版本和驱动要求是否匹配重点检查这几项Linux 内核版本大部分情况下 4.18 到 5.15 之间都还行用uname -r查看。GCC 版本编译 CANN 样例时编译器版本过新或过旧都可能报错。官方推荐的 GCC 版本一般会在驱动包说明里写。如果报Unknown option之类的编译错误多半是 GCC 版本太新建议用 7.5 或 9.4。内存如果打算跑 YOLOv8x 这种大模型至少保证系统内存 32G 以上。推理过程中模型转换和内存申请都比较占空间。还有个大坑BIOS 层面的。某些主板默认开启了 IOMMU或者设置了错误的 PCIe ACS 策略导致板卡枚举不稳定。现象就是npu-smi info时而能看到卡时而看不到或者驱动加载报npu reset failed。如果遇到可以在 BIOS 里把 IOMMU 设置为关闭或者把 ACS 设置为禁用。这个坑在配套的国产主板上更多见折腾得我一度想把机器砸了后来发现是主板的 PCIe 拓扑兼容性问题。装卡之前最好先确认主板对非 NVIDIA 设备的支持情况。3. 核心环节YOLO 模型从 PyTorch 到 OM 的转换3.1 导出 ONNX 的正确姿势说实话Atlas 上跑 YOLO 的流程最核心的一步不是写推理代码而是把 PyTorch 训练好的模型转换成昇腾能认识的 OM 格式。整个链路是PyTorch 权重 - ONNX - OM。第一步导出 ONNX就有不少讲究。YOLO 系列的网络结构里detect 头通常包含一些动态算子比如某些模型版本在 forward 时用了 Python 层的循环或者动态 shape。直接导出 ONNX 很容易导出成带一堆小算子的笨重结构或者干脆导出失败。我一般在导出前做的处理是把模型切成 backbone neck head 三部分只导出前两部分用来做特征提取后处理检测头的逻辑留在推理代码里用 numpy 实现。固定输入尺寸。推理场景下YOLO 模型最稳定的方式就是固定输入尺寸比如 640x640 或 1280x1280。动态输入尺寸虽然 CANN 也支持一部分但性能和兼容性都会打折。导出时设置opset_version11这个版本在昇腾上的算子覆盖面最广太新或太旧都可能出现算子不支持。cmd 命令大概是这样的python export.py --weights yolov8s.pt --include onnx --opset 11 --batch-size 1导出后检查一下 ONNX 模型信息确认输入输出节点的维度符合预期import onnx model onnx.load(yolov8s.onnx) onnx.checker.check_model(model) print(model.graph.input) print(model.graph.output)3.2 ATC 模型转换与算子上板拿到 ONNX 之后接下来用 ATC 工具转换成 OM。ATC 的完整命令很长但核心参数就那些我放一个实际用过的转换命令样例atc --modelyolov8s.onnx \ --framework5 \ --outputyolov8s_bs1 \ --input_shapeimages:1,3,640,640 \ --soc_versionAscend310P3 \ --insert_op_confaipp.cfg \ --output_typeFP16 \ --logerror解释几个关键参数--framework5固定写法表示输入模型格式是 ONNX。--soc_versionAscend310P3芯片型号。Atlas 300V Pro 对应的是 Ascend310P3不确定的时候用npu-smi info能看到具体的芯片型号。这个参数填错转换出来的模型根本跑不起来。--insert_op_confaipp.cfgAIPP 配置文件可以在硬件上直接完成图像的缩放、减均值、除以标准差、RGB 转换等预处理相当于把预处理也压进模型里。推理速度会快不少。AIPP 的完整配置我也放一下这是一个包含色域转换和尺寸裁剪的通用配置。--output_typeFP16模型输出数据以 FP16 格式计算。YOLO 这种检测模型对精度不敏感FP16 基本无损但速度会有明显提升。aipp.cfg 大致长这样aipp_op { aipp_mode: static input_format: RGB888_U8 src_image_size_w: 640 src_image_size_h: 640 csc_switch: true rbuv_swap_switch: false matrix_r0c0: 0.299 matrix_r0c1: 0.587 matrix_r0c2: 0.114 matrix_r1c0: -0.169 ... }每家模型用的均值方差不一样要根据你自己的 YOLO 版本配置。比如官方 YOLOv5 的 normalize 参数是0.003921也就是 1/255有的 YOLOv8 也有自己的配置。没有 AIPP 的话就得在代码里自行预处理也可以跑只是张卡没有把预处理优化到极致吞吐会受点影响。转换成功后会生成yolov8s_bs1.om文件这个文件才是最后部署到推理环境的核心产物。到这一步你已经成功了一半。3.3 精度校验与模型落盘模型转换完最忌讳的事情是“转换成功就直接上线”。OM 模型和原 PyTorch 模型的数值在算子层面会有些微小差异尤其是使用 FP16 或 AIPP 混合处理之后可能出现检测框偏移、置信度下降等问题。我习惯的做法是准备一组固定的测试图片分别用 PyTorch 原始模型和 OM 模型跑一遍对比检测结果。取同一张图先跑 PyTorch 模型记录检测框坐标、分类和置信度。再用 AscendCL 或 MindX SDK 跑 OM 模型得到同样输出。对比时重点关注目标数不一致、置信度下降超过 0.1、目标框 IoU 低于 0.5 的情况。如果精度有问题排查顺序是先关 AIPP改成直接输入归一化后的数据看问题是否消失再切换成 FP32 输出看是不是精度问题最后再针对性查看出现差异的算子。我在实际项目里遇到过Sigmoid和Exp算子在 FP16 模式下精度损失较大导致置信度掉得厉害。解决办法是在 ATC 命令里针对特定算子使用混合精度设置某些算子跑 FP32。具体做法是用算子调优工具或者手动指定算子精度这个比较进阶一般遇到再学也来得及。精度校验通过之后OM 模型连同推理代码、配置文件一起打个包放到部署环境。到这里模型准备工作才算彻底结束。4. 推理代码实战AscendCL 跑通 YOLO4.1 申请资源与数据传输写推理代码时可以用 MindX SDK 的 Python 接口也可以用底层的 AscendCL 接口。前者封装度高代码量小后者更灵活适合有特殊需求的项目。我个人更推荐刚开始接触 Atlas 的人用 AscendCL因为你能更清楚地看到显存申请、数据拷贝、模型加载这些细节出问题也好排查。先看初始化与资源申请的代码import acl ret acl.init() ret acl.rt.set_device(0) # 选择第 0 张卡 context, ret acl.rt.create_context(0) # 申请 Host 端内存 image_data np.fromfile(test.jpg, dtypenp.uint8) host_ptr acl.util.np_to_ptr(image_data) # 申请 Device 端内存 dev_ptr, ret acl.rt.malloc(size, acl.const.MEM_MALLOC_NORMAL_ONLY) ret acl.rt.memcpy(dev_ptr, size, host_ptr, size, acl.const.MEMCPY_HOST_TO_DEVICE)这块和 CUDA 的cudaMalloccudaMemcpy非常像有 CUDA 经验的人上手会很快。要注意的是昇腾的显存管理比 NVIDIA 更“抠”申请完的内存一定要及时释放否则稍长时间运行就会出现out of memory。4.2 模型加载与推理模型加载和推理的接口我自己封装了一个类核心思路是这样的model_id acl.mdl.load_from_file(yolov8s_bs1.om) desc acl.mdl.create_desc() acl.mdl.get_desc(desc, model_id) # 获取模型输入输出的维度和 buffer 大小 input_size acl.mdl.get_input_size_by_index(desc, 0) output_size acl.mdl.get_output_size_by_index(desc, 0) # 申请 device 内存 input_ptr acl.rt.malloc(input_size, ...) output_ptr acl.rt.malloc(output_size, ...)推理调用就一行ret acl.mdl.execute(model_id, input_ptr, input_size, output_ptr, output_size)但是注意acl.mdl.execute是异步的还是同步的取决于是否设置了 stream。一般简单场景用默认 stream调用后需要acl.rt.synchronize_stream等待完成。异步推理是提升吞吐的关键尤其是多路视频流同时推理时建议每条流建一个独立 stream把图片数据拷入 device 后不同 stream 可以并行推理。4.3 后处理从输出张量到检测框Atlas 上的 YOLO 模型输出分为两种一种是你在导出 ONNX 时就把解码逻辑放进了网络结构里输出直接是坐标、置信度另一种是只输出原始特征图比如 1x84x8400后处理全在代码里做。第二种在部署上更通用但代码要注意对齐 YOLO 的输出格式。以 YOLOv8s 为例如果导出时不动头输出 shape 是[1,84,8400]意思是 84 4坐标 80类别8400 是三个尺度下的 anchor 总数。后处理的核心逻辑是把输出转成[1,8400,84]去掉置信度低于阈值比如 0.25的候选框。用xywh到xyxy的转换得到标准框坐标。对剩余框做 NMS去掉重叠严重的框。这块代码动手写的时候一定要非常小心坐标系的定义。YOLOv5 和 YOLOv8 的坐标定义略有差异输入分辨率变了缩放系数也要跟着变。我见过不少人把 960x960 图片的坐标用 640x640 模型输出的缩放去映射结果所有检测框位置都偏到姥姥家去了。4.4 性能调优从 30FPS 到 60FPS如果第一版推理代码能跑通但帧率老是上不去可以按这几个方向优化第一把图像缩放、格式转换尽量放到 AIPP 里做不要用 Python 端去 resize。AIPP 用硬件完成几乎不占 CPU。第二使用批量推理。如果业务场景允许把多张图拼成一个 batch。ASCEND 的 batch 推理比单张推理性能提升明显。第三开启 stream 并发。至少保证memcpy Host-Device、execute和memcpy Device-Host三个操作分别在不同的 stream 上避免互相等待。第四用profiler工具看每个算子的耗时。在 CANN 包里有msprof命令能导出推理过程的算子级时间。如果发现某个算子耗时特别长可以回到模型转换环节调整融合策略或精度。我实际调过的一个项目早期在 Atlas 300V Pro 上跑 YOLOv8s10 路 1080p 视频流大约 35FPS 总吞吐经过 AIPP 预处理、滚动 batch、异步推理之后稳定跑到了 60FPS 以上。那块的收益远比自己改模型结构大得多。5. 常见问题与排查经验实录5.1 算子不支持、降级失败的坑昇腾对算子的支持是有边界的。虽然 CANN 不断扩充算子库但遇到一个从来没见过的复杂算子还是很痛苦。我在转换 YOLOv7 的时候就遇到过模型里有几个带自定义 CUDA 算子的重参数化模块ATC 转换直接报Unsupported opxxx。处理方式有两个一是找替代方案把自定义算子在 PyTorch 里改成多个标准算子组合二是把该模块放到 CPU 上计算只在 Atlas 上跑卷积部分。后者的代价是多一次 Host-Device 数据拷贝性能偶尔不划算但某些网络只能这么干。降级失败的问题也比较常见。ATC 转换时报Auto schedule failed通常是因为输入 shape 太大、在芯片上找不到合适的 tiling 方案。把输入尺寸从 1280 改成 640往往就能解决。所以你需要先牢记不是越大越好Atlas 是嵌入式芯片架构它有自己的算力节奏要学会顺着它的性格来。5.2 显存不足与内存泄漏运行一段时间后提示显存不足这个是推理场景最高频的故障了。第一次遇到的时候我也很懵明明 24G 显存按模型大小来算绰绰有余怎么会不够排查步骤用npu-smi info查看当前显存占用确认是哪个进程占用高。检查代码里每个acl.rt.malloc是否有对应的释放。检查数据拷贝的缓存是否释放。比如说在循环里反复执行acl.util.np_to_ptr和acl.rt.memcpy之前申请的指针如果没释放每帧都会泄漏一点显存十几分钟就把 24G 撑爆。另外模型加载后不要释放 desc 和 model_id否则下次推理会重新加载模型显存碎片化越来越严重。5.3 版本兼容性最常见且最难排查的问题昇腾生态的版本习惯和 NVIDIA 差别很大。NVIDIA 的 CUDA 和驱动版本相对宽容但昇腾的 CANN、驱动、固件版本强绑定一个对不上可能一开始没问题跑到某个算子就崩。我做过的项目里CANN 5.1.RC2 和 6.0.RC1 之间的算子行为就有差异。所以版本升级前建议先在测试环境把转换流程和推理流程全部跑一遍再上线。“转换能用、推理报错”的多数情况都是驱动和 CANN 不匹配。检查版本统一用npu-smi info /usr/local/Ascend/ascend-toolkit/latest/version.cfg把这两处信息拍下来无论是查文档还是找人求助都能大幅减少沟通成本。5.4 高频问题速查表现象原因解决办法npu-smi info看不到卡驱动未装好、PCIe 枚举失败、BIOS 设置重装驱动关闭 IOMMU检查供电ATC 转换报算子不支持模型算子超出版本范围修改网络结构或升级 CANN推理输出全为 0AIPP 参数配错、输入数据未正确拷入校准预处理检查 input 类型运行一段时间 OOM内存泄漏或未释放 buffer逐帧排查 malloc 和 free推理速度很慢未开 stream、未用 AIPP、输入 shape 过大开启并行流用硬件预处理精度对不上FP16 精度损失、AIPP 均值方差错误改用 FP32 或混合精度检查配置6. 写在最后关于 Atlas 部署的几句大实话在 Atlas 300V Pro 24G 上部署 YOLO 这件事说难不算特别难但说简单也绝不像装个显卡驱动那么轻松。整个过程最大的感受是昇腾的生态在快速变好但还没到像 NVIDIA 那样“开箱即用”的程度。算子兼容性、版本强绑定、工具链的细节都需要你花时间慢慢摸清楚。我个人的建议是入门时不要一上来就搞 YOLOv8x 这种大模型先用 YOLOv5s 把整条链路跑通从模型导出到 ATC 转换到推理代码任何一个环节出问题都能快速定位。链路稳定之后再逐步加大模型和并发路数。这个过程踩坑积累的经验比任何教程都值钱。最后再分享一个小技巧模型转换命令、AIPP 配置、推理代码版本一定要全部纳入 git 管理。昇腾相关的配置项太多了今天能用、下周可能因为某个参数改动就崩。我一开始用文档记录后来发现根本记不过来全部写进仓库配置里之后环境恢复和问题回滚都快了很多。这是好几个项目的血泪教训算是给准备入坑 Atlas 的同学提个醒。
返回列表