ARTICLE DETAIL

资讯详情

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

Atlas 300V 24G昇腾NPU实战:从识别到YOLO模型部署

Atlas 300V 24G昇腾NPU实战:从识别到YOLO模型部署 第一次拿到Atlas 300V 24G这块卡的时候我心里其实带着一个疑问这玩意长得跟GPU挺像插在服务器PCIe槽位上规格表里写着“AI加速卡”但市面上叫“运算加速卡”的东西太杂了它到底算不算能不能真正顶上去用答案很明确算而且它是目前我在端侧和服务端推理场景里用得最顺手的一块昇腾NPU。这篇文章不打算整什么高深理论就围绕“Atlas 300V 24G到底是不是运算加速卡”和“怎么用它把YOLO模型部署起来”这两件事给你一份能直接照着做的实战记录。在开始之前先交代一下适用人群你要是手里正好有一块Atlas 300V 24G或者正在选型AI推理卡想把YOLOv5、YOLOv8这类检测模型从GPU平滑迁移到昇腾环境那么这篇文章适合你。如果你是刚入行只看过一些深度学习教程也没关系我会把驱动安装、模型转换、推理代码、踩坑记录全部拆开讲尽量让你少走弯路。1. 上手前先确认Atlas 300V 24G是谁1.1 它确实是运算加速卡但不是传统GPU很多人看到“运算加速卡”几个字第一反应就是NVIDIA的GPU。实话实说Atlas 300V 24G确实是一块运算加速卡而且是一块非常典型的AI推理加速卡核心芯片是华为昇腾310P属于神经网络处理器NPU。那NPU和GPU有什么区别用大白话讲GPU是为通用并行计算设计的能做图形渲染、科学计算、AI训练也能跑AI推理属于“全能型选手”而NPU是把神经网络里最常见的卷积、矩阵乘、激活函数这些算子尽量用硬件电路直接做掉属于“专精型选手”。跑YOLO这种以卷积和矩阵乘为主的检测模型NPU的算子执行效率往往比同价位的GPU更可观尤其在功耗和单位算力成本上优势明显。所以回到热搜问题“atlas 300v 24g 是运算加速卡吗”答案是肯定的。它是一块专门用于AI推理的计算加速卡但它不是GPU不是让你用来跑CUDA程序的。搞清楚这一点后面很多操作逻辑就顺了。1.2 与同家族几块卡对比看它适合什么活昇腾的推理卡产品线里Atlas 300V系列的定位非常清晰。为了方便对比我整理了一个表格列出Atlas 300I Pro、Atlas 300V Pro、Atlas 300V小显存版本的典型差异型号芯片显存定位典型功耗适合场景Atlas 300I Pro昇腾310P8GB/16GB/24GB数据中心推理卡约72W服务器侧多路视频分析、大batch推理Atlas 300V Pro昇腾310P24GB边缘/数据中心两栖推理卡约72WYOLO类模型部署、批量图片检测Atlas 300V小卡版昇腾310P12GB轻量级推理卡约8W-16W嵌入式设备、小模型加速从参数上看Atlas 300V 24G指的就是Atlas 300V Pro这款24GB显存版本。它的单卡INT8算力在140 TOPS量级具体数值以官方规格书为准FP16算力约70 TFLOPS显存带宽也足够喂饱YOLO这类实时检测网络。24GB显存对一个目标检测任务来说是什么概念YOLOv5s用640分辨率输入模型权重才14MB左右推理时的显存占用通常不到1GB。所以你可能会觉得24GB太“浪费”了。但实际场景里24GB往往不是给单模型用的而是给“同一时刻加载多个模型”或“跑较大batch”用的。比如一台服务器要同时跑YOLOv5、YOLOv8和一个人脸关键点模型每路模型都常驻显存24GB就非常从容。再说说选型建议。你要是只在嵌入式或者边缘盒子里跑单路模型Atlas 300V小卡就够你要是做服务器侧的视频分析、图像检测需要叠加并发那Atlas 300V 24G更合适。我这边的项目是视频流里实时检测车辆和行人block一个模型不够后来直接上24G版本多模型多路并发才不捉襟见肘。2. 部署YOLO前的环境搭建2.1 先装对驱动和固件拿到卡第一件事不是立刻装CANN而是先装NPU驱动和固件。很多人一上来就装工具链结果发现npu-smi都跑不起来十有八九就是驱动和固件缺一不可。以Atlas 300V 24G为例软件栈大概是这么个顺序安装NPU驱动安装NPU固件安装CANN工具包配置环境变量驱动和固件在昇腾社区官网的“Atlas 300V Pro”页面下面下载注意选择跟服务器CPU架构对应的版本。这里有个大坑x86服务器和ARM服务器要下载不同架构的安装包常见的是linux-x86_64.run和linux-aarch64.run下错了会直接报错。安装驱动和固件一般用root执行命令类似chmod x Ascend-hdk-310p-npu-driver_6.3.RC3_linux-x86_64.run ./Ascend-hdk-310p-npu-driver_6.3.RC3_linux-x86_64.run --full chmod x Ascend-hdk-310p-npu-firmware_6.3.RC3_linux-x86_64.run ./Ascend-hdk-310p-npu-firmware_6.3.RC3_linux-x86_64.run --full安装完成后重启服务器然后执行npu-smi info如果能看到卡的温度、显存、算力状态说明驱动和固件都正常了。这一步一定要确认后面所有问题排查都要以“npu-smi能识别卡”为前提。2.2 用Docker隔离环境别直接在宿主上裸奔CANN版本迭代很快而且不同项目依赖的CANN版本可能不一样。我强烈建议用Docker来跑昇腾环境而不是直接装在宿主机上。原因很简单CANN和驱动之间的版本必须匹配一旦搞错重新装一套环境非常耗时Docker可以把环境隔离起来出问题直接删容器重来。昇腾官方提供了带CANN的镜像当然你也可以自己在Ubuntu镜像上装。关键是启动容器时一定要把NPU设备映射进去docker run -itd \ --name yolo-atlas \ --device/dev/davinci0 \ --device/dev/davinci_manager \ --device/dev/hisi_hdc \ --device/dev/devmm_svm \ -v /usr/local/Ascend/driver:/usr/local/Ascend/driver \ -v /usr/local/dcmi:/usr/local/dcmi \ -v /usr/local/bin/npu-smi:/usr/local/bin/npu-smi \ --entrypoint /bin/bash \ ascendhub.huawei.com/public/ascend-ubuntu20.04:latest启动容器后在容器里执行npu-smi info如果能正常显示卡信息说明设备映射成功。这一步卡住的概率很高常见问题是/dev/davinci_manager不存在这通常意味着驱动版本与你下载的固件不匹配或者驱动没有正确加载。2.3 验证环境是否就绪环境装完别急着转模型先做一个最简单的验证。在容器里进入Python环境执行import acl print(acl.__version__)如果能正常导入说明CANN的Python接口已经可用。然后再跑一下python -c import acl; print(acl.rt.set_device(0))这一步会尝试申请NPU设备如果返回0说明设备可用。如果报错优先检查LD_LIBRARY_PATH。通常需要在~/.bashrc里加上source /usr/local/Ascend/ascend-toolkit/set_env.sh这一行一定不能少它能帮你把CANN的库路径、工具路径全部配置好。很多人导入acl失败就是因为忘了source这个脚本。3. 模型转换从YOLOv5权重到OM离线模型3.1 导出ONNX时的几个关键选项昇腾ATC工具并不直接支持PyTorch的.pt权重通常需要先把PyTorch模型导出为ONNX再做一次转换。我的做法是以YOLOv5为例因为YOLOv5在导出ONNX时踩坑最少社区资料也最多。在YOLOv5仓库环境下导出命令大致是python export.py --weights yolov5s.pt --include onnx --opset 11 --batch-size 1这里有两个点要特别注意第一--opset建议不要太高。昇腾ATC对ONNX算子opset的兼容性一直在更新opset 11在大多数CANN版本里兼容性最稳。你用opset 17导出的模型ATC可能报“不支持的算子”或“算子版本不匹配”。我一开始贪新用opset 17结果转换时报Unsupported ops老老实实换回opset 11就过了。第二--batch-size先导成1。动态batch在ATC里不是不能配但配置动态shape时还要加--dynamic-batch-size参数麻烦不说在部分CANN版本下还有性能损失。早期验证阶段固定batch为1足够。导出后得到一个yolov5s.onnx先别急用onnxsim做了简化再转。简化可以消除一些冗余的Transpose、Reshape节点ATC转换成功率更高python -m onnxsim yolov5s.onnx yolov5s_sim.onnx3.2 ATC转换与关键参数ATC工具的路径在CANN安装目录下一般位于/usr/local/Ascend/ascend-toolkit/latest/bin/atc。执行转换时我的标准命令atc \ --modelyolov5s_sim.onnx \ --framework5 \ --outputyolov5s_bs1 \ --input_shapeimages:1,3,640,640 \ --soc_versionAscend310P3 \ --output_typeFP32 \ --loginfo逐项解释一下--framework5表示输入的是ONNX模型。这个参数很容易记错但ONNX确实对应5。--input_shape指定输入张量的名称和尺寸。YOLOv5导出ONNX后输入节点通常叫images维度是1,3,640,640。如果你的YOLOv5版本输入节点名不同可以在onnx里查一下不要盲写。--soc_version这是最关键也最容易填错的参数。Atlas 300V 24G对应的芯片是昇腾310P在部分CANN版本里要写成Ascend310P3。如果你不确定可以先用npu-smi info看芯片型号然后对照CANN文档找到对应的--soc_version。--output_typeFP32指定输出数据类型YOLO后处理在CPU上做时FP32更省事。转换成功后目录下会出现yolov5s_bs1.om文件。看到ATC run success那一刻说明模型转换流程基本跑通了。3.3 我踩过的转换坑模型转换是整个部署链路里最容易出问题的一环我把自己踩过的几个典型问题列一下第一个是“Unsupported op”。YOLOv5中经常出现Focus层、SPP、上采样等结构某些CANN版本对高版本ONNX的Resize算子或者Sliced算子支持不全。解决思路有几种换低版本opset、用onnxsim简化、或者把Pytorch源码里的Focus层提前用普通卷积替换掉。YOLOv5官方后期已经默认去掉Focus层所以如果你用的版本比较新这一步能省心不少。第二个是“Input node data type is invalid”。ATC报这个错往往是因为ONNX输入节点的数据类型是float64而不是float32。YOLOv5导出时一般不会出这个错但如果你是自己写的模型导出前要确认输入张量是torch.float32。第三个是转换成功但推理结果明显不对。这种情况大概率是预处理不一致。比如训练时做了归一化、减均值、除方差但推理时没做或者Color通道顺序反了。后面讲推理代码时我会再强调。4. 推理代码与前后处理细节4.1 pyACL推理主流程在昇腾上跑推理官方提供的Python接口是pyACL。流程不复杂但代码结构相对固定。我贴一个最精简的推理核心片段从加载模型到输出结果import acl import numpy as np # 初始化 acl.init() # 指定计算设备 ret acl.rt.set_device(0) # 加载om模型 model_path yolov5s_bs1.om model_id, ret acl.mdl.load_from_file(model_path) # 获取模型输入输出信息 input_desc acl.mdl.get_input_desc(model_id) output_desc acl.mdl.get_output_desc(model_id) input_size acl.mdl.get_input_size_by_index(model_id, 0) output_size acl.mdl.get_output_size_by_index(model_id, 0) # 分配设备内存 input_mem, ret acl.rt.malloc(input_size, acl.const.ACL_MEM_MALLOC_HUGE_FIRST) output_mem, ret acl.rt.malloc(output_size, acl.const.ACL_MEM_MALLOC_HUGE_FIRST) # 创建stream stream acl.rt.create_stream()接着把预处理好的图像数据放到numpy数组里再拷贝到设备内存# input_data是预处理后的numpy数组shape为(1,3,640,640)dtype为float32 input_data np.ascontiguousarray(input_data) # 获取host端numpy对象的数据指针 input_ptr acl.util.numpy_to_ptr(input_data) # 拷贝到设备内存 ret acl.rt.memcpy(input_mem, input_size, input_ptr, input_data.nbytes, acl.const.ACL_MEMCPY_HOST_TO_DEVICE) # 执行推理 ret acl.mdl.execute_async(model_id, [input_mem], [output_mem], stream) # 同步等待 acl.rt.synchronize_stream(stream) # 把输出从设备拷回host output_data np.zeros(output_size, dtypenp.uint8) output_ptr acl.util.numpy_to_ptr(output_data) ret acl.rt.memcpy(output_ptr, output_size, output_mem, output_size, acl.const.ACL_MEMCPY_DEVICE_TO_HOST)最后记得释放资源acl.rt.free(input_mem) acl.rt.free(output_mem) acl.mdl.unload(model_id) acl.rt.destroy_stream(stream) acl.rt.reset_device(0) acl.finalize()这段代码虽然简单但已经能跑通一个完整的推理流程。实际项目里我通常把加载模型、分配内存、创建stream放在初始化阶段一次性做完推理循环里只做拷贝和execute这样性能会好很多。4.2 图像预处理和后处理预处理决定了模型能不能在推理中“看懂”输入这一步必须和训练时的策略保持一致。YOLOv5训练时通常做letterbox预处理也就是把原始图片等比缩放后填充到640x640。推理时也要做同样的操作不然检测精度会大幅下降。具体步骤包括用OpenCV读取图片得到BGR图像。计算缩放比例把长边缩放到640短边按比例缩放然后填充到640x640。BGR转RGB。除以255归一化把像素值从0-255映射到0.0-1.0。将HWC格式转成CHW格式。增加batch维度转成1,3,640,640的float32数组。我习惯把这段代码封装成函数def preprocess(img): # img: BGR image from cv2, shape (h,w,3) h, w img.shape[:2] target_size 640 ratio min(target_size / h, target_size / w) new_h, new_w int(round(h * ratio)), int(round(w * ratio)) resized cv2.resize(img, (new_w, new_h)) canvas np.full((target_size, target_size, 3), 114, dtypenp.uint8) x_offset (target_size - new_w) // 2 y_offset (target_size - new_h) // 2 canvas[y_offset:y_offsetnew_h, x_offset:x_offsetnew_w] resized # BGR - RGB, HWC - CHW, 归一化 rgb canvas[:, :, ::-1] rgb rgb.astype(np.float32) / 255.0 chw np.transpose(rgb, (2, 0, 1)) return np.expand_dims(chw, axis0)模型输出通常是1, 25200, 85这种shape其中85代表x,y,w,h,obj_conf以及80个类别得分。后处理需要先解析出所有候选框再做NMS非极大值抑制过滤重叠的框。NMS处理时要注意YOLOv5的坐标是相对于640x640的letterbox图的需要把坐标映射回原始图像尺寸。这里的偏移量就是letterbox时记录下来的x_offset、y_offset和缩放比例。不然你拿到的检测框坐标会和原图对不上。这一步最容易踩坑很多同学换到昇腾后推理结果“看起来有点问题”十有八九是letterbox坐标还原没做好。4.3 跑起来之后的性能观察我用Atlas 300V 24G跑YOLOv5s640x640输入单帧端到端延迟包括预处理、推理、后处理在几十毫秒量级纯推理部分更是远低于这个数。这个性能对实时视频流分析来说是完全够用的。当然具体数值跟你用的CANN版本、是否开启算子调优、batch大小都有关系。值得一提的是Atlas 300V 24G在跑batch 4或者batch 8时性能提升比较明显。如果你的场景允许攒批比如对一批图片做离线检测尽量把batch加大一些NPU的利用率会更高。我第一次测试时傻乎乎地batch1一张一张跑后面改成批量提交吞吐量提升了不少这是经验之谈。5. 常见问题排查与调优心得5.1 排查表高频报错部署昇腾大概率会遇到各种报错。我把高频问题整理成一张表方便直接对号入座现象可能原因解决思路npu-smi info无法显示卡驱动未安装或驱动与固件版本不匹配重装匹配版本的驱动和固件重启机器容器内看不到/dev/davinci*Docker启动参数没加设备映射加上--device/dev/davinci0等参数acl导入失败没有source set_env.sh执行source /usr/local/Ascend/ascend-toolkit/set_env.shATC转换报Unsupported opONNX算子或opset版本过高降低opset到11使用onnxsim简化模型推理结果全是0或形状不对预处理与训练不一致或输出解析错误检查letterbox归一化、通道顺序、输出shape执行推理报错507033设备内存不足或重复分配未释放检查显存占用确保acl.rt.free释放多卡调用时冲突没有正确指定设备ID用acl.rt.set_device(card_id)显式指定报错信息里最烦的是507033这类错误码你光看数字很难猜出原因。遇到这种可以查CANN日志日志路径一般在~/ascend/log把日志级别调成DEBUG后再跑一次关键报错会写得很详细。5.2 性能调优的几个方向跑通了只是第一步想压榨Atlas 300V 24G的性能可以从这几个方向做调优第一个方向是用AIPP做预处理。ATC转换时可以配置AIPP把图片缩放、色域转换、归一化都放到硬件上做这样就不用每次推理都在CPU上做预处理能省下不少时间。但代价是AIPP配置比较繁琐而且灵活性不如自己写预处理代码。建议前期先用CPU预处理跑通后期再考虑AIPP优化。第二个方向是开算子调优。ATC转换时有一个--optypelist_for_implmode和--op_select_implmode参数可以指定算子的高性能实现方式。你可以在CANN的日志目录里看算子调优报告找到哪些算子耗时异常再针对性地优化。第三个方向是合理使用Stream。pyACL里acl.rt.execute_async是异步接口如果能在读图、预处理、推理、后处理之间用多个Stream做流水线性能还能再上一个台阶。不过异步编程的复杂度较高建议先把同步流程跑稳再改。第四个方向是注意数据摆放。输入numpy数组一定要满足内存连续如果不连续拷贝到设备时会多一次拷贝操作。我习惯在预处理输出时加一句np.ascontiguousarray。另外建议定期升级CANN版本。昇腾的算子支持和性能优化更新非常频繁半年后的新版本可能比旧版本性能提升20%以上。2023到2024年CANN在YOLO系列模型上的优化力度很大升级之后经常能白捡性能。我个人在实际项目里的体会是Atlas 300V 24G这块卡性能扎实、功耗低特别适合To B或To G场景下的AI推理部署。但它的学习曲线比GPU要陡一些核心难点不在推理代码而在于环境版本匹配和模型转换。只要你把驱动、固件、CANN这套组合拳打好把ONNX转OM的流程走顺后面跑YOLO其实非常省心。最后再分享一个小技巧但凡在转换或推理阶段遇到奇怪问题先检查版本匹配关系。驱动版本、固件版本、CANN版本、芯片型号、容器镜像这几个因素只要有一个对不上就会出现诡异的报错。先不要怀疑代码先用排除法把环境版本锁死在一个已知OK的组合上再往下调。我在部署第二个项目时就是靠这个方式把一个“看起来像模型问题”的环境问题快速定位出来的。
返回列表