尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

Atlas 300V 24G推理加速卡部署YOLOv5/v8实战与踩坑记录

Atlas 300V 24G推理加速卡部署YOLOv5/v8实战与踩坑记录 最近后台收到不少朋友在问同一个问题Atlas 300V 24G 这块卡到底是不是运算加速卡能不能拿来部署 YOLO正好我手里有一张 Atlas 300V 24G从开箱到把 YOLOv5 和 YOLOv8 都跑通前前后后折腾了大半个月中间踩的坑比想象中多得多。这篇文章就把整个部署过程、硬件定位、模型转换链路和实测数据一次性说清楚给正在犹豫选型和准备入手的同学一个参考。1. 先回答是不是加速卡Atlas 300V 24G 的真实定位先说结论Atlas 300V 24G 确实是运算加速卡但它是推理加速卡不是拿来训模型的卡。这个定位差异直接决定了你能不能拿它干你想干的事必须一开始就搞清楚。1.1 拆开规格看本质310P 芯片与 24G 显存Atlas 300V 系列基于昇腾 310P 芯片这一点从命名就能看出来——300V 里的 V 代表推理inference产品线。我手里这张 24G 版本单卡配备 24GB 显存整卡功耗大概在 72W 左右采用半高半长的被动散热设计适合插在服务器里通过风道散热。关键参数我整理了一个表格方便对照参数项Atlas 300V 24G芯片昇腾 310P多个 Die 组合显存容量24GB显存类型LPDDR4XINT8 算力约 140 TOPSFP16 算力约 70 TFLOPS功耗约 72W接口PCIe 4.0 x16散热方式被动散热典型场景视频分析、目标检测、OCR、推荐系统推理24GB 这个容量在推理卡里算比较大的这也是很多人把目光投向它的核心原因。市面上同价位的 GPU 卡显存普遍在 8GB 到 16GB 之间显存焦虑确实是很多人的痛点而 24G 显存意味着可以塞下更大的 batch size或者跑一些参数量较大的模型。1.2 它和 NVIDIA GPU 的本质区别在哪NVIDIA 的卡比如 T4、A10、L4既能训练也能推理而 Atlas 300V 系列不支持训练。这不是简单的软件限制而是硬件层面的设计差异。310P 芯片的张量计算单元主要针对推理算子做了优化虽然也支持 FP16 计算但是缺少训练所需的自动微分、梯度同步等硬件支持。说白了训练任务里大量的反向传播计算在 310P 上跑不起来或者速度极慢。另外Atlas 300V 在生态上和 CUDA 完全是两个世界。CUDA 发展了十几年PyTorch、TensorFlow 直接pip install就能用 GPU 加速而昇腾平台你需要安装 CANN华为昇腾计算架构模型也要转成 OM 格式才能在 NPU 上跑。这个格式壁垒是很多人拿到卡之后第一个不适应的地方。1.3 适合什么场景不适合什么场景从我的实际使用经验来看Atlas 300V 24G 适合这些场景视频流实时推理比如智慧园区、明厨亮灶、安防监控这类 24 小时不间断的视频分析一张卡同时跑十路八路 1080p 视频的 YOLO 检测毫无压力。批量离线推理需要对历史视频、图片库做批量检测的场景24G 大显存能撑起较大的 batch吞吐量很可观。国产化替代项目信创项目里要求国产算力时昇腾是绕不开的选择Atlas 300V 是常见的推理卡型号。不适合的场景也很明确模型训练和微调别拿它训练哪怕是小模型。虽然能跑通但速度会让你怀疑人生。需要 CUDA 生态依赖的算法很多新出的算法依赖 CUDA 算子库昇腾平台支持不了需要自己移植算子成本很高。重要提醒买卡之前一定要确认你的算法模型能不能转成 OM 格式。如果模型里有昇腾不支持的算子比如某些自定义算子转换会失败这时候卡就变成一块废铁了。建议先跑通模型转换再下单。2. 部署 YOLO 前的准备环境、驱动与 CANN 软件栈确定这块卡能干活之后接下来就是环境搭建。这一步最考验耐心因为昇腾的软件栈比 CUDA 复杂不少版本匹配关系也比较严格。2.1 第一件事驱动、固件和 CANN 的版本匹配Atlas 300V 要正常工作需要装三层软件驱动Driver、固件Firmware、CANN 工具包。这里有个容易搞混的地方固件和驱动是分开发布的而且必须配套。如果你装了新驱动但固件还是旧的npu-smi info可能会显示异常甚至卡直接不识别。我一开始就吃过这个亏驱动装好了但固件没升结果 NPU 状态一直是 Faulty。推荐的做法是到昇腾社区下载对应型号的固件驱动包一个包里面同时包含固件和驱动直接解压后执行安装脚本就行。版本选择上建议使用 CANN 8.0 及以上版本配套的固件驱动因为新版 CANN 对 ONNX 模型的兼容性更好。执行安装时用 root 权限# 解压固件驱动包 chmod x Ascend-hdk-310p-npu-firmware_*.run ./Ascend-hdk-310p-npu-firmware_*.run --full # 解压驱动包 chmod x Ascend-hdk-310p-npu-driver_*.run ./Ascend-hdk-310p-npu-driver_*.run --full安装完成后重启机器然后执行npu-smi info如果能看到类似下面的输出说明 NPU 已经被正确识别------------------------------------------------------------------------------------------------ | npu-smi 24.0.rc1 Version: 24.0.rc1 | | NPU Name | Health | Power | HBM-Usage | Temp | | | 0 | OK | 32W | 1203M / 24576M | 38C | 这里要注意 HBM-Usage显存使用那一栏Atlas 300V 24G 总显存是 24GB但实际可用大概在 22GB 左右因为有一部分被系统保留不用纠结这个差异。2.2 CANN 安装决定模型能否转换的关键CANN 是昇腾平台的软件栈类比 CUDA cuDNN 的合体。安装 CANN 的方式有两种通过pip安装 或者 下载 run 包安装。我强烈推荐用pip 安装方式因为后续 Python 接口的版本和 CANN 版本能自动对齐不容易出幺蛾子pip install cann-toolkit或者如果你有明确的版本需求也可以指定版本号pip install cann-toolkit8.0.0安装完之后设置环境变量source /usr/local/Ascend/ascend-toolkit/set_env.sh这个set_env.sh是必须 source 的否则命令行找不到atc模型转换工具和msame模型推理工具。建议直接写进.bashrc省得每次手动执行。2.3 容器化部署推荐 Docker 方案如果你和我一样是在 x86 服务器上部署强烈建议使用官方提供的昇腾 Docker 镜像。镜像里面已经把固件驱动、CANN 都预装好了只需要在启动容器时把宿主机的 NPU 设备映射进去。官方镜像拉取和启动命令docker pull ascendhub.huawei.com/public/ascend-infer:24.0-ubuntu20.04 docker run -it \ --device/dev/davinci0 \ --device/dev/davinci_manager \ --device/dev/hisi_hdc \ --volume /usr/local/Ascend/driver:/usr/local/Ascend/driver \ --volume /usr/local/dcmi:/usr/local/dcmi \ --volume /usr/local/bin/npu-smi:/usr/local/bin/npu-smi \ ascendhub.huawei.com/public/ascend-infer:24.0-ubuntu20.04 \ /bin/bash注意--device/dev/davinci0是映射 NPU 设备节点。如果你服务器插了多张卡需要把 davinci0、davinci1 等都映射进去否则容器里只能看到第一张卡。容器化部署的好处是隔离性好驱动和 CANN 版本不一致的问题减少很多。但要注意如果宿主机驱动版本和容器镜像里的驱动版本不匹配NPU 设备是映射不进去的。所以拉镜像之前先确认宿主机驱动版本最好保持一致。3. 从 ONNX 到 OM模型转换的完整实操记录环境准备好之后就到了整个部署流程里最关键也最容易出错的一步把 PyTorch 训练好的 YOLO 模型转换成昇腾平台能识别的 OM 格式。3.1 YOLOv5 导出 ONNX 的几个坑我以 YOLOv5 为例说明YOLOv8 的流程类似只是导出脚本参数略有差异。首先在 PyTorch 环境里导出 ONNXimport torch from models.experimental import attempt_load model attempt_load(yolov5s.pt, map_locationcpu) model.eval() dummy_input torch.randn(1, 3, 640, 640) torch.onnx.export( model, dummy_input, yolov5s.onnx, opset_version11, input_names[images], output_names[output0] )这一步看起来简单但实际上有几个容易踩的坑第一个坑opset_version 不能太高。昇腾 ATC 工具对 ONNX 算子的支持是逐渐完善的opset 版本太高比如 17、18会导致部分算子不识别。实测下来 opset_version11 是最稳的算子支持最全。第二个坑必须把模型切到 eval 模式。如果模型还处于 training 模式导出的 ONNX 里会包含 BNBatch Normalization层的训练逻辑ATC 转换时会报算子不支持。第三个坑YOLO 的检测头和 ONNX 的兼容性。YOLOv5 的检测头在导出 ONNX 时通常没问题但 YOLOv8 的检测头结构不同导出时最好使用官方提供的export.py脚本它会自动处理一些兼容性问题python export.py --weights yolov8s.pt --include onnx --opset 113.2 ATC 工具转换命令与参数说明拿到 ONNX 模型之后用 ATC 工具转换成 OM 格式。ATC 的路径一般在/usr/local/Ascend/ascend-toolkit/latest/bin/atc如果环境变量 source 正确可以直接执行atc --modelyolov5s.onnx \ --framework5 \ --outputyolov5s_om \ --input_shapeimages:1,3,640,640 \ --soc_versionAscend310P3 \ --output_typeFP32几个关键参数解释一下--framework55 代表 ONNX 模型这是固定值不能改。--output输出文件路径不需要加后缀ATC 会自动生成 .om 文件。--input_shape输入张量的形状注意要和导出 ONNX 时的 dummy_input 保持一致。--soc_versionAscend310P3这个参数特别重要必须填对芯片型号。Atlas 300V 对应的 SoC 版本是 Ascend310P3如果填错转换会报错或者生成的 OM 在推理时报错。--output_typeFP32指定输出数据类型。如果模型输出是 FP32 的检测框坐标就指定 FP32。有时候输出类型不匹配会导致检测框坐标全部乱掉表现为检测不到目标或者框的位置完全不对。转换成功的话终端会输出类似ATC run success, save om offile to yolov5s_om.om3.3 转换报错的排查链路转换失败是家常便饭我就遇到过至少五种不同的报错。这里分享一下排查的完整链路比直接给答案更有用。第一步看报错信息里的算子名称。这是最关键的定位手段。ATC 报错通常会指出哪个算子不支持比如[ERROR] Op type [Sigmoid] is not supported这时候要先去查这个算子在昇腾社区的算子支持列表里是否真的不支持。很多时候并不是算子完全不支持而是参数配置不兼容。比如某个算子在量化模型里不支持某种数据格式或者在新版本 CANN 里已经被替代了。第二步检查 ONNX 模型是否有动态维度。昇腾推理卡对动态 shape 的支持非常有限模型输入必须是固定 shape。如果你的 ONNX 模型是通过动态 batch 导出比如dynamic_axes设置了 batch 维度为动态ATC 转换大概率会失败。解决方法是重新导出固定 shape 的 ONNX 模型。第三步用 polygraphy 或 onnxsim 简化模型。有时候 ONNX 模型里有大量冗余的恒等算子、Shape 算子这些会影响 ATC 的解析。用 onnxsim 简化一遍往往能解决很多莫名其妙的问题pip install onnxsim onnxsim yolov5s.onnx yolov5s_sim.onnx第四步降低 opset 版本重新导出。如果上面三步都没解决回到导出阶段把 opset_version 从 13 降到 11重新导出再转。提示不要试图把 NMS非极大值抑制放进 ONNX 模型一起转换。昇腾平台虽然也有 NMS 算子支持但测试下来兼容性一般一个不兼容就会卡住整个部署。更合理的做法是模型只输出原始预测框、置信度和类别概率NMS 放后处理阶段用 CPU 或者昇腾的 ACL 接口实现。4. 在 Atlas 300V 24G 上跑通 YOLO 推理模型转换成功只是第一步真正跑起来还会遇到不少软钉子。这里记录我用 Python ACL 接口完成推理的完整过程。4.1 Python ACL 推理的最小实现昇腾提供 Python ACL 接口类似 PyTorch 的 Python API但写起来会更底层一些。核心流程是初始化算力设备、加载 OM 模型、准备输入输出内存、执行推理、解析结果。import numpy as np import acl from PIL import Image # 初始化 ACL acl.init() ret acl.rt.set_device(0) context, ret acl.rt.create_context(0) # 加载 OM 模型 model_path byolov5s_om.om model_id, ret acl.mdl.load_from_file(model_path) # 获取模型描述信息 desc acl.mdl.create_desc() ret 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) # 准备输入数据 image Image.open(test.jpg).resize((640, 640)) input_data np.asarray(image, dtypenp.float32) / 255.0 input_data input_data.transpose(2, 0, 1)[None, :, :, :] # 用 ACL 的数据缓存函数把 numpy 数据拷贝到设备内存 input_ptr acl.util.numpy_to_ptr(input_data) output_ptr acl.util.numpy_to_ptr(np.zeros(output_size, dtypenp.float32)) # 执行推理 ret acl.mdl.execute(model_id, input_ptr, input_size, output_ptr, output_size) # 把输出数据拷贝回 host 内存 output_data acl.util.ptr_to_numpy(output_ptr, (output_size,), np.int8)这里有个关键点acl.mdl.execute要求输入数据必须存放在设备内存上。我见过不少新手直接用 numpy 数组传给 execute结果报内存访问错误。正确做法是先用acl.util.numpy_to_ptr把输入 data 拷贝到设备侧再传给执行函数。4.2 输入输出的数据排布问题YOLO 模型在 PyTorch 里的输入是 NCHW 格式batch, channel, height, width颜色通道顺序是 RGB。但用 OpenCV 读图时是 BGR用 PIL 读图是 RGB。这个转换如果做错了模型推理结果会非常奇怪——不是完全检测不到而是检测框乱七八糟置信度极低。还有一个容易被忽略的是归一化操作。YOLOv5 在训练时做了像素值除以 255 的归一化操作推理时也要保持一致。如果忘记归一化而直接把 0~255 的原始像素值送进模型推理结果会非常差甚至全是 0 置信度。我的经验是把预处理统一封装成一个函数避免不同脚本之间处理方式不一致def preprocess(image_path, input_shape(640, 640)): image Image.open(image_path).convert(RGB) image image.resize(input_shape) img_array np.asarray(image, dtypenp.float32) img_array img_array / 255.0 img_array img_array.transpose(2, 0, 1) img_array np.expand_dims(img_array, axis0) return np.ascontiguousarray(img_array)4.3 后处理YOLO 输出的解码与 NMSOM 模型的输出是原始的检测头输出形状通常是(1, 25200, 85)或者(1, 84, 8400)这样的三维张量。以 YOLOv5 的(1, 25200, 85)为例85 4坐标 1置信度 80COCO 类别数。推理拿到原始输出后需要先解析出检测框坐标中心点 x、y、宽、高再过滤低置信度的框最后做 NMS。这部分代码比较繁琐建议直接用 YOLO 官方仓库里的后处理逻辑不要自己重写。但有一点要注意官方代码是面向 PyTorch 张量的实现输入的是 GPU 上的张量而昇腾平台的输出是 numpy 格式需要做类型转换后再送入后处理函数。4.4 性能实测单卡推理延时和吞吐量我把 YOLOv5s 和 YOLOv8s 在 Atlas 300V 24G 上分别做了实测单张 640x640 图片的推理延时如下模型输入分辨率单图推理耗时ms帧率FPSYOLOv5s640x64025-3033-40YOLOv8s640x64030-3528-33YOLOv5s1280x128080-9011-12这个数据是在 batch_size1 的情况下测得的。如果把 batch_size 加大到 8吞吐量提升非常明显——单图延迟会增加到 60ms 左右但总处理帧数能到 130 FPS说明加大 batch 是提升单位时间处理量的关键手段。24G 大显存在这里就发挥出优势了。用 batch_size16 跑 YOLOv5s640x640完全没问题显存占用也就 6-8GB 的样子离 24G 还远得很。如果你要跑 YOLOv5x 或者 YOLOv8x 这种大模型24G 显存也能轻松容纳 batch8 的输入。5. 部署过程中的典型故障与调优思路部署过程中我记录的典型故障大概有七八类这里挑几个最有代表性的分享这些坑在昇腾论坛上被反复提问过说明不是个例。5.1 模型输出全是零置信度数据预处理不一致这是我碰到的第一个大坑。OM 转换成功、模型加载成功、推理也不报错但输出的置信度全为 0检测框一个都找不到。排查过程先用一张训练集里的图片测试排除模型本身没学到特征的可能。检查预处理流程对比 PyTorch GPU 推理的预处理发现问题出在归一化。PyTorch 端推理时用了 transforms.Normalize(mean[0.485, 0.456, 0.406], std[0.229, 0.224, 0.225])而我的 ACL 预处理只做了除以 255没有做 ImageNet 标准化。YOLOv5 在 export ONNX 时默认会去掉标准化层因为标准化可以融合到卷积层里但 YOLOv8 的导出可能保留标准化层。如果导出的 ONNX 里没有标准化层就需要在预处理阶段手动做标准化。正确的预处理对应 YOLOv8 导出mean np.array([0.485, 0.456, 0.406], dtypenp.float32) std np.array([0.229, 0.224, 0.225], dtypenp.float32) img_array (img_array / 255.0 - mean) / std5.2 推理速度越来越慢内存泄漏与缓存未清理跑了一段时间后发现推理速度从最初的 25ms 逐渐退化到 100ms 以上最终甚至卡死。排查后发现是没有及时释放 ACL 内存。ACL 的acl.mdl.execute会分配设备内存如果推理循环里反复调用而不释放内存最终会被吃满导致显存溢出和速度骤降。解决方法是使用 ACL 的内存池机制或者每次推理后在循环内主动销毁输出指针# 每次推理后释放 acl.rt.free(output_ptr)另一个性能杀手是没有使用 ACL 的 stream 并发机制。昇腾 NPU 支持多个 stream 并行执行如果你的应用是视频分析场景建议使用多线程 多 stream 的方式每个 stream 处理一路视频流吞吐量能提升 2-3 倍。5.3 显存占用与 batch_size 的平衡虽然 24G 显存很大但也架不住盲目加大 batch。我测试了几个配置组合模型Batch Size显存占用单图耗时备注YOLOv5s 6401~2.1GB25ms延迟最优YOLOv5s 6408~5.8GB45ms吞吐较好YOLOv5s 64016~9.6GB80ms吞吐最高YOLOv5x 6404~14GB120ms延迟偏高YOLOv5x 6408~21GB180ms接近显存上限从表格可以看出显存占用并不是线性增长的随着 batch 增大每个样本的额外开销变小显存利用率会高一些。但 batch 增大会导致单图延迟快速上升所以需要根据场景取舍实时交互场景比如摄像头实时检测batch1 是最优选择延迟最低。离线批量任务比如历史视频分析batch8~16 更划算单位时间处理量最大化。经验分享如果发现显存不够用不一定非要减小 batch也可以考虑把输入分辨率从 640 降到 544 或 416。YOLO 模型对输入分辨率不太敏感416x416 和 640x640 的 mAP 差距在 2%-3% 左右但推理速度提升接近一倍。这在部署阶段是性价比很高的调优手段。5.4 多卡并行如何发挥多张 Atlas 300V 的性能如果服务器插了多张 Atlas 300V可以在应用层实现多卡并行。ACL 中通过acl.rt.set_device(device_id)切换设备。我的做法是用 Python 的 multiprocessing 或者线程池每个线程绑定一张卡各自加载同一个 OM 模型然后分发推理任务。实测 4 卡并行可以获得接近 3.5 倍的加速比损失的部分主要是进程调度和数据拷贝开销。需要特别注意的是多进程场景下每个进程都要先调用acl.init()再调用acl.rt.set_device()且两个进程不能共享同一个 context。否则会报设备被占用错误。6. 部署完之后的进一步思考Atlas 300V 24G 这块卡给我最大的感受是它是一块称职的推理卡但不是一块省心的卡。和 N 卡开箱即用的体验不同昇腾平台的部署链路更长涉及的工具更多踩坑的几率也更大。但如果你能接受这个学习成本它的性价比确实可观——相比同等显存规格的 N 卡价格低了不少而且推理性能并不逊色。我接下来的几个方向是尝试 MindSpore 框架。CANN 对自家 MindSpore 框架的支持是最完善的从训练到推理全链路无痛只是生态比较小众可参考的案例少。用 MindX SDK 替换手动 ACL 编程。MindX SDK 是昇腾高层 API内置了图像解码、缩放、模型推理、后处理这些常用组件开发效率比纯 ACL 高很多。把模型部署到昇腾 Atlas 200I DK 开发者套件上。这是一块比 300V 更便宜的单板适合边缘场景功耗更低测试完再分享经验。如果在部署过程中遇到具体问题欢迎在评论区留言我会尽量回复。也建议折腾过程中养成记录日志的习惯——昇腾的报错信息虽然晦涩但每次排查都是一次对算子、数据流和内存管理的深入理解这对后续做选型评估非常有帮助。
返回列表