ARTICLE DETAIL

资讯详情

深耕网站建设、视觉设计与SEO优化的一线实战洞察。

Atlas 300V 24G推理加速卡上部署YOLOv5:从驱动到om模型转换全流程实战

Atlas 300V 24G推理加速卡上部署YOLOv5:从驱动到om模型转换全流程实战 Atlas 这个词在 AI 推理圈子里现在越来越常听见。尤其是最近好几个人跑来问我“Atlas 300V 24G 是运算加速卡吗”、“有人用 Atlas 部署 YOLO到底怎么搞”我恰好在半个月前为一个视频结构化项目干了件事——在一台插着 Atlas 300V 24G 的服务器上把 YOLOv5 检测流程完整跑通从最开始连驱动都装不对到最终 16 路视频流同时推理稳定运行中间踩的坑比写业务代码多得多。今天这篇我打算把整个路线讲透先帮你看清 Atlas 300V 24G 的真实身份不绕弯子再讲清楚部署 YOLO 的完整链路从驱动安装、模型转换到推理代码最后把我实际踩过的几个大坑一字不落列出来希望能帮你少走几天弯路。1. 先别急着写代码把 Atlas 300V 24G 的真实身份搞清楚1.1 从型号名拆解这块卡Atlas 是昇腾产品线里的一个系列名主要覆盖训练卡、推理卡和边缘智能小站。你看到的“Atlas 300V 24G”拆开来说Atlas 300 是板卡系列300V 中的 V 一般对应视频分析方向24G 则是板载内存容量也就是 24GB。它用的芯片是昇腾 310P这块芯片本身是面向推理场景设计的不是用来做训练的。很多第一次接触的人看它是一块 PCIe 接口的卡又插在服务器里下意识就把它当成“显卡”了。这个理解方向对一半但容易误导后面所有的技术决策。Atlas 300V 24G 的核心定位是“AI 推理加速卡”它加速的对象是卷积、矩阵乘、激活函数这些神经网络里的算子而不是通用并行计算或者图形渲染。换句话说你可以很舒服地拿它跑 YOLO、ResNet、OCR、人脸检测这类推理任务但你别指望它能跑 CUDA 通用计算更不能拿来打游戏。1.2 那它到底算不算“运算加速卡”直接给结论算而且是一张非常典型的专用运算加速卡。你问“Atlas 300V 24G 是运算加速卡吗”如果是拿它和 CPU 比它当然是加速卡而且比 CPU 做神经网络推理快得多如果是拿它和 NVIDIA 的普通显卡比它也算加速卡只是加速的领域更专一。我在实际项目中把一张 YOLOv5s 模型分别跑在 CPU 和 Atlas 300V 24G 上同样处理 640x640 的输入CPU 单张要 200 毫秒以上Atlas 大概能跑到 20 毫秒以内具体帧率受功耗和频率策略影响会有波动。这种差距本质上来自架构不同昇腾 310P 内部把大量计算单元编排成了适合张量运算的专用流水线配合高带宽内存让数据搬运和矩阵计算尽量重叠所以做推理时效率非常高。但你要特别记住一个边界它不像 GPU 那样有 CUDA 这种通用编程模型你想随便写一段并行逻辑扔上去跑是不现实的。它只能执行经过昇腾工具链编译好的神经网络模型也就是后面要讲的 om 格式。这个特点决定了我们在部署 YOLO 时必然要走一条和 GPU 不太一样的路。1.3 和 NVIDIA GPU 最大的差异在生态差异不只在硬件参数表上更在“习惯”上。在 NVIDIA 生态里你习惯了 pip install torch然后.cuda()一把梭在 Atlas 上这一套完全不成立。PyTorch 不能直接调用昇腾芯片必须通过 CANN昇腾计算架构 里的适配层或者先把模型导出成 ONNX再用 ATC 工具转成 om 格式最后用昇腾的推理接口去加载和执行。我打个比方如果说 NVIDIA 生态像一间标准化的酒店你拎包入住就行那 Atlas 更像一套全屋定制的房子效果可以做得很好但设计、施工、软装都得按它的规则来。正因为这样很多人拿到 Atlas 300V 24G 后第一反应是“这卡到底能不能用”第二反应是“部署 YOLO 怎么这么绕”。答案是能且绕得有道理——后面我详细解释。2. YOLO 部署的整体思路为什么必须经过模型转换2.1 推理的本质把计算图编译成芯片指令要理解 Atlas 部署 YOLO得先退一步看神经网络推理的本质。一个训练好的 YOLO 模型本质上是一张计算图卷积、池化、上采样、拼接、激活函数按顺序连在一起。在 GPU 上PyTorch 或 TensorRT 会把这套图里的每一个算子映射到 CUDA 核心上执行因为 CUDA 核心是通用的所以可以比较灵活地处理各种算子。昇腾芯片的设计思路不一样。它内部有专门用于矩阵运算的 Cube 单元、用于标量运算的 Vector 单元还有专门管理数据搬运的缓存体系。为了让这些专用单元高效协作模型必须预先编译成一种“离线指令序列”也就是 om 文件。这一步就是 ATCAscend Tensor Compiler做的事情。你可以把它理解成GPU 是“边解释边执行”的脚本语言昇腾更像“提前编译好”的可执行文件。所以onxx、PyTorch 模型不能直接跑必须经过转换。2.2 Atlas 部署的关键名词部署过程中你会反复看到这几个名词我这里一次性讲清楚CANN昇腾计算架构可以理解成一套完整的软件栈包括算子库、图编译引擎、运行时、应用开发接口作用类似于 CUDA 加 cuDNN 的组合。ATC模型转换工具负责把 ONNX、TensorFlow、Caffe 等格式的模型转换成昇腾的离线模型 om。om离线模型昇腾芯片能直接加载执行的模型格式。AscendCL昇腾计算语言是写推理应用时直接调用的 API有 C 和 Python 版本。msame官方提供的简易推理工具可以用几行命令加载 om 模型对指定输入做推理适合快速验证。npu-smi类似 NVIDIA 的 nvidia-smi用来查看芯片状态、内存占用、温度、算力利用率。很多教程一上来就让你敲命令导致你根本不知道自己在干什么。其实你只需要抓住主线训练好的 YOLO 权重 - 转成 ONNX - ATC 转 om - 用 AscendCL 或 msame 加载执行。所有环节都是围绕这条主线展开的。2.3 整体流程全景图我先给一个完整的部署流程让大家心里有数。后面每一节都会对应其中的一部分。在服务器上装好操作系统内核版本尽量选昇腾官方支持列表里的版本。安装昇腾驱动和固件并确认 npu-smi info 能看到设备。安装 CANN 工具包配置环境变量。准备 YOLOv5 的权重文件用官方 export.py 导出 ONNX。编写 AIPP 配置文件可选用于预处理调用 ATC 把 ONNX 转成 om。用 msame 先快速验证 om 能不能正常输出。写正式的推理代码接入业务处理后端 NMS 和逻辑。联调性能设置 batch、多路流等参数压测。我在实操中发现大部分人的问题都出在第 1 步到第 3 步也就是环境搭建。这些环境问题看起来琐碎但只要有一处版本不匹配后面所有步骤都会连环报错。所以我建议你拿出耐心把环境准备好再往下走。3. 实操记录在 Atlas 300V 24G 上把 YOLOv5 跑起来3.1 环境准备驱动、固件、CANN 安装的关键细节先说硬件部署。Atlas 300V 24G 是一张标准 PCIe 接口卡我是在一台双路 x86 服务器上插的系统用的 Ubuntu 20.04内核版本 5.4。这里有个很容易踩的坑昇腾官方对内核版本有兼容性要求太新或者太旧的内核驱动编译或加载都可能出问题。如果你不是非要用最新内核不可建议直接用官方文档推荐的操作系统版本省掉一堆麻烦。软件安装顺序是固定的先装驱动再装固件最后装 CANN。昇腾社区通常会把驱动和固件打包发布叫 Ascend HDK你下载对应型号的包后按官方指引执行安装脚本即可。安装完成后立刻执行npu-smi info如果能看到类似下表的信息说明驱动和固件基本正常设备编号 Device ID芯片型号昇腾 310P显存24G温度、功耗、算力利用率如果这一步报错先别继续下一步。最常见的原因要么是驱动安装时缺内核头文件要么是驱动和固件版本对不上。我在第一次安装时就遇到后者驱动是新版固件却是上个版本导致 npu-smi info 能看到卡但一跑样例就报设备打开失败。最终的解决办法是下载配套的驱动固件整包一起重新安装。CANN 的安装相对简单通常是下载 .run 包然后执行安装脚本。装完之后一定不要忘记 source 环境变量脚本一般在安装目录下source /usr/local/Ascend/ascend-toolkit/set_env.sh这一步很多新手会忘结果执行 atc 或运行程序时报“找不到 libascendcl.so”之类的错误。另外提醒一句如果你机器上装了多个版本的 CANN环境变量极其容易混乱。我的习惯是一个项目固定一个 CANN 版本每次开终端都重新 source 对应版本的 set_env.sh。3.2 从 YOLOv5 权重导出 ONNX 模型环境就绪后开始处理模型。YOLOv5 官方仓库自带export.py导出 ONNX 的命令大致是python export.py --weights yolov5s.pt --include onnx --opset 12 --img 640 --batch 1有几个细节值得注意。第一opset 版本尽量选 11 以上因为太低的话一些算子比如上采样、Slice在 ATC 转换时容易出幺蛾子第二--batch 1可以先固定 batch后期如果要做多 batch 推理再单独处理动态 shape第三输入尺寸如果不确定就先固定成 640x640这是 YOLOv5 的默认训练尺寸定位最简单。导出完成后会得到一个yolov5s.onnx文件。我建议先用 Netron 之类的工具打开看一眼确认输入节点名称一般是 images和输出节点个数。YOLOv5 有三个输出分别对应三种尺度的检测头。记下这些节点的名字和 shape后面 ATC 配置和推理代码里面都要用到。3.3 ATC 模型转换从 ONNX 到 om 的关键命令有了 ONNX 文件核心一步就是用 ATC 把它转换成 om。这里给出我实际用过的命令模板atc --modelyolov5s.onnx \ --framework5 \ --outputyolov5s \ --input_shapeimages:1,3,640,640 \ --soc_versionAscend310P3 \ --insert_op_confaipp.cfg参数解释一下--framework55 表示 ONNX 格式。--output输出 om 文件的名称。--input_shape指定输入形状这里要和导出 ONNX 时一致。--soc_version按实际芯片型号填写。Atlas 300V 24G 用的昇腾 310P 系列所以填 Ascend310P3。--insert_op_conf插入 AIPP 预处理配置可选我建议第一次调试先不加后面再按需加上。如果你不加 AIPP就意味着所有预处理resize、归一化、颜色转换都要在你的应用代码里自己完成然后把处理后的 float32 数据直接丢给模型。这样做的好处是逻辑清晰、容易排查问题坏处是主机端 CPU 要承担一部分预处理计算。对于第一次部署我强烈建议“先不加 AIPP跑通再说”。如果转换过程中报算子不支持、算子融合失败之类的错误不要慌后面第 4 节我会详细讲排查思路。总之看到类似 “ATC run success” 的日志就说明 om 生成成功了。3.4 用 msame 快速验证 om 模型om 生成后先用官方 msame 工具做一次“冒烟测试”确认模型能否正确推理。准备一个输入 bin 文件这里可以用 Python 把一张图片预处理后存成二进制import cv2 import numpy as np img cv2.imread(test.jpg) img cv2.resize(img, (640, 640)) img img[:, :, ::-1] # BGR - RGB img img.astype(np.float32) / 255.0 img np.transpose(img, (2, 0, 1)) # HWC - CHW img np.expand_dims(img, 0).copy() img.tofile(test.bin)然后执行推理msame --modelyolov5s.om --inputtest.bin --outputoutmsame 会在 out 目录下生成推理输出文件。如果你的模型包含完整的检测头输出通常是一个数组——注意这时还没做 NMS只是网络的原始输出。从 msame 能成功把整个流程跑通说明 om 模型本身没有问题后面写业务代码时心里就有底了。3.5 正式推理代码AscendCL Python 接口的使用要点实际项目里不可能每次都调 msame 命令所以要用 AscendCL 写正式推理代码。我这里给一个最小可用的 Python 示例骨架import acl import numpy as np def init(device_id0): acl.init() acl.rt.set_device(device_id) context acl.rt.create_context(device_id) return context def load_model(om_path): model_id acl.mdl.load_from_file(om_path) return model_id def inference(model_id, input_data): # 根据模型描述获取输入输出大小 desc acl.mdl.create_desc() acl.mdl.get_desc(desc, model_id) 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, acl.const.MEM_MALLOC_NORMAL_ONLY) output_ptr acl.rt.malloc(output_size, acl.const.MEM_MALLOC_NORMAL_ONLY) # 数据拷贝到 device acl.rt.memcpy(input_ptr, input_size, input_data.tobytes(), input_size, acl.const.MEMCPY_HOST_TO_DEVICE) # 执行模型 acl.mdl.execute(model_id, [input_ptr], [input_size], [output_ptr], [output_size]) # 把结果拷回 host out np.zeros(output_size, dtypenp.uint8) acl.rt.memcpy(out.tobytes(), output_size, output_ptr, output_size, acl.const.MEMCPY_DEVICE_TO_HOST) acl.rt.free(input_ptr) acl.rt.free(output_ptr) return out if __name__ __main__: context init(0) model_id load_model(yolov5s.om) # 构造输入数据 img np.fromfile(test.bin, dtypenp.float32).reshape(1, 3, 640, 640) result inference(model_id, img) print(inference done, output shape bytes:, len(result))这段逻辑比较简略但把 AscendCL 的核心流程全串起来了初始化、加载模型、准备输入输出内存、执行、释放资源。你在真实项目里还需要注意几个点模型每次推理都要把输入数据放到 device 内存里输出也要从 device 拷贝回 host。频繁申请释放内存会带来开销性能调优时最好在初始化阶段一次性申请好内存循环复用。对于 YOLO 这种多输出模型要用acl.mdl.get_output_desc和对应接口分别获取每个输出的大小然后把输出 buffer 按顺序填入。推理完成后记得释放资源否则连续跑几天内存占用会一直涨。3.6 后处理从原始输出到检测框拿到网络输出后还不能直接用。YOLOv5 的输出是三个尺度的特征图上面带有坐标、置信度和类别概率。你需要自己完成解码先将特征图里面每个格子对应的预测框还原到原图坐标然后做置信度过滤最后用 NMS 去掉重复框。这一步的代码和你在 GPU 上写的 YOLO 后处理几乎一样唯一要注意的是数据在内存里的排布方式需要按照模型输出的 shape 和 layout 去解析。如果你不想自己写解码也可以尝试一些封装好的开源推理引擎比如昇腾社区有人开源过基于 AscendCL 的 YOLO 系列样例里面有完整的后处理代码。第一次跑通完全可以基于这些样例改。4. 我实际踩过的坑与排查方法4.1 设备打开失败驱动和固件版本的经典问题现象npu-smi info能看到设备但一运行推理程序就报类似 “device open failed” 或者 ErrCode 100001 之类的错。当时我检查了好几遍驱动显示正常可程序就是起不来。最后定位到驱动版本和固件版本不一致。昇腾的设备管理驱动负责操作系统层和硬件通信固件负责芯片内部微码。两者必须严格匹配否则就会出现“看着在线实际上用不了”的诡异状态。解决办法也直接从官方下载对应的“驱动固件”整包一起重装装完重启问题消失。4.2 ATC 转换报错 E19999算子兼容性问题ATC 转 YOLOv5 时最常碰到的错误码是大类错误 E19999后面通常还跟着更详细的错误描述。比如我遇到过“AI Core operator xxx unsupported”或者“op type xxx not registered”。意思就是当前 CANN 版本里的算子库不认识模型里某一个算子。排查思路是这样的先看日志文件一般在当前目录下的ascend_install.log或 ATC 输出的日志目录里找到具体是哪个算子不支持然后回到导出 ONNX 的环节看能不能绕开这个算子。对于 YOLOv5常见的兼容性问题往往出在nn.SiLU激活函数上。有些低版本 CANN 对 SiLU 支持不完整解决办法是升级 CANN 版本或者在导出 ONNX 时把 SiLU 替换成对应的数学组合形式。我当时直接升级了 CANN 的小版本问题就消失了。4.3 推理结果异常预处理到底该谁来做另一个非常隐蔽的坑是预处理被做了两遍。我一开始图省事在应用侧把图片 resize 后归一化又在 AIPP 配置里开了归一化。结果模型输出置信度全部特别低检测框也完全不对。后来才意识到Atlas 的 AIPP 是在芯片内部、模型推理前自动执行的预处理模块如果你应用侧已经做了归一化AIPP 里就必须关闭。最好的调试方式是第一步完全不使用 AIPP所有预处理在应用侧代码里完成跑通后再考虑把 color conversion、resize 挪到 AIPP 里。这样可以避免一开始就陷入“到底谁改了我的数据”的泥潭。4.4 24G 大显存还是报内存不足24G 听起来很大但在 Atlas 上这块内存是芯片内部的内存同时要存放模型权重、中间特征图、推理输入输出 buffer。如果你创建了多个 context或者开了多个线程同时加载多个模型内存照样会爆。我遇到一次是另一个程序在同一个设备上占了 80% 的内存我的进程一启动就报 OOM。排查办法多用npu-smi info看当前内存占用。它的输出里会显示每个进程占用的显存。如果发现内存被占满要么关掉其他进程要么把推理进程拆成多个设备如果服务器插了多张卡。另外如果你只是做单路视频处理batch 设为 1 即可没必要把输入 batch 开到 4 或 8那样会白白消耗大量内存。4.5 常见问题速查表现象可能原因解决思路npu-smi info 看不到设备驱动未正确加载或硬件没插好检查 lspci重装驱动确认插槽供电设备能见但应用打不开驱动固件版本不匹配下载配套整包重刷ATC 报 E19999算子不支持或输入 shape 不匹配查日志定位算子升级 CANN导简化 onnx推理输出全空或置信度低预处理重复或 AIPP 配置错误先全用应用侧预处理跑通再考虑 AIPPOOM 内存不足模型过大、batch 过高、其他进程占用降低 batch查看 npu-smi 进程占用推理速度明显偏慢没设置多 batch、没使用多 stream、CPU 预处理瓶颈用图模式、多 batch、把预处理移到设备端动态 shape 转换失败输入尺寸不固定导出 ONNX 时固定输入尺寸或使用动态分档配置这张表是我在实际调试中总结出来的基本能覆盖 Atlas 部署 YOLO 时的常见问题。你要是卡住了先对照看一遍大概率能找到方向。5. 关于性能调优和落地建议5.1 调优方向一用足 batch 和多路并发Atlas 300V 24G 最大的本钱就是 24GB 大内存。单张图推理时很多算力单元其实是空闲的。如果你的业务是视频流分析建议不要一条视频流一个进程而是把多路视频帧凑成一个 batch 送进去推理。我自己的实践是把 8 路 1080p 视频帧统一缩放到 640x640打包成 batch8比单独推理 8 次快了将近 4 倍。这里的关键是预处理部分要保证各路视频帧在送进模型前已经对齐到相同 shape否则 batch 打包会很痛苦。5.2 调优方向二把预处理交给 AIPP当你要压榨性能时建议把图像 resize、色域转换、归一化交给 AIPP 去做。AIPP 在芯片内部硬件执行不占主机 CPU也不占用 PCIe 带宽。你只需要把原始图像数据直接拷到 device 内存剩下的交给芯片处理。这个优化在视频流场景里尤其明显因为 1080p 图在主机端做 resize 和 normalize 是非常耗 CPU 的迁移到 AIPP 后CPU 利用率能下降不少。但注意AIPP 的配置比较讲究。比如输入图片的格式、crop 参数、mean 和 var 这些都要和模型训练时的预处理保持一致。YOLOv5 训练时用的归一化是 /255mean 和 var 分别是 0 和 255等价于只缩放不偏移。AIPP 配置里要写成[aipp_op] input_format RGB888_U8 src_image_size_w 640 src_image_size_h 640 crop 0 mean_chn_0 0 mean_chn_1 0 mean_chn_2 0 var_reci_chn_0 0.003921569 var_reci_chn_1 0.003921569 var_reci_chn_2 0.003921569这里的var_reci_chn_0是 1/255 的浮点表示。如果你对训练时的预处理不熟宁可先不用 AIPP。5.3 落地建议什么场景适合 Atlas 300V 24G从我实际项目经验看Atlas 300V 24G 最适合的是推理密集型、对成本敏感、又不想被 GPU 高价捆绑的场景。比如园区摄像头视频结构化、工厂质检OCR缺陷检测、交通流量分析、边缘盒子私有化部署。24G 大内存意味着你可以同时加载多个模型比如 YOLO 检测 人脸特征提取 车牌识别三个模型放一张卡上互相切换成本很低这在多算法融合场景里很划算。反过来如果你想拿它训练 YOLO或者跑一些 PyTorch 里冷门算子那就很不合适。这种场景老老实实用 CUDA 生态更省心。选型这件事关键是看需求画像匹配不匹配而不是谁强谁弱。最后再分享一个小体会Atlas 这套东西最大的学习成本不在写推理代码而在理解它“编译执行”的思维方式。驱动固件、CANN、ATC、om、AIPP这些概念环环相扣任何一个环节理解不到位都会在后面调试时加倍偿还。我第一次编译驱动加刷固件就花了整整大半天一旦环境稳定后真正部署 YOLOv5 反而只用了两天。如果你现在正对着报错日志头疼别急把每一步按顺序理一遍问题通常就藏在那个你跳过的“理所当然”里。
返回列表