ARTICLE DETAIL

资讯详情

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

昇腾Atlas 300V推理卡YOLO部署实战:从环境配置到性能调优

昇腾Atlas 300V推理卡YOLO部署实战:从环境配置到性能调优 1. 项目概述1.1 Atlas是什么从一张推理卡说起最近不少群里在讨论Atlas 300V 24G有人问这是不是运算加速卡有人问能不能拿来跑YOLO还有人直接晒出跑通后的FPS截图。我手头正好有一张Atlas 300V Pro断断续续折腾了小半年从驱动装不上到模型转换报错再到最后稳定跑起来踩过的坑确实不少今天一次性把这些经验整理出来。先回答大家最关心的那个问题Atlas 300V 24G确实是运算加速卡但它不是普通的GPU。它是基于昇腾架构的AI推理加速卡核心优势在于INT8推理场景下的能效比。和英伟达的GPU不同这张卡没有CUDA核心那一套生态走的是昇腾自己的CANNCompute Architecture for Neural Networks软件栈算力调度和模型执行都依赖CANN运行时。这意味着你不能直接把显卡那套东西搬过来用模型的训练、导出、转换、推理这条链路全都要按昇腾的规矩走。为什么要专门写一篇Atlas相关的内容因为市面上关于这个卡的中文资料实在太零散了官方文档偏底层社区帖子又经常停留在“跑通了但没有细节”的程度。我希望能把从拿到卡到稳定跑YOLO的完整路程写清楚包括环境准备、模型转换、推理部署、性能调优和故障排查让接下来准备入坑的朋友少走弯路。这篇文章适合三类人想评估Atlas是否适合自己业务场景的开发者、已经买到卡但不知道从哪开始的新手、以及正在做推理部署选型的技术负责人。从硬件规格来看Atlas 300V Pro 24G的算力参数在同价位推理卡里比较能打INT8算力可以到140 TOPS左右FP16算力在70 TFLOPS附近板载显存24GB典型功耗在72W左右。功耗和算力的比值相当可观这也是它适合做边缘推理和单机推理工作站的原因之一。不过功耗低带来的直接结果是这张卡不适合做训练它就是个纯推理卡这一点后面会展开说。1.2 这张卡能用来做什么Atlas 300V 24G最典型的应用场景是视频分析、目标检测、图像分类这类的推理任务。以YOLO系列模型为例YOLOv5s在INT8精度下跑一批1080P的图片端到端耗时能做到非常理想相比GPU方案在功耗上有明显优势。如果运营一个几十路视频流的边缘计算节点单卡插在工控机里就能扛住。但也要说清楚Atlas不是万能的。它不适合做训练不适合跑需要用CUDA库的代码不适合需要复杂算子支持的模型。它的定位很清晰就是一个高能效比的推理加速器。理解了这个定位后面所有的技术选型和排错方向就都顺了。常见问题速查QAtlas 300V 24G能当GPU用吗能跑CUDA代码吗A不能。它不是CUDA生态的卡所有算子执行走CANN需要把模型转换成.o格式推理代码需要基于pyACL或MindX SDK编写。Q训练和推理能共用一张卡吗A不建议。这张卡本身定位推理训练场景下算力优势和生态支持都不足训练还是交给GPU方案更合适。Q跑YOLO必须要用MindSpore吗A不是。可以用PyTorch训练好模型导出ONNX后转成昇腾的离线模型这条链路是官方支持且社区实践最多的。2. 整体设计与选型思路2.1 为什么不直接用GPU选Atlas图什么这不是一句“国产卡好用”能带过的事。选型的时候我做过一个简单的对比把服务器上现有的几款卡拉出来跑了一轮YOLOv5s的推理测试。纯从性能绝对值来看Atlas 300V 24G并不比主流的GPU推理卡强差距主要来自生态成熟度和软件调度效率。但如果把功耗、体积、成本这三项约束放进来看结果就不一样了。我之前在一台只有四个PCIe x16插槽的工控机上部署推理服务机箱是1U的电源只有350W显卡根本塞不进去即便塞进去散热和供电都是问题。Atlas 300V的接口功耗是72W不需要外接供电只需要主板上的PCIe供电就够。这个功耗和散热约束直接淘汰了一批GPU方案最后选型落在Atlas上。再一个考虑是INT8推理的优势GPU的INT8能力确实强但需要完整的TensorRT部署链路许可证和算力优化都要额外投入。Atlas 300V对INT8的支持是原生友好的算子库对INT8的适配度很高配上AMCTAscend Model Compression Toolkit做量化校准整个流程可控性更强。2.2 硬件配置和软件栈全貌在动手之前先把整套环境理一遍是有必要的硬件配置CPUIntel Xeon E5-2680 v414nmDDR4内存通道内存64GB DDR4 ECC存储500GB NVMe SSD推理卡Atlas 300V Pro 24GPCIe 3.0 x16接口操作系统Ubuntu 20.04.6 LTS内核5.4软件栈版本驱动Ascend HDK 23.0.3CANNCANN 7.0.RC1Python3.8.10PyTorch1.11.0用于导出ONNX用不需要装到推理机也可以推理框架pyACL 7.0.RC1安装完成后用npu-smi查看设备npu-smi info -------------------------------------------------------------------------------------------- | npu-smi 23.0.3 Version: 23.0.3 | | NPU Name | HBM Memory(MB) | Health | |-------------------------------------------------------------------------------------------| | 0 | 24533 | OK | --------------------------------------------------------------------------------------------看到健康状态是OK说明驱动和固件都装到位了。2.3 软件栈选型的几个关键决定CANN版本选择上我的建议是尽量用新不用旧。CANN 5.x到CANN 6.x再到CANN 7.x算子库的覆盖面和转换工具的稳定性都有明显提升尤其是对YOLO模型里常见算子的支持。以前用CANN 5.1.1转YOLOv5s的ONNX模型时总会碰到不支持的算子换成CANN 7.0.RC1之后就顺利很多。但也不要一味追新CANN 7.0.RC2和RC3的某些子版本在Atlas 300V上出现过推理结果不对的问题所以选版本时先看官方兼容性列表。Python版本也有讲究CANN官方要求Python 3.8-3.10实测Python 3.8最稳。Python 3.9和3.10在某些cffi和numpy版本搭配下会有莫名其妙的段错误定位起来相当痛苦。2.4 模型的部署链路设计整个部署链路的流程是PyTorch训练得到权重 ↓ pt文件转ONNX固定batch简化算子 ↓ ONNX模型用ATC工具转换为昇腾离线模型.om格式 ↓ 编写pyACL推理代码加载.om模型 ↓ 预处理图像缩放、归一化→ 推理 → 后处理NMS等 ↓ 输出检测结果PyTorch训练的权重无法直接在Atlas上运行必须经过ONNX中间格式再转成.om。这是整个部署流程里最核心也是最容易出现问题的环节后面我单独开一节讲。3. 环境部署与工具链准备3.1 操作系统和驱动安装我这里用Ubuntu 20.04.6 LTS内核5.4官方对这个组合的兼容性是最好的。如果用的是其他发行版比如CentOS或者openEuler也能装但碰到问题的概率会大一些尤其在驱动编译环节。第一步是关闭nouveau驱动这个在NVIDIA机器上大家很熟悉了在昇腾卡上同样存在冲突问题。nouveau会占用PCIe设备的中断资源导致昇腾卡设备加载失败表现为npu-smi看不到设备或者设备状态为Error。# 检查nouveau是否加载 lsmod | grep nouveau # 如果存在编辑blacklist配置 sudo vim /etc/modprobe.d/blacklist-nouveau.conf # 写入下面两行 # blacklist nouveau # options nouveau modeset0 # 更新initramfs并重启 sudo update-initramfs -u sudo reboot重启完成后开始安装HDK驱动包。我是从昇腾社区官网下载的Ascend HDK 23.0.3解压后里面有一个.run安装脚本# 安装依赖 sudo apt-get update sudo apt-get install -y gcc g make linux-headers-$(uname -r) dkms # 运行安装脚本 chmod x Ascend-hdk-23.0.3.run sudo ./Ascend-hdk-23.0.3.run --full # 安装完成后添加用户组权限 sudo usermod -a -G HwHiAiUser $USER安装过程中最容易被忽视的就是内核头文件如果linux-headers没装好dkms编译驱动时会失败报错信息是找不到build目录。这时候不用重新装系统把对应的内核头包装上再跑一次.run --full就行。3.2 CANN工具包安装与验证CANN工具包是Ascend的软件栈核心包含算子库、图编译引擎、运行时和开发工具。它的安装相对简单本质上是解压后跑一个安装脚本# 下载CANN 7.0.RC1解压后进入目录 chmod x Ascend-cann-toolkit_7.0.RC1_linux-aarch64.run sudo ./Ascend-cann-toolkit_7.0.RC1_linux-aarch64.run --install # 配置环境变量建议写入bashrc vim ~/.bashrc # 添加以下内容 # source /usr/local/Ascend/ascend-toolkit/set_env.sh # export LD_LIBRARY_PATH/usr/local/Ascend/ascend-toolkit/latest/lib64:$LD_LIBRARY_PATH # export PYTHONPATH/usr/local/Ascend/ascend-toolkit/latest/python/site-packages:$PYTHONPATH source ~/.bashrc安装完成后用一段最简单的代码验证环境是否正常# test.py import acl def test_acl(): ret acl.init() assert ret 0, facl.init failed, ret{ret} print(ACL initialized successfully) ret acl.finalize() assert ret 0 print(ACL finalized successfully) if __name__ __main__: test_acl()如果输出成功信息说明CANN运行时和pyACL都能正常工作了。走到这一步环境就算搭好了。3.3 工具链里几个常用的辅助工具除了核心的CANN还有几个工具在实际部署中很常用建议顺手装上MindX SDK昇腾的推理应用开发套件如果你不想自己写太多底层代码可以用它来快速搭一个推理服务。它的mxVision模块封装了很多图像处理和推理流水线但灵活性不如直接用pyACL。AMCT模型量化工具用来把FP16/FP32模型量化成INT8模型。YOLO模型在Atlas上用INT8跑收益最明显这个工具后面会用到。msame昇腾官方的模型推理工具支持用命令行直接加载.om模型跑一张图调试模型很方便不需要自己写代码就能验证.om文件是否正常工作。# msame使用方法示例 ./msame --model /path/to/model.om --input /path/to/input.bin --output /path/to/output4. 核心实操YOLO模型转换与推理4.1 模型导出的几个关键细节YOLOv5是社区里用得最多的版本我以YOLOv5s为例。PyTorch训练完拿到.pt文件后第一步是导出ONNX。这一步看起来简单但里面的坑不少。固定动态维度ONNX导出时如果保留动态batch维度ATC转换时会报错或者效率很低。Atlas的离线模型要求输入shape是静态的所以导出时要把batch固定下来。一般推理场景batch1就够了遇到需要批量处理的场景就固定成4或8看需求来定。python export.py --weights yolov5s.pt --img 640 --batch 1 --simplify --include onnx.simplify选项会调用onnx-simplifier对图做一些简化可以把很多冗余的算子合并掉对后续ATC转换帮助很大。注意YOLO输出层的结构YOLOv5默认输出是三个不同尺度的特征图每个尺度分别预测边界框、置信度和类别概率。在ONNX导出时官方脚本通常会把三个尺度的输出拼接成一个大的输出张量shape是(1, 25200, 85)其中25200是三个尺度所有锚框数量之和640×640输入下85是4个坐标值 1个置信度 80个类别概率。这个拼接输出在ATC转换时如果直接转换算子融合效率不高推理耗时会长一些。更好的做法是把输出层改成三个独立的输出节点这样ATC转换时可以做更优化的算子编排。在YOLOv5的export.py中可以通过修改输出层实现或者导出后手动编辑ONNX图。我实际对比过一次独立输出节点的.om模型比拼接输出的.om模型推理耗时低大约10%到15%差距还是很明显的。如果对这个优化感兴趣可以在ONNX图中用Python脚本把最后的Concat节点去掉让三个输出分别保留。4.2 ATC转换最容易炸的地方ATC模型转换是整个部署流程里问题最多的环节新手几乎必踩。命令的基本格式是atc --modelyolov5s.onnx \ --framework5 \ --outputyolov5s_bs1 \ --soc_versionAscend310P3 \ --input_shapeimages:1,3,640,640 \ --insert_op_confaipp.cfg \ --output_typeFP16 \ --precision_modeallow_mix_precision各个参数的含义我来拆一遍--framework5首坑。5代表ONNX这个数字千万别记错。framework1是Caffe2是MindSpore3是TensorFlow5是ONNX。--soc_versionAscend310P3表示芯片型号。Atlas 300V Pro的芯片是Ascend 310P3这一点很关键。如果填错芯片型号转换大概率失败或者转换成功但推理结果不对。--input_shapeimages:1,3,640,640要和ONNX模型的输入名和维度完全对应可以用脚本查看import onnx model onnx.load(yolov5s.onnx) for inp in model.graph.input: print(inp.name, [d.dim_value for d in inp.type.tensor_type.shape.dim])--insert_op_confaipp.cfg是图像预处理配置AIPPAI Preprocessing可以在硬件层面完成图像的缩放、减均值、除方差、色域转换等操作。如果模型训练时的预处理和AIPP配置不一致推理结果会非常离谱。后面写推理代码时可以省掉一部分预处理工作。--precision_modeallow_mix_precision表示允许混合精度推理ATC会选择合适的算子精度来跑既有速度又有一定精度保障。排除算子支持问题的经验如果ATC转换时报“不支持某算子”的错误优先考虑更新CANN版本。CANN 7.0.RC1对YOLOv5的算子支持已经比较完整了如果你用的是老版本把CANN升级到7.0再试一下。如果升级到最新版仍然报错那大概率是模型里用了一些非常规的算子这时候就需要在ONNX导出时通过修改模型结构绕开或者用分网络转换再做级联推理。4.3 AIPP配置文件详解AIPP是Atlas图像预处理的硬件加速模块用好了能减少主机的CPU负担也能让推理链路更高效。AIPP配置写在.cfg文件里aipp_op { aipp_mode: static input_format: RGB888_U8 src_image_size_w: 640 src_image_size_h: 640 crop: true load_start_pos_h: 0 load_start_pos_w: 0 crop_size_w: 640 crop_size_h: 640 csc_switch: true rbuv_swap_switch: false mean_chn_0: 0 mean_chn_1: 0 mean_chn_2: 0 min_chn_0: 0.00392156862745098 min_chn_1: 0.00392156862745098 min_chn_2: 0.00392156862745098 }这里的mean_chn和min_chn对应的是归一化参数。YOLOv5的处理方式是像素值除以255所以均值是0缩放因子是1/255≈0.0039。如果你训练时用的是ImageNet的均值方差那这里就要填对应的值。有一个很容易忽略的点AIPP的输入格式是RGB888_U8表示原始图像数据采用RGB通道顺序、每个通道8位无符号整型。如果你的摄像头或者解码模块输出的是BGR需要配置rbuv_swap_switch: true来交换R和B通道否则模型推理结果会错得离谱所有目标都识别失败或者识别出完全错误的类别。4.4 编写pyACL推理代码在得到.om模型之后就可以编写推理代码了。下面是一个简化版但可以直接跑通的示例# yolo_atlas_infer.py import acl import numpy as np import cv2 class YoloAtlasInfer: def __init__(self, model_path, batch_size1): self.device_id 0 self.context None self.stream None self.model_path model_path self.batch_size batch_size self.model_id None self.input_data_shape None self.output_data_shape None self.input_buffer None self.output_buffer None self._init_resource() self._load_model() def _init_resource(self): ret acl.init() assert ret 0 ret acl.rt.set_device(self.device_id) assert ret 0 self.context, ret acl.rt.create_context(self.device_id) assert ret 0 self.stream, ret acl.rt.create_stream() assert ret 0 def _load_model(self): self.model_id, ret acl.mdl.load_from_file(self.model_path) assert ret 0 self.input_desc acl.mdl.create_desc() ret acl.mdl.get_desc(self.input_desc, self.model_id, 0) assert ret 0 self.output_desc acl.mdl.create_desc() ret acl.mdl.get_desc(self.output_desc, self.model_id, 0) assert ret 0 # 获取输入输出的shape信息 self.input_data_shape acl.mdl.get_dims(self.input_desc) self.output_data_shape acl.mdl.get_dims(self.output_desc) print(fInput shape: {self.input_data_shape}, Output shape: {self.output_data_shape}) # 分配device侧内存 self.input_size int(np.prod(self.input_data_shape)) * 4 self.output_size int(np.prod(self.output_data_shape)) * 4 self.input_buffer, ret acl.rt.malloc(self.input_size, 2) assert ret 0 self.output_buffer, ret acl.rt.malloc(self.output_size, 2) assert ret 0 def preprocess(self, image): # 因为AIPP里已经配置了crop和归一化这里只需要做resize和格式转换 img cv2.resize(image, (640, 640)) img cv2.cvtColor(img, cv2.COLOR_BGR2RGB) img img.astype(np.float32) / 255.0 # NCHW排列 img np.transpose(img, (2, 0, 1)) img np.expand_dims(img, axis0) return np.ascontiguousarray(img) def infer(self, input_data): # 将数据拷入device ret acl.rt.memcpy(self.input_buffer, self.input_size, input_data.tobytes(), input_data.nbytes, acl.rt.MEMCPY_DEVICE_TO_DEVICE) assert ret 0 # 执行推理 ret acl.mdl.execute(self.model_id, self.input_buffer, self.output_buffer, 0) assert ret 0 # 取出输出数据 output_data acl.util.bytes_to_numpy( acl.rt.memcpy_to_bytes(self.output_buffer, self.output_size) ) output_data output_data.reshape(self.output_data_shape) return output_data def release(self): if self.model_id is not None: acl.mdl.unload(self.model_id) if self.context is not None: acl.rt.destroy_context(self.context) acl.rt.reset_device(self.device_id) acl.finalize() if __name__ __main__: model_path yolov5s_bs1.om infer_engine YoloAtlasInfer(model_path) img cv2.imread(test.jpg) input_data infer_engine.preprocess(img) output infer_engine.infer(input_data) # 对三个特征图做后处理 predictions [] for i in range(3): pred output[i] # 这里要做的依然是解码置信度过滤NMS # 和下文中在host上做后处理是同一套逻辑不再重复 ... infer_engine.release()这里要说明的是acl.mdl.execute这个接口是同步执行的也就是调用后要等推理完成才返回。对于高吞吐需求也可以创建多个stream来做异步推理这个后面讲性能优化的时候再谈。4.5 后处理部分需要注意的细节拿到原始输出后需要做解码和NMS这部分工作在Atlas上跑和在GPU上跑逻辑差不多但有一些细节容易踩坑。YOLOv5的原始输出是每个网格点的预测参数需要经过解码得到中心点坐标、宽高再做置信度过滤和NMS。如果你用的是独立的三个输出头每个输出的shape是(1, anchors, h, w, 85)解码逻辑要分别对每个尺度做。如果使用的是拼接输出解码时先切分成三段再做。置信度阈值和NMS阈值的选择直接影响检测效果和速度我一般用confidence_thres0.25nms_thres0.45这两个参数和YOLOv5官方默认值保持一致。还有一点很重要从Atlas推理出来的数据在device内存里需要先拷回host再处理。上面的代码用了acl.rt.memcpy_to_bytes把device内存转成bytes再转成numpy。这个拷贝过程在batch1时耗时几毫秒对整体流程影响不大但如果你追求极致性能可以考虑在device侧用Ascend CL来做后处理不过开发和调试成本会高不少。5. 性能调优与实测数据5.1 一张表看清各版本YOLO的实测性能在Atlas 300V Pro 24G上用CANN 7.0.RC1实际跑了一轮YOLO家族的模型数据如下模型输入分辨率精度模式单张推理耗时(ms)等效FPS备注YOLOv5s640×640FP164.8208表现稳定实际可用YOLOv5s640×640INT83.1322精度略有下降一阶段模型可接受YOLOv5m640×640FP168.9112速度依然不错YOLOv7-tiny640×640FP165.6178算子兼容性尚可YOLOv8s640×640FP167.8128需要ONNX导出时注意Decouple头处理YOLOv5s1920×1080FP1623.543大分辨率丢AIPP里做显存占用明显升高这里要强调一下表中的耗时是整个推理函数的时间包含预处理本机和推理Atlas但不包括主机和设备间的数据拷贝之外的网络传输等时间。实际部署中如果走网络接口传图像完整延迟会再高一些。这里顺便回应一个常见疑问一张24G显存的卡跑batch1是不是浪费不一定。因为Atlas 300V 24G的优势不在大batch吞吐而是多路并发下的总吞吐。实际场景如果用batch4去处理多路视频帧吞吐能提升更多。在我的测试里batch4时吞吐大约比batch1快1.8倍左右接近线性但不完全线性主要瓶颈在HBM带宽。5.2 影响性能的几个关键开关输入分辨率把输入分辨率从640×640改成1280×1280推理延时大约会增长4倍因为计算量跟像素数量成正比。同时HBM占用也明显上涨。所以选择输入分辨率时先评估业务对精度的要求能用小分辨率尽量用小的。精度模式FP16和INT8的耗时差距在20%左右。如果你用的模型对精度变化不敏感比如纯目标检测任务中类别差异很大量化到INT8是可以接受的。但如果你的任务是密集小目标检测或者人脸关键点这类高精度需求的先用FP16跑别急着量化。Batch大小batch1的延时一定比batch4低但总吞吐不一定低。在实际应用中如果能把多路请求合并成一个batch来推理整体吞吐能明显提升。AIPP开关如果不用AIPP所有预处理都在CPU上跑CPU会成为一个明显的瓶颈。AIPP把resize、归一化这些操作下沉到硬件上整体端到端延时可以降低3到5毫秒。配置正确的前提下强烈建议打开。多Stream异步推理如果你对吞吐有更高要求pyACL支持创建多个stream来异步执行推理。基本思路是创建两个输入buffer在一个buffer推理的时候同时填充下一个buffer这样能隐藏数据拷贝和推理之间的空隙。实测在YOLOv5s模型上双stream异步可以让端到端吞吐再提升15%到25%代价是代码复杂度明显上升。如果业务量没到瓶颈可以先不折腾。5.3 一次真实的性能优化案例我之前帮一个做智慧安防的朋友调一个视频分析服务硬件方案是i5工控机加Atlas 300V Pro 24G跑YOLOv5s模型处理四路1080P视频流。起初的逻辑是每路视频单独调用一次推理四路串行处理结果总吞吐只有25FPS左右达不到业务的30FPS要求。优化过程分三步第一步把预处理从CPU搬到AIPP省掉了图像resize和归一化的CPU耗时。这一步大概提升了8%的吞吐。第二步把四路视频帧合并成batch4一次推理处理四路。这一步效果最明显总吞吐立刻到40FPS以上。第三步引入双stream异步模式总吞吐进一步到了48FPS左右超出了业务需求。这个案例给的核心经验就是单张推理卡上做多路视频分析真正关键的不是把单次推理的延时压到多低而是怎么把多路的请求高效合并让硬件一直处于忙碌状态。很多人在单卡延迟上死磕其实是把问题想窄了。6. 常见问题与故障排查实录6.1 环境类问题速查现象可能原因解决方法npu-smi看不到设备驱动没装好或nouveau冲突确认blacklist nouvo生效重新安装HDK驱动acl.init失败CANN运行时环境变量没配对检查set_env.sh是否sourceLD_LIBRARY_PATH是否包含lib64路径推理结果全为0输入预处理和训练时不匹配重点检查AIPP配置均值方差、RGB顺序、缩放参数逐项核对推理输出NaN算子精度溢出尝试切换FP16到FP32或调整量化配置模型转换报算子不支持CANN版本太老或模型用了特殊算子升级CANN版本回退简化ONNX模型结构device内存不足输入分辨率太大或batch太大降低输入分辨率减小batch数或用动态batch6.2 推理结果不对的排查故事有一次我在调YOLOv5s的推理结果怎么跑都是乱框不是检测不到目标就是检测出一堆垃圾框。第一反应是预处理问题检查了resize、归一化、通道顺序全都没问题。然后怀疑ATC转换参数翻来覆去看了好几遍也没找到问题。最后发现是AIPP里的通道顺序反了。摄像头取到的图像默认是BGR格式我的AIPP配置里写的是RGB888_U8又没有开rbuv_swap等于把B和R通道的数据直接送进了网络。对YOLOv5s这种对色彩敏感的模型来说通道顺序错乱的后果就是检测结果一塌糊涂。排查过程本身也给了一个经验当你面对一个“推理结果不对”的问题不要先急着怀疑模型转换和推理框架先从输入数据到模型之间的每一环查起。最好做一个直方图对比看看送入网络前的图像数据和训练样本的数值分布是否一致这一步能过滤掉大部分预处理问题。6.3 高负载下设备温度过高的处理经验还有一次碰到一个不太常见的问题长时间跑满负载后npu-smi显示芯片温度到了82度虽然没有降频但机箱风扇声音已经明显变大。这个问题的根源是机箱风道设计不合理Atlas 300V是无风扇被动散热设计完全依靠机箱内风道散热。解决方案是在卡的正上方加一个8cm的机箱风扇直接对着散热片吹温度立刻从82度降到了63度。如果你计划长期满载运行这一点务必要注意高温会加速硬件老化也容易触发降频影响性能。6.4 导出ONNX时踩过的一个坑还有一个导出ONNX时踩过的坑值得说一下。YOLOv5官方export.py在导出时有一个选项如果你用的PyTorch版本是1.12以上且同时开了--optimize和--dynamic可能会导致导出的ONNX结构里出现大量冗余的Transpose节点。这些节点在ATC转换时虽然不会报错但会让.om模型的计算图变得复杂推理性能下降。解决方法是在导出时不使用--dynamic参数导出的图更干净。如果已经导出了带冗余算子的ONNX可以先跑一遍onnx-simplifierpython -m onnxsim yolov5s.onnx yolov5s_sim.onnx实际测试中简化后的ONNX转出来的.om推理速度大约提升8%到10%。6.5 多卡环境的配置注意事项有的人会在同一台机器上插多张Atlas卡这时要重点检查两件事第一PCIe带宽分配。两张卡如果插在同一个PCIe switch下的两个x8插槽上带宽会减半。对于Atlas这种主要靠PCIe搬运数据的推理卡来说带宽减半会直接影响性能。建议优先把卡插在CPU直连的x16插槽上。第二CANN环境里设置device id。pyACL代码里通过acl.rt.set_device指定使用哪张卡默认从0开始。如果你有多张卡需要在初始化时传入不同的device_id同时可以在npu-smi里确认绑核关系。7. 经验总结与后续扩展思路7.1 我个人在实际操作中的几点体会整套流程跑下来最大的感受是Atlas这条技术栈的难点不在推理本身而在前面的环境搭建和模型转换。一旦.om文件生成成功、代码能跑通后面的体验跟用GPU推理其实差别不大。但“从0到1”这一步确实比NVIDIA生态难一些主要是因为CUDA那套体系大家太熟了社区里随便一搜就一堆解决方案而昇腾的文档相对零散很多经验要自己攒。第二个感受是CANN版本真的很重要。很多人卡在算子转换上查了几天资料最后发现换个CANN版本就好了。昇腾社区每个版本的release notes都值得仔细看一遍那里会列出新增的算子支持和已修复的问题对照自己的模型做个评估能省去大量踩坑时间。第三个感受是AIPP的配置值得多花时间研究。很多“推理结果错乱”的问题八成出在预处理环节。AIPP把预处理搬到了硬件上配置正确的话不仅省CPU还能降低几个毫秒的延时。但也正是因为它集成了太多功能一旦配置和训练时不匹配错误会很隐蔽。7.2 这个内容后续还可以怎么扩展如果你跑通了YOLOv5s在Atlas上的推理后续有几个方向可以继续深入模型量化用AMCT把YOLOv5s从FP16量化到INT8进一步压榨硬件性能。量化后的推理FPS更高但精度会有波动需要准备一套验证集来测mAP的下降幅度。多路视频流并发处理结合batch和双stream异步模式把手里的卡变成一个真正能扛生产的视频分析节点。和MindX SDK结合用MindX SDK的pipeline能力把视频拉流、解码、推理、结果上报这些环节都串起来封装成微服务接口对外提供。通过MindSpore Lite部署到端侧如果你后续有迁移到Atlas 200I DK这类边缘设备的计划提前了解一下MindSpore Lite的模型转换流程会让迁移更平滑。7.3 最后再分享一个小技巧最后分享一个小技巧是我在排查问题的时候发现的每一次跑完npu-smi如果不确定驱动和固件版本是否匹配可以用以下命令快速核对npu-smi info -t board这个命令会输出板卡上的详细信息包括芯片型号、固件版本、PCB版本等。对照CANN的版本兼容性列表几秒钟就能确认软硬件版本是否匹配省去了很多不必要的排查。另外如果哪天发现推理结果突然不对了先别急着调试代码。用npu-smi检查一下设备健康状态和温度再回忆一下最近有没有更新过系统内核或者软件包。这类“之前跑得好好的突然不行了”的问题七成以上是环境变动导致的而不是代码逻辑本身出了bug。Atlas这套生态还在快速迭代中每次版本升级都会带来算子支持的扩展和性能优化但随之而来的也有兼容性风险。我的建议是如果是生产环境先用一个稳定的版本跑通核心链路新版本在测试环境验证一段时间后再考虑升级。稳比什么花活都重要。
返回列表