拓十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

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

Atlas 300V 24G部署YOLO实战:从推理卡环境搭建到性能优化

Atlas 300V 24G部署YOLO实战:从推理卡环境搭建到性能优化 最近工作室来了张Atlas 300V 24G正好手里有几个YOLO检测项目要落地。折腾了几天从装卡、配置环境到把模型跑起来中间踩了不少坑也摸到了一些门道。这篇就把我拿这张运算加速卡部署YOLO的完整过程写出来包括硬件安装、软件栈匹配、模型转换推理、性能优化和问题排查。先说明一点Atlas 300V 24G不是有人误以为的显卡或训练卡它是一张标准的AI推理加速卡主要用昇腾芯片做服务器端的推理负载典型场景就是YOLO这类目标检测模型的部署。如果你手里正好有这张卡或者正在选型阶段拿它跟别的推理方案对比想知道它到底能不能跑YOLO、怎么跑、瓶颈在哪那这篇应该能帮上忙。下面的操作都在一台x86 Ubuntu 22.04服务器上完成CANN工具链版本以5.1.RC2为基准不同版本的命令差异我会单独标注。1. 先搞清楚Atlas 300V 24G是什么卡部署前心里才不慌1.1 插上去的第一眼它跟GPU的定位完全不一样Atlas 300V这个系列的卡核心定位是数据中心场景下的AI推理。我第一次把这张卡插进PCIe插槽的时候第一反应是轻质感上就是一块标准的半高半长卡不需要外接辅助供电跟动辄双风扇、三风扇的GPU卡站在一起完全两个画风。这个形态本身就说明了它的使用场景在2U/4U服务器里一张24G显存版本的推理卡可以做到单槽位、低功耗、高密度部署这是很多同性能GPU给不了的。再看接口和指示灯。卡上除了PCIe金手指没有多余的视频输出口所以它天生不是给你接显示器用的。前后的状态灯在驱动正确安装后会变成绿色如果一直是黄色或者红色大概率是驱动没起来或者卡没被系统正确识别。这个细节在我第一次上电时帮了大忙后面排查问题也经常靠看灯。这张卡的核心是昇腾310P系列芯片属于纯推理芯片训练不是它该干的活。24G版本在这个系列里属于大显存档位目标很明确让一个模型用更大的batch跑或者同时塞多个模型进去做多路推理。简单理解训练卡像造样品的实验室推理卡像流水线这张卡就是流水线上一条功率不高但很能出活的产线。1.2 技术指标背后的真实含义TOPS和24G显存到底意味着什么看昇腾推理卡参数时最容易被绕晕的就是各种算力单位。Atlas 300V这类卡标称的算力通常是INT8 TOPS比如1XX-2XX TOPS这个量级。很多人拿这个数字直接跟GPU的FP32 TFLOPS比然后得出这卡真猛的结论其实是不对的。TOPSTera Operations Per Second是每秒万亿次整数运算适合衡量推理场景的定点算力GPU标称的TFLOPS则主要指浮点算力。跑YOLO这类模型时经过量化后主要吃INT8算力所以这张卡纸面数字确实不难看但你不能指望它跑训练也不能拿FP16精度去硬碰高精度浮点任务那是两码事。24G显存怎么理解以YOLOv5s为例FP16精度的模型权重大概几十MB单张640x640图片的中间特征图占用的内存也不大理论上几个GB就够跑了。24G显然不是为了单路小模型准备的。它更适合以下场景一是大batch推理一次塞32张甚至64张图进去通过吞吐量摊薄调度开销二是多模型常驻比如同一张卡上常驻YOLOv5检测、YOLOv8分割、一个分类模型按需调度三是背景复杂的高分辨率输入比如4K图像切块处理输入输出的缓冲区就得多预留。换句话说24G买的是灵活度和余量。还有一个容易忽略的参数是功耗。这张卡空载时基本没什么发热满载功耗控制在一个相对友好的水平比同性能的GPU低不少。对机房租用机位、电力有限的环境来说这个特性有时候比绝对性能更值钱。我实际测下来单卡跑YOLOv5s INT8模式满负载运行整机功耗上升并不夸张服务器原装电源完全带得动不需要额外改供电。1.3 上了昇腾这条船先调整心态这不是CUDA部署之前必须做好心理预期昇腾的软件生态和CUDA是两套体系。CUDA生态里写好的Python推理脚本、PyTorch模型没办法直接拿过来用。你需要把模型转换成昇腾的OM格式用ACL或pyACL这套接口去加载和执行很多算子的实现细节也需要针对昇腾芯片做适配。这不是说它不好而是说你要做好多花时间在环境适配和心理建设上的准备。但反过来也有好处。GPU方案在推理场景往往大材小用驱动、CUDA版本、PyTorch版本之间稍有不匹配就崩给你看昇腾这边只要驱动、固件、CANN版本对齐了模型转换推理链路其实是比较固定的。我第一次花了大半天适配环境后面再跑新模型就顺了很多基本就是导出ONNX、转OM、写推理脚本这三个固定步骤。换句话说学习曲线陡但一旦爬过那个坎后续的流程化程度很高。2. 环境搭建从插卡到npu-smi能看见卡这步不能急2.1 硬件安装与BIOS设置细节决定能不能识别硬件安装本身不难但有几个细节直接影响后面能不能顺利识别。首先确认主板有空闲的PCIe x16插槽最好插在直连CPU的槽位上不要插在走芯片组的槽位。为什么虽然推理卡对PCIe带宽的敏感度不像训练卡那么夸张但走芯片组会跟其他设备抢带宽高负载下的稳定性会受影响。插槽的物理供电能力也要注意虽然这张卡不需要外接供电但PCIe插槽本身需要提供足够的75W供电老旧主板的PCIe供电滤波不好可能会在高负载时掉卡。装好之后开机进BIOS有两个设置建议提前确认。第一个是Above 4G Decoding这个选项在多数主流主板上默认是关闭的但昇腾系列推理卡需要它来正确映射大地址空间不开的话系统可能识别不到卡或者驱动加载时报资源不足。第二个是Resizable BAR / Re-Size BAR Support部分主板又叫SR-IOV或者PCIe BAR Sizing能开就开对DMA传输的稳定性有帮助。改完BIOS设置后保存重启别急着装软件先看系统能不能发现设备。用lspci命令确认一下卡是否在总线上lspci | grep -i process如果能看到类似Processing accelerators: Huawei Technologies Co., Ltd. 这样的条目说明硬件层面已经被系统发现了。如果你在x86服务器上命令输出里什么都没有先回头检查PCIe插槽和BIOS设置别急着怪驱动。2.2 驱动、固件和CANN的版本匹配这是最大的坑昇腾环境的版本匹配是我见过最容易出问题的环节。驱动Driver、固件Firmware、CANN工具包必须配套交叉版本轻则功能异常重则模块加载直接失败。我的建议是别自己东拼西凑去昇腾社区下载对应型号的软件包列表选一个稳定配套版本整套安装。下面是实际操作的完整流程。先把软件包传到服务器上一般需要三个东西驱动包Ascend-hdk-xxx.run、固件包Ascend-atc-xxx.run或者合并在驱动里、CANN工具包Ascend-cann-toolkit_xxx.run。不同版本文件名有差异但安装方式大同小异。安装驱动和固件chmod x Ascend-hdk-*.run ./Ascend-hdk-*.run --full --install-for-all--full参数表示驱动固件都装--install-for-all表示给所有用户装省得后面普通用户权限不足。安装完成后重启一次系统让内核模块生效然后运行npu-smi info正常情况下能看到卡的型号、芯片名称、显存大小、驱动版本这些信息。如果这里报错或者看不到卡多半是前面BIOS设置的问题或者驱动和固件版本不一致。我当时第一次装的时候驱动和固件是从两个不同时间点下载的结果npu-smi能列出卡但状态始终是Fault最后重新下了一套同批次的包才恢复正常。所以我的经验是驱动、固件、CANN尽量从同一版本的发布说明页里下载不要图新混搭。接着装CANN工具包chmod x Ascend-cann-toolkit_*.run ./Ascend-cann-toolkit_*.run --install --install-for-all装完以后环境变量已经自动写到了/usr/local/Ascend/ascend-toolkit/set_env.sh每次开新终端记得source一下source /usr/local/Ascend/ascend-toolkit/set_env.sh检查工具链是否可用which atc能输出路径说明ATC模型转换工具已经就位。到这里一张卡从硬件到工具链就算跑通了。2.3 要不要用Docker部署我的建议是尽量用如果你之前玩过GPU部署肯定知道Docker镜像省去了很多环境地狱问题。昇腾这边同样有官方容器镜像把驱动、CANN、运行环境都打包好了。我实际部署应用时就是直接拉镜像起容器而不是在裸机上反复折腾Python依赖。用容器需要注意两点第一挂载设备要用昇腾的Docker Runtime而不是默认的runc否则容器里看不到NPU设备第二版本同样要对齐容器镜像和宿主机的CANN版本最好保持一致不然可能报ACL库版本不匹配。我把启动命令贴出来实际使用替换镜像名和挂载路径即可docker run -it --name atlas-yolo \ --device/dev/davinci0 \ --device/dev/davinci_manager \ --device/dev/hisi_hdc \ -v /usr/local/Ascend/driver:/usr/local/Ascend/driver \ -v /etc/ascend_install.info:/etc/ascend_install.info \ ascendai/cann:5.1.RC2-ubuntu20.04 \ bash容器内部也要source环境变量source /usr/local/Ascend/ascend-toolkit/set_env.sh这样折腾一轮之后宿主机上的Python环境可以保持很干净项目依赖全锁在镜像里换机器迁移也方便得多。3. 部署YOLO的完整链路从ONNX到OM再到板卡推理3.1 模型选型和ONNX导出定型定尺寸是关键一步我实际部署时分别跑了YOLOv5s和YOLOv8s。选型建议是如果追求低延迟和部署简单YOLOv5s优先如果精度要求高一些YOLOv8s也可以但后处理的算子适配要多花点心思。最终导出ONNX时有一个关键决策固定输入shape还是用动态shape。我的建议是推理卡上尽量固定输入shape。原因很简单ATC转换OM模型时输入shape越固定编译器能做的图优化越激进性能越好。动态shape意味着运行时才知道输入尺寸很多内存规划和算子融合没法提前做性能会有明显折扣。实际项目中按640x640输入、batch1转换这样最简单也最容易排查问题。如果确实需要动态shape需要在ATC命令里单独配置而且后续调优会痛苦很多。导出ONNX时以YOLOv5为例用官方仓库的export.pypython export.py --weights yolov5s.pt --include onnx --opset 11 --batch-size 1 --img 640这里opset版本建议用11太高或太低在ATC转换时都容易出幺蛾子。导出后可以用一个简单的ONNX检查脚本确认模型结构没丢import onnx model onnx.load(yolov5s.onnx) onnx.checker.check_model(model) print(ONNX model is valid)这时候要注意ONNX模型里的输出通常包含3个尺度的检测头shape类似[1, 255, 80, 80]、[1, 255, 40, 40]、[1, 255, 20, 20]因为是5个类别所以是255。如果你导出时有NMS插件或者自定义算子ATC转换会复杂很多我建议先不加NMS把检测头的原始输出拿到后处理里自己写NMS这样每一步都可控。3.2 ATC模型转换最核心的一步参数必须逐项吃透ATCAscend Tensor Compiler是把ONNX转成OM格式的工具。转好的OM模型才是昇腾芯片真正能加载执行的格式。这一步的命令和参数直接决定你后面推理能不能跑、跑多快。核心转换命令如下atc --modelyolov5s.onnx \ --framework5 \ --outputyolov5s_bs1 \ --input_shapeimages:1,3,640,640 \ --soc_versionAscend310P3 \ --logerror \ --precision_modeallow_fp32_to_fp16参数说明--framework5固定表示输入是ONNX模型。--input_shape指定输入的name和shape。这里的images必须跟ONNX模型里的输入名完全一致可以通过打印ONNX节点信息确认。--soc_version这是不能写错的一个参数。它告诉编译器目标芯片型号。我试过写不对的话会报不支持的SoC版本错误。怎么确认自己的SoC版本运行npu-smi info输出里的Chip Version一栏就是比如我这张卡显示的是310P3对应参数就是Ascend310P3。--precision_modeallow_fp32_to_fp16允许模型里的FP32算子转成FP16执行。这个参数加上以后模型占用的内存和计算量都会下降但个别算子转成FP16后可能出现精度损失如果后处理时发现检测框偏移尝试换成 --precision_modeforce_fp32看看是不是精度问题。如果模型里有ATC不认识的算子转换会报错并给出具体的算子名。我的处理办法是先把报错截图记下来去昇腾社区查这个算子是否支持不支持就回到PyTorch侧把模型里的对应模块替换掉或者用自定义算子包。曾经遇到过一个实例YOLOv8的高版本导出ONNX里有个特殊实现的自定义算子ATC不认最后我把检测头部分的算子换成标准卷积加Sigmoid才通过。转换成功后会生成yolov5s_bs1.om文件还会打印出模型的OP数量、算力预估等统计信息。这时候可以先跑一下ATC自带的校验工具om验证确认模型能在NPU上正常加载。3.3 量化到INT8要不要做什么时候做这里要先说清楚ONNX转出来的OM默认可能是FP16也能跑但推理卡最大的优势在INT8。昇腾芯片的INT8算力往往是FP16的几倍所以想要发挥这张卡的真实性能量化基本是必经之路。CANN官方提供了一套模型压缩工具包叫AMCTAscend Model Compression Toolkit可以做PTQ训练后量化。流程大致是先用原始OM模型在少量样本上做推理收集每层激活值的分布然后根据分布确定量化参数最后生成量化后的部署模型。这个过程不需要重新训练但需要准备几百张到上千张代表真实场景的图片图片分布最好贴近线上数据否则量化后精度可能掉得很厉害。实际操作时我先把FP16 OM在测试集上跑出一个基准mAP然后做PTQ量化再跑一遍对比。YOLOv5s量化后精度损失通常能控制在1-2个点以内但换个没见过的场景可能会掉3个点以上。如果你的业务对框的精度极其敏感比如工业质检里的缺陷检测建议先在验证集上量化校准完跑一遍完整评测再上线。另外量化之后模型大小也会明显减小显存占用更低单卡可以常驻更多模型。3.4 pyACL推理代码骨架拿过来能跑的版本模型转换完之后就是写推理代码。昇腾官方推荐的方式有C ACL和pyACL对快速验证来说pyACL更顺手。核心流程不复杂初始化ACL、设置设备、加载模型、准备输入输出、执行推理、取回结果。下面是我整理的最小可运行骨架。import numpy as np import acl # 初始化ACL acl.init() # 设置使用0号设备 ret acl.rt.set_device(0) # 创建Context context, ret acl.rt.create_context(0) # 加载OM模型 model_path byolov5s_bs1.om model_id, ret acl.mdl.load_from_file(model_path) # 获取模型输入输出描述 input_desc acl.mdl.create_desc() output_desc acl.mdl.create_desc() acl.mdl.get_input_desc(input_desc, model_id, 0) acl.mdl.get_output_desc(output_desc, model_id, 0) input_size acl.mdl.get_desc_size(input_desc) output_size acl.mdl.get_desc_size(output_desc) # 分配Device内存 input_buffer, ret acl.rt.malloc(input_size, 2) # 2表示普通内存 output_buffer, ret acl.rt.malloc(output_size, 2) # 假设你已经把图像预处理成1,3,640,640的float16数组 input_data np.random.randn(1, 3, 640, 640).astype(np.float16) # 将输入数据拷贝到Device内存 ret acl.rt.memcpy(input_buffer, input_size, input_data.tobytes(), input_size, 1) # 执行推理 ret acl.mdl.execute(model_id, [input_buffer, input_size], [output_buffer, output_size]) # 取回输出 output_data np.zeros(output_size, dtypenp.uint8) ret acl.rt.memcpy(output_data.tobytes(), output_size, output_buffer, output_size, 2) # 解析输出这里按YOLOv5的输出格式做后处理 output_np np.frombuffer(output_data, dtypenp.float16).reshape((1, 25200, 5 num_classes)) # 清理资源 acl.rt.free(input_buffer) acl.rt.free(output_buffer) acl.mdl.unload(model_id) acl.rt.destroy_context(context) acl.finalize()这段代码离生产还差很远但作为验证模型能不能跑通的骨架已经够了。有几个细节值得注意输入数据必须是模型要求的精度。FP16模型就需要先把图像转成float16用float32往往会报内存大小不匹配或者干脆得到全零输出。memcpy的方向参数1表示H2DHost到Device2表示D2HDevice到Host这个很容易写反。图像预处理最好在代码里跟训练时保持一致包括resize方式、归一化公式、RGB通道顺序。我遇到过模型输出完全乱掉的情况排查半天发现是BGR和RGB的问题YOLOv5官方实现里图像是RGB还是BGR跟着训练代码走导出ONNX后预处理必须保持一致。3.5 性能测试和优化思路给个参考范围模型跑通之后下一步就是压性能。我以YOLOv5s、640x640输入、batch1、FP16模式为例在Atlas 300V 24G上的实测结果大概是单帧10-15毫秒这个量级换算过来就是每秒60-100帧左右。INT8量化后延迟会更低大约能提升40%-60%但要看你模型本身的算子和量化效果。注意这个数据只是参考不同CANN版本、不同batch、不同输入尺寸都会影响结果在你自己机器上重新测一遍才靠谱。性能优化有几个方向按性价比排序第一个是固定shape和固定batch这在上面的ATC命令里已经体现。batch从1加到4或8虽然单帧延迟略增但吞吐量几乎线性提升非常划算。第二个是启用多Stream并行一张卡可以创建多个推理流把预处理、推理、后处理串成流水线CPU和NPU能同时干活。第三个是避免在Python侧做太多逐帧同步等待用异步接口把请求发出去再批量收结果Python的GIL在这种场景下影响反而没那么大因为真正的耗时在C侧执行。还有个小技巧图片缩放和归一化可以放到AIPPAscend Image Preprocessing里做ATC转换时通过配置档把预处理算子直接编进OM模型里。这样输入侧只需要把原始图像以NV12或RGB格式拷进Device内存NPU自动完成resize和归一化CPU这边的预处理开销直接省掉。配置AIPP需要编写一个aipp.cfg文件内容大致如下aipp_op { aipp_mode: static input_format: RGB888_U8 src_image_size_w: 640 src_image_size_h: 640 csc_switch: false rbuv_swap_switch: false min_chan: 0 matrix_r0c0: 1 matrix_r0c1: 0 matrix_r0c2: 0 matrix_r1c0: 0 matrix_r1c1: 1 matrix_r1c2: 0 matrix_r2c0: 0 matrix_r2c1: 0 matrix_r2c2: 1 input_origin: 0 }这只是一个简化示例实际配置要对照你的预处理逻辑调整。AIPP配好之后Python侧就少一大块工作线上稳定性也会好不少。4. 踩坑实录驱动、转换、推理三类问题一次说透4.1 设备初始化和驱动相关的坑别一上来就怀疑卡坏了最常见的第一类问题就是装完驱动之后npu-smi info看不到卡或者看到卡但状态异常。我第一次遇到时也怀疑是卡坏了后来排查下来其实是主板BIOS的Above 4G Decoding没开地址空间映射失败导致驱动初始化不了。所以按顺序检查先看lspci能不能发现设备再看BIOS选项是否正确开启最后才重新安装驱动。驱动版本和固件版本不匹配也会导致诡异问题。比如我早期驱动日志里会有Load fw failed这类信息npu-smi里卡的运行状态一直是Fault重启多少次都没用。最终解决方法是把驱动、固件、CANN全部卸载干净然后按官方配套关系重新装同一批次的包。卸载命令如下/usr/local/Ascend/driver/uninstall.shCANN工具包卸载可以直接用软件包自带的uninstall脚本或者手动删除/usr/local/Ascend目录再清理环境变量。注意卸载前先停掉所有使用NPU的容器和进程不然会有内存碎片残留。另外还有一类设备问题发生在多卡机器上。如果你服务器插了两张卡而每张卡的算力芯片版本不完全一致ATC转换时要针对每张卡单独指定soc_version推理时也要用acl.rt.set_device指定卡号。默认device 0如果不指定就只跑第一张卡负载全部压在一块卡上。4.2 模型转换和推理结果相关的坑十有八九是预处理模型转换阶段的报错大多数集中在算子不支持、shape不匹配、SoC版本写错这三类。算子不支持的老实去查算子表能换就换shape不匹配检查输入名和维度SoC版本写错就对着npu-smi info的Chip Version抄一遍。推理结果不对比如框的位置偏了、置信度全是0、输出NaN大概率不是模型转换的问题而是预处理和后处理没对齐。我整理了一个排查顺序1. 通道顺序对不对RGB/BGR 2. 归一化方式对不对0-1还是-1到1 3. resize方式是不是和训练时一致letterbox还是直接拉伸 4. 模型输出精度是不是正确FP16还是FP32解析 5. 后处理的缩放系数是不是640x640对应的曾经有一次检测框全部偏在图像左上角排查下来是resize时没有做letterbox把原始图像直接拉伸到640x640改变了目标的长宽比导致框位置偏移。这种问题在代码里看着完全不显眼但推理结果就是莫名其妙。4.3 常见问题速查表粘贴到你的运维手册里问题现象可能原因解决方法npu-smi info 找不到设备系统没识别硬件/驱动未加载查lspci确认卡在总线上重新安装驱动npu-smi 显示设备Fault驱动固件版本不匹配卸载后重新装配套的驱动固件包ATC转换报SoC版本错误--soc_version写错用npu-smi info查Chip Version后重填ATC转换报算子不支持模型里有昇腾不支持的算子替换或移除该算子或升级CANN版本推理结果全零/NaN输入精度/预处理不一致检查float16/float32、RGB/BGR、归一化推理时报显存不足静态内存分配不够调大模型转换时的memory分配参数或减小batch容器里看不到NPU设备Docker运行时不是昇腾runtime用昇腾容器镜像和正确的--device参数启动多卡负载不均衡没有指定设备ID代码里用acl.rt.set_device切换设备号这张表其实是我从自己笔记里整理出来的每一条都真实踩过。如果做大规模部署建议把它扩展到具体环境和版本文档里能省掉很多重复排查时间。5. 一些压箱底的经验用Atlas 300V 24G跑YOLO这段时间最大的感受是这张卡本身不复杂复杂的是围绕它的软件链路。一旦把驱动、CANN、OM转换这套流程跑顺后续跑新模型就是流水线作业。如果你刚开始接触我的建议是先别急着上量化、AIPP这些进阶功能。第一步用FP16精度、固定shape、PyACL最小代码把模型跑通确认每个环节的输出都对然后再逐步加batch、加量化、加AIPP。每加一个优化点都重新测一遍精度和性能出了问题也能快速定位到是哪一步引入的。最后分享一个小经验CANN的版本发布说明一定要留好每次升级环境之前先在测试机上完整跑一遍回归确认转换后模型精度和性能不降级再上生产。我遇到过CANN小版本升级之后同一个OM模型推理结果出现细微差异的情况后来靠对比版本发布说明和回归测试才意识到是工具链行为变化。所以生产环境一旦稳定不要频繁升级工具链稳定压倒一切。
返回列表