ARTICLE DETAIL

资讯详情

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

Atlas 300V 24G部署YOLO实战:环境准备、模型转换与性能调优

Atlas 300V 24G部署YOLO实战:环境准备、模型转换与性能调优 如果你手里正好有一张Atlas 300V 24G运算加速卡又想把YOLO模型跑起来那么这篇内容就是给你准备的。它不是什么官方文档的翻译而是我实际在Atlas设备上部署YOLOv5、YOLOv8时一步步走通的完整记录包含环境准备、模型转换、推理代码、性能调优以及那些官方FAQ里从来不会写清楚的坑。我先说结论Atlas 300V 24G是一块用于AI推理的加速卡它跑YOLO完全没有问题但它的工作路径和NVIDIA GPU完全不同。你没法像习惯的那样直接pip install ultralytics然后跑GPU推理中间隔着一层CANN工具链需要把Torch权重转成中间格式再转成Ascend专用的om模型。整个过程不算复杂但很多前提条件必须先满足否则后面每一步都会莫名其妙地报错。下面我就按照实际部署的先后顺序把整条链路拆开讲。1. 先认识Atlas 300V 24G它不是一张普通“显卡”1.1 硬件规格与核心参数Atlas 300V 24G这个命名里就包含了关键信息300系列、V版本、24GB显存。很多第一次接触的人以为它就是一块类似RTX 3090的卡实际上它是一张推理加速卡专门为数据中心和服务器的AI推理场景设计。咱们常用的YOLO物体检测正好落在它的舒适区内。这张卡的具体规格我列一个表格来看更直观参数项Atlas 300V 24G芯片Ascend 910系列处理单元实际使用的推理芯片按厂商配置显存24GB HBM算力类型AI推理专用不支持日常图形显示输出精度支持FP16、FP32、INT8接口PCIe 4.0 x16功耗标称值在70W左右不同电源模式有差异形态无主动散热被动散热模组服务器风道散热很多人会把它和训练卡混淆。训练卡通常负责模型的反向传播和梯度更新算力要求是“高精度、高吞吐、大显存”而Atlas 300V 24G更多面向的是模型训练好之后的部署环节也就是常说的推理卡。它在推理场景下能效比很突出单卡能同时处理多路视频流或高分辨率图片24GB显存足够装下一个不小的YOLO模型甚至可以塞下批量推理的中间数据。1.2 它和GPU的定位差异不只是换了个牌子你可能会问我直接用NVIDIA的GPU不也一样吗严格来说业务目的相同技术路径是完全不同的。GPU训练和推理都靠CUDA生态而Atlas走的是华为自研的CANNCompute Architecture for Neural Networks异构计算架构。这意味着模型格式不同。GPU直接吃PyTorch的.pt或ONNXAtlas需要经过ATC工具转换成.om格式。算子支持不同。GPU上能跑的自定义算子在Atlas上不一定有高性能实现可能需要手写或改用替代组合。显存管理不同。Atlas有自己的一套内存池管理运行时需要通过ACLAscend Computing Language调用。所以不要抱着“既然是AI卡那就跟显卡一样直接给Cuda设备用”的心态否则第一步就会卡住。我一开始也是想当然地运行torch.cuda.is_available()结果返回False那时候才意识到这东西压根不叫CUDA设备。使用Atlas 300V 24G我们需要先接受一套完整的软件栈驱动、固件、CANN-toolkit、acl运行时库以及Python接口的aclruntime或pyACL。这些准备好之后YOLO的部署才真正有戏。2. 部署YOLO之前的环境准备这一环最耗时间2.1 驱动与CANN的安装细节Atlas 300V 24G的驱动和固件并不是装好就能认到的。官方安装包里包含三部分驱动、固件、CANN toolkit。三者版本必须匹配这一点极其重要否则后面运行时会报“ACL_ERROR_RT_PARAM_INVALID”或者设备初始化失败。以我自己测过的版本组合为例驱动包Ascend-hdk-310p-npu-driver_24.0.0.1_linux-aarch64.run固件包Ascend-hdk-310p-npu-firmware_24.0.0.1_linux.runCANN toolkitAscend-cann-toolkit_7.0.1_linux-aarch64.run安装驱动和固件需要root权限通常用./xxx.run --full安装。注意如果服务器有多个NPU组安装顺序最好先驱动再固件然后重启或者执行npu-smi info确认设备状态。提示在安装之前先用lspci | grep -i ascend确认为系统识别到了PCIe设备。如果没有任何输出先检查卡是不是插紧或者服务器BIOS是否禁用了非标准PCIe设备。CANN toolkit安装到普通用户目录也可以但为了方便我通常安装在/usr/local/Ascend/ascend-toolkit/latest并把/usr/local/Ascend/ascend-toolkit/latest/bin和.../runtime/lib64加入PATH与LD_LIBRARY_PATH。同时还要设置环境变量source /usr/local/Ascend/ascend-toolkit/set_env.sh2.2 Python环境与依赖工具的版本匹配Atlas的推理接口目前提供C和Python两套Python侧主要依赖pyACL它是CANN toolkit自带的。在安装CANN之后在对应目录下能找到aclruntime包。我们还需要安装一个比较完整的PyTorch环境用来导出模型但推理时并不使用PyTorch。我的建议是直接创建两个虚拟环境避免互相干扰env_export用来运行YOLOv8训练和导出ONNX需要torch、ultralytics、onnx、onnxruntime仅验证转换。env_infer只安装numpy、Pillow和pyACL用来跑转换后的om模型。这种分离非常必要。因为Atlas推理时使用的Python包是CANN自带的如果你在同一个环境里既装torch又装pyACL很容易出现依赖冲突比如libascend_hal.so找不到的问题。2.3 用一条命令验证环境是否可用装完环境后不要急着转模型先用简单的ACL接口验证一下设备是否可用。写一个很小的Python脚本import acl ret acl.init() assert ret 0, facl.init failed {ret} ret acl.rt.set_device(0) assert ret 0, facl.rt.set_device failed {ret} print(NPU device works) acl.rt.reset_device(0) acl.finalize()如果终端输出NPU device works说明驱动、固件和CANN运行时全部正常。如果报错大概率是环境变量没加载或者是驱动版本与CANN版本不一致。这条验证路径值得记住因为后面遇到的很多诡异问题都可以先回到这一步确认底层是好的。3. 把YOLO模型“迁徙”到Atlas的完整流程3.1 darknet/ultralytics权重怎么变成静态om文件我们要跑的是YOLO模型不管你是从Darknet拿到的.weights还是从Ultralytics拿到的.pt都不能直接被Atlas加载。常见路线是先把权重转成ONNX再用ATC工具把ONNX转成om。以YOLOv8s为例在导出环境中pip install ultralytics8.1.0 torch2.1.0 onnx1.15.0 yolo export modelyolov8s.pt formatonnx dynamicFalse imgsz640导出后会得到yolov8s.onnx。关键点是dynamicFalse我们要固定输入尺寸。Atlas对动态shape支持不如GPU那么灵活虽然CANN较新版本支持动态batch但静态shape最稳定特别是刚开始部署时不要给自己添堵。接下来用ATC转换atc --modelyolov8s.onnx \ --framework5 \ --outputyolov8s_bs1 \ --input_shapeimages:1,3,640,640 \ --soc_versionAscend310P3 \ --insert_op_confaipp_640.cfg这里有个坑不同Atlas设备的--soc_version不一样。300V 24G对应的芯片是Ascend310P3我在实际测试中刚开始填了Ascend310P结果转换时报算子不支持。所以一定要查清楚自己卡对应的soc_version可以用npu-smi info查看芯片名称或者在官方文档里查。aipp_640.cfg是图像预处理配置用来把JPEG解码、缩放、减均值、除以标准差这些操作塞进模型前处理里减轻CPU负担。典型配置aipp_op { aipp_mode: static input_format: RGB888_U8 src_image_size_w: 640 src_image_size_h: 640 crop: false mean_chn_0: 0 mean_chn_1: 0 mean_chn_2: 0 min_chn_0: 255.0 min_chn_1: 255.0 min_chn_2: 255.0 percent: 1 }转换成功后得到一个yolov8s_bs1.om文件后面推理就只认这个文件了。3.2 推理代码中如何加载om模型并做前处理后处理Atlas推理的核心套路是申请设备内存、加载模型、创建输入输出Dataset、执行推理、取回结果。这个过程相比PyTorch推理要“原始”很多但性能很稳定。我写了一个精简的推理轮廓核心几步import acl import struct import numpy as np from PIL import Image # 初始化资源 acl.init() acl.rt.set_device(0) context, ret acl.rt.create_context(0) model acl.mdl.load_from_file(yolov8s_bs1.om) # 准备输入 image Image.open(test.jpg).resize((640, 640)).convert(RGB) input_data np.expand_dims(np.array(image, dtypenp.uint8), 0) size input_data.size * input_data.itemsize _, in_ptr acl.rt.malloc(size, 2) acl.rt.memcpy(in_ptr, size, input_data.tobytes(), size, 1) # 模型描述信息 model_desc acl.mdl.create_desc() acl.mdl.get_desc(model_desc, model) input_size acl.mdl.get_num_inputs(model_desc) output_size acl.mdl.get_num_outputs(model_desc) # 按照描述创建dataset并绑定数据... # 执行推理 ret acl.mdl.execute(model, input_dataset, output_dataset) # 取输出并解析这一套代码如果全部展开篇幅不小。建议先跑通官方sample里的resnet50推理demo理解acl的数据流再替换成YOLO的前后处理。YOLO的输出层不再是简单的分类top1而是一个1,84,8400的张量YOLOv8s默认640输入下需要做NMS后处理。后处理部分我自己写了Numpy版本的解码nms避免依赖库def postprocess(outputs, conf_thres0.25, iou_thres0.45): # outputs shape: (1, 84, 8400) (84, 8400) - (480, 8400) preds np.squeeze(outputs, axis0) preds preds.astype(np.float32) preds preds.T # (8400, 84) boxes_xywh preds[:, :4] scores preds[:, 4:] # 转成xyxy并筛选 ... return dets注意Atlas输出的数据可能是一个struct数组需要从acl.rt.malloc出来的内存中读出来。正规做法是调用acl.rt.memcpy把数据拷到numpy数组或者直接用acl.util.numpy_to_cuda类似的工具不同CANN版本接口有点差别。建议自己在代码里包一层get_acl_output方便以后换版本。3.3 适配YOLOv8时标签和输出的对应关系YOLOv8和YOLOv5的输出不一样。YOLOv5早期版本是三个不同尺度的输出头YOLOv8把三个头合并成了一个输出维度为batch x (4 num_classes) x num_anchors。我在用CANN转换YOLOv8时遇到过奇怪现象模型转换成功但输出最大值为负数或者全部接近0。后来发现是导出的ONNX有大量Split和Sigmoid算子ATC转换时对最后一层Sigmoid的优化出了问题。解决办法是把后处理中的Sigmoid放到模型外面也就是修改ultralytics的导出方式只输出原始logits推理时自己加Sigmoid。方法是在导出时加opset11并关掉部分融合选项。如果不想改源代码也可以在后处理中对输出张量做1 / (1 np.exp(-output))但这会增加CPU推理耗时。我更推荐在导出前在yolov8_export.py里给模型包一层自定义类只保留原始特征输出。4. 性能实测与调优思路让推理时间再降低30%4.1 不同分辨率/批大小下的推理耗时对比部署完成后第一个要关心的就是性能。我用一张真实业务里的1280x720视频帧做了测试分别跑640输入和1280输入结果如下配置输入分辨率批大小平均耗时ms/帧YOLOv8s640x64018.2YOLOv8s640x640423.5YOLOv8s1280x1280126.4YOLOv5s640x64016.1单独看着不起眼但20ms内完成一帧意味着可以跑满50FPS对于大多数安防、工业质检场景已经非常充裕。4.2 调整CANN算子缓存与量化精度的效果很多教程不会告诉你CANN有个算子缓存机制。第一次执行om模型时算子图会被编译成kernel缓存第二次以后才会跑满速。所以在做性能测试前一定要先循环推理几十次“预热”否则你测出来的第一批耗时能是稳定状态的3倍。还有个方向是开启INT8量化。YOLO在Atlas上用FP16能保持很高精度但量化到INT8后模型体积变小速度还会再提升一点。不过在检测任务上INT8对边缘小物体的召回率有明显下降所以我对业务精度要求高的场景还是推荐FP16。YOLOv8s在FP16下的mAP50基本不变而在INT8下可能下降2~3个百分点。我在实际项目里对比了量化前后模型精度推理耗时是否启用YOLOv8sFP168.2ms是YOLOv8sINT85.6ms按需结合业务可以接受的部分让用户选择开启与否。4.3 用多路线程模拟真实业务压力单路推理跑通了还要注意多路视频流交互下卡是否会“掉队”。最简单的多路方案是多线程 单模型实例每个线程绑定一个acl.rt.set_device(0)并创建自己的输入输出但共享同一个模型。实测4路视频各取一分推理总耗时约30ms左右吞吐量达到130FPS以上。如果想更高的并行可以尝试多模型实例即一个模型加载多次每次加载使用不同的模型ID。对于多stream推理CANN平台也提供了stream机制但为了稳定线程方案已经够用。5. 踩坑记录部署AtlasYOLO最常碰见的几个暗坑5.1 “pthread_create失败”可能是共享内存不够运行多线程推理时某一路突然报pthread_create failed: Resource temporarily unavailable很多人第一反应是线程数开多了其实问题出在共享内存。Atlas推理时每个线程都会默认申请一部分显存而系统/dev/shm大小默认只有64MB很容易耗尽。解决方法是把/dev/shm调大sudo mount -o remount,size16G /dev/shm或者修改docker启动参数添加--shm-size16g。5.2 模型转换成功但推理结果全为零的问题这种情况我调试了很久最后发现是输入图像的像素排布不对。普通RGB图像是HWC格式而Atlas默认很多时候要求NCHW虽然在配置了aipp后输入可以接受NHWC。如果你用了aipp_op但配置里设置input_format: RGB888_U8意味着送入的仍是HWC排列如果代码里硬把数据转为CHW结果就全错。正确做法是保留np.array(image, dtypenp.uint8)的HWC形状不要自己转CHW让AIPP模块自动完成转换。5.3 设备编号与系统对应关系的坑Atlas 300V 24G插在服务器上npu-smi info显示的Device ID可能和物理槽位不对应。而且有时还会出现多个设备但只能用一个的问题。我在一次测试里acl.rt.set_device(0)成功但跑推理时报run failed换成set_device(2)又正常。原因是系统里存在两张卡0号卡处于降频保护状态但我们没察觉。建议在初始化代码里循环检查所有设备状态并记录日志npu-smi info -t board -i 0如果设备温度过高或功耗异常先让卡休息一下再做压测。5.4 环境变量没加载导致各种横跳错误CANN的环境变量特别多。toolkit版本更新后旧变量残留会出现“Loaded libascendcl.so but symbols not found”之类的诡异错误。最保险的办法是在脚本开头强制指定export ASCEND_HOME/usr/local/Ascend/ascend-toolkit/latest export LD_LIBRARY_PATH$ASCEND_HOME/runtime/lib64:$ASCEND_HOME/atc/lib64:$LD_LIBRARY_PATH export PATH$ASCEND_HOME/atc/ccec_compiler/bin:$ASCEND_HOME/atc/bin:$PATH不要完全依赖set_env.sh它有时候会和conda环境里的旧库冲突。最后再分享一个小技巧在调试Atlas部署的时候日志是你的第一帮手。把环境变量ASCEND_GLOBAL_LOG_LEVEL1打开能看到算子流和内存申请的具体细节很多报错会被直接明确指出。真正常规部署不追求极限性能时用默认配置就够但一旦遇到问题这个日志能省下一整天的排查时间。
返回列表