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

资讯详情

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

Atlas 300V 24G昇腾推理卡部署YOLOv5/v8实战与避坑指南

Atlas 300V 24G昇腾推理卡部署YOLOv5/v8实战与避坑指南 翻车翻多了慢慢就摸清这张卡的脾气了。Atlas 300V 24G 最近在算法工程圈里热度不低尤其是“部署 YOLO”相关的问题隔三差五就有人问。先说结论它确实是一张运算加速卡但它不是 GPU也不是拿来跑训练的卡它是一张面向推理场景的昇腾 AI 加速卡。这篇文章我就用自己实际跑通 YOLOv5/YOLOv8 推理的经验把 Atlas 300V 24G 从硬件定位、环境部署、模型转换到推理代码、性能调优、常见坑位一次讲清楚给准备上手的朋友一份能直接照着干的笔记。1. 先回答热搜Atlas 300V 24G 到底是不是加速卡1.1 这卡的准确身份推理加速卡不是通用 GPU如果你是第一次接触昇腾产品很容易被型号绕晕。Atlas 300V 24G 全称一般是 Atlas 300V Pro 24G也有标准版 300V从产品序列看它属于 Atlas 300V 系列是华为昇腾生态里的 PCIe 推理加速卡。它采用的是昇腾 310P 系列芯片板载 24GB 显存LPDDR4X整卡功耗控制在 70W 上下属于那种“看着不起眼、算力不小、功耗很低”的卡。和 GPU 不一样的几个关键点它不能当通用 GPU 用不支持 CUDA也不能直接跑 PyTorch 的.pt模型。它主要执行的是推理计算INT8 算力很猛FP16 也支持但对于训练场景支撑很弱。软件栈是 CANN昇腾异构计算架构模型要先转成.om格式才能在上面跑。所以回到热搜问题“atlas 300v 24g 是运算加速卡吗”——是但它是专门干推理的加速卡。你要拿它做训练不能说完全不行但生态和驱动都不在那个方向上没必要给自己找罪受。明确了这个定位后面所有操作才有正确的出发点。1.2 硬件规格与使用场景定位我拿手上这张 Atlas 300V Pro 24G 为例硬件参数大概是这样项目参数芯片昇腾 310P 系列具体型号以 npu-smi 显示为准显存24GB LPDDR4XINT8 算力140 TOPS 左右不同版本有差异以官方规格为准FP16 算力70 TFLOPS 左右功耗最大 72W被动散热接口PCIe 3.0/4.0 x16推理能力支持静态/动态 Batch、多路视频流并发这类卡最典型的落地场景是边缘服务器、安防视频分析盒子、工业质检工控机、智慧零售终端、自动驾驶路侧感知单元。说白了就是要在现场设备里做实时推理又不想上一张 300W 的 GPU 把散热和电费拉爆的场景。24GB 大显存的意义在于可以一次性载入较大的模型比如带注意力机制的检测模型也可以同时加载多个模型做多任务推理类似 GPU 上的 MIG 思路。1.3 定个性它适合谁用如果你符合下面任何一条Atlas 300V 24G 会很对胃口项目要求全国产化硬件对供应链有硬性要求。推理服务部署在机房或边缘端功耗、散热、机箱空间都紧张。需要同时处理多路 RTSP 视频流做检测对单帧延迟不敏感但对吞吐量敏感。手里的 PyTorch 模型主要是 YOLO 系列、ResNet 系列、OCR、人脸识别这类成熟模型。反过来如果你只是想在自己的 Linux 服务器上快速跑个 demo、经常要改模型结构或者做训练调参劝你别买生态磨合成本会抹掉硬件成本优势。昇腾这套东西适合“模型一旦定下来就固定部署”的生产环境不适合“一天改八个模型结构”的研究环境。这个心态先摆正后面每一步都能顺利不少。2. 环境准备从拆箱到 npu-smi 能看到卡2.1 硬件安装要点Atlas 300V 24G 是标准 PCIe 全高全长卡安装本身不难但有几个细节我踩过坑先列出来第一供电。虽然整卡功耗只有 70W 左右但建议插在主板有充足供电能力的 PCIe x16 插槽上尽量不要用转接线或延长线尤其是那种 1 转 2 的 PCIe 拆分线信号质量不稳定会导致 npu-smi 间歇性识别不到卡。第二散热。300V Pro 是无风扇被动散热设计它需要依赖服务器机箱的系统风道来散热。如果装在塔式工作站里机箱后面板没有强排风卡很容易在满载推理半小时后温度飙到 85 度以上然后触发降频。我的经验是机箱至少要有前吹后抽的水平风道或者直接选 2U 以上的机架式服务器。第三CPU 和主板兼容性。官方支持 x86 和 ARM 服务器但部分旧款主板在 BIOS 里对 PCIe AERAdvanced Error Reporting支持不完善会出现开机认卡、拷机掉卡的情况。遇到这种问题先把 BIOS 更新到最新再查一下主板的 PCIe 链路降级日志。装好以后通电进系统执行lspci | grep -i ascend能看到类似Huawei Technologies Co., Ltd. Device的输出说明硬件链路正常。如果什么都查不到先检查卡是否插紧、供电是否到位再去翻系统日志dmesg | tail -50看有没有 PCIe 报错。2.2 驱动与 CANN 安装硬件装好只是第一步真正影响使用体验的是软件栈版本匹配。我用的组合是 Ubuntu 20.04.5 LTS CANN 6.x整体稳定。驱动下载渠道是昇腾社区官网需要注册账号这个没法绕开。推荐的安装顺序是安装 NPU 固件和驱动Ascend HDK。驱动包解压后里面有install.sh执行后会自动安装 driver 和 firmware。安装 CANN Toolkit。解压后执行./install.sh --install-for-user或--install-for-all我习惯装到当前用户目录省得污染系统。安装 CANN 内核源码包。这个包主要用于编译自定义算子如果只是跑推理不装也能过但很多官方脚本会检查它干脆一步到位。配置环境变量。将下面这段加到~/.bashrcsource /usr/local/Ascend/ascend-toolkit/set_env.sh export ASCEND_DEVICE_ID0注意安装之前先把系统里可能残留的旧版本卸载干净否则驱动和 CANN 版本错配会让你在推理阶段遇到很多莫名其妙的“Run time error”。卸载命令在解压后的目录里也提供了uninstall.sh跑一下重启再开始装新版。2.3 环境自查npu-smi info 怎么读装完之后第一件事就是敲npu-smi info看到类似下面的信息就说明基础环境通了------------------------------------------------------------------------------------------- | npu-smi 5.0.0 Version: 5.0.0 | ---------------------------------------------------------------------------------------- | NPU Name ... | Health | Power / Temp ... | ---------------------------------------------------------------------------------------- | 0 310P | OK | 25W / 48C | ----------------------------------------------------------------------------------------这里要重点看几个字段Health: 必须是 OK。Chip Version: 记下芯片具体型号比如 Ascend310P3后面转模型时--soc_version参数要填它。Hugepages Total / Hugepages Free: 如果 Free 为 0需要在/etc/sysctl.conf里配置大页内存。推荐设置vm.nr_hugepages2048每个大页 2MB总共约 4GB然后sysctl -p生效。Power / Temp: 空载时一般 20W 以下温度 50 度以内属正常。另外建议跑一遍官方自带的环境自检脚本/usr/local/Ascend/ascend-toolkit/latest/tools/run_msopstype.sh它能帮你确认 CANN 安装是否完整、环境变量是否生效。我就遇到过 CANN 装了两次、环境变量指向旧版本的情况最后python -c import acl; print(acl.__version__)直接报错排查了一圈发现是set_env.sh加载顺序问题多装真的不如装对。3. 把 YOLO 模型弄进去PyTorch 到 OM 的完整转换3.1 第一步PyTorch 导出 ONNXCANN 不认识.pt也不推荐直接转 ONNX 后再转 OM 的路径。我用的工具链是 PyTorch - ONNX - OM。以 YOLOv5s 为例先拿到官方权重然后导出 ONNX。cd yolov5 python export.py --weights yolov5s.pt --include onnx --opset 11 --batch-size 1导出时有几个关键点必须注意第一opset 版本不要太高。YOLOv5 官方仓库默认可能导出 opset 12 甚至 17但 CANN 的 ATC 工具对部分新算子支持滞后我实测用 opset 11 最稳尤其是 SiLU 激活函数和 Focus 模块相关的算子opset 11 下踩坑最少。第二输入尺寸固定。如果你部署的视频流分辨率固定是 1920x1080推理尺寸建议直接用 640x640导出时--imgsz 640。ATC 对静态 shape 支持最好动态 shape 虽然能配挺多参数但会牺牲性能还会引入额外的 shape 推导算子新手阶段不建议碰。第三ONNX 输出问题。因为我们在 Host 侧CPU做后处理所以导出时不要带 NMS 层也就是不要勾选 YOLOv5 的端到端导出选项。ONNX 的输出就是一个大的特征矩阵比如 YOLOv5s 输出1x25200x85后面我在 Python 代码里自己解码。导出成功后先用onnxruntime或python -c import onnx; onnx.checker.check_model(...)验证一下顺手可以跑一张测试图确认输出合理再进入下一步。我建议导完直接拿一张猫图跑一次 ONNX Runtime 推理确保模型本身没问题不然后面 ATC 报错时很难区分是 ONNX 的问题还是昇腾的问题。3.2 第二步ATC 工具转 OMATCAscend Tensor Compiler是 CANN 提供的模型转换工具命令行路径在$ASCEND_TOOLKIT_HOME/atc/bin/atc我用的命令模板是这样的atc --modelyolov5s.onnx \ --framework5 \ --outputyolov5s_bs1 \ --soc_versionAscend310P3 \ --input_shapeimages:1,3,640,640 \ --logerror \ --insert_op_confaipp.cfg参数解释一下--framework5表示输入是 ONNX。--soc_version必须和npu-smi info里看到的芯片版本一致填错会直接报错。--input_shape要和 ONNX 输入名一致YOLOv5 默认输入名是images。--insert_op_conf是 AIPP 配置文件可以把图像缩放、减均值、归一化这些预处理算子固化到模型里这样 Host 侧只需要做 letterbox 和 BGR/ RGB 转换省下大量 CPU 时间。AIPP 配置我单独说下文件内容大概是aipp_op { aipp_mode: static input_format: RGB888_U8 mean_chn_0: 0 mean_chn_1: 0 mean_chn_2: 0 min_chn_0: 0.003921569 min_chn_1: 0.003921569 min_chn_2: 0.003921569 }注意如果 YOLOv5 的源码里预处理已经做了归一化AI PP 这边就不再额外做否则会双重归一化导致精度崩掉。我这里配置成 RGB 输入和 1/255 缩放对应 YOLOv5 官方letterbox之后的处理逻辑。想省事的话可以先不用 AIPP在代码里做预处理等流程完全跑通后再加出问题也好定位。转换成功后会生成yolov5s_bs1.om大约十几 MB。转换过程通常几十秒到几分钟如果--logerror模式下没有输出恭喜说明转得很顺利。日志级别建议用--logerror否则 CANN 的 warning 信息多到刷屏非常影响心情。3.3 转换常见报错与解决ATC 转换过程是新手最容易心态炸裂的阶段。我遇到过的几类典型报错和处理方法报错 1E40001: Socketted Async pipeline session start failed一般不是模型问题是环境变量或权限问题。先检查当前用户对/usr/local/Ascend目录是否有写权限chmod一下再试。还有可能是上一次转换进程残留了临时文件用ps aux | grep atc清掉残留进程再转。报错 2E10001: Failed to parse the model后面跟着 ONNX 解析失败先看 is 的 ONNX 文件能否被 onnxruntime 正常加载。如果能加载问题多半是某个算子不在 ATC 的支持列表里。这时候返回 PyTorch 导出步骤尝试降低 opset 版本或者把模型升级到官方最新版比如 YOLOv5 v6.0 之后 Focus 模块被替换成 Conv算子兼容性更好。报错 3E40005: The model is too large or unsupported ops之类的模糊提示如果模型里有非常小众的算子比如某些注意力模块的自定义算子ATC 无法解析。处理思路是替换成昇腾支持的等价结构把torch.onnx.export里的custom_opsets去掉或者把自定义算子用 torch 基础算子重写。实在不行就在 ONNX 里用onnx-simplifier简化计算图python -m onnxsim yolov5s.onnx yolov5s_sim.onnx然后再用简化后的 ONNX 转 OM。绝大多数情况下能被 simplify 掉的冗余算子也是 ATC 解析的噪音来源。4. 写推理代码ACL 部署 YOLO 的核心流程4.1 完整代码骨架模型转换成功只是把“料”备好了真正要上桌还是得写推理代码。昇腾对外提供的是 AscendCL简称 ACL接口Python 版本的接口基本能覆盖全部推理场景。我把一个能跑通的 YOLOv5 推理流程骨架贴出来import cv2 import numpy as np import acl class YoloInferencer: def __init__(self, model_path, device_id0): self.device_id device_id # 初始化 ACL ret acl.init() assert ret 0, facl.init failed: {ret} ret acl.rt.set_device(self.device_id) assert ret 0, facl.rt.set_device failed: {ret} self.context, ret acl.rt.create_context(self.device_id) assert ret 0, facl.rt.create_context failed: {ret} # 加载模型 self.model_id, ret acl.mdl.load_from_file(model_path) assert ret 0, facl.mdl.load_from_file failed: {ret} self.model_desc acl.mdl.create_desc() acl.mdl.get_desc(self.model_desc, self.model_id) self._init_input_output() def _init_input_output(self): self.num_inputs acl.mdl.get_num_inputs(self.model_desc) self.num_outputs acl.mdl.get_num_outputs(self.model_desc) self.input_shapes [] self.output_shapes [] self.input_buffers [] self.output_buffers [] for i in range(self.num_inputs): size acl.mdl.get_input_size_by_index(self.model_desc, i) buf, ret acl.rt.malloc(size, 2 * 1024 * 1024) assert ret 0, finput malloc failed: {ret} self.input_buffers.append(buf) self.input_shapes.append([dim for dim in acl.mdl.get_input_dims(self.model_desc, i)[dims]]) for i in range(self.num_outputs): size acl.mdl.get_output_size_by_index(self.model_desc, i) buf, ret acl.rt.malloc(size, 2 * 1024 * 1024) assert ret 0, foutput malloc failed: {ret} self.output_buffers.append(buf) self.output_shapes.append([dim for dim in acl.mdl.get_output_dims(self.model_desc, i)[dims]]) def infer(self, input_data): # input_data 是经过预处理后的 ndarray连续内存 acl.rt.memcpy(self.input_buffers[0], input_data.nbytes, input_data, input_data.nbytes, acl.memcpy_kind.acl_rt_memcpy_host_to_device) # 创建 dataset input_dataset acl.mdl.create_dataset() output_dataset acl.mdl.create_dataset() input_data_buffer acl.mdl.create_data_buffer(self.input_buffers[0], input_data.nbytes) acl.mdl.add_dataset_buffer(input_dataset, input_data_buffer) for i in range(self.num_outputs): size acl.mdl.get_output_size_by_index(self.model_desc, i) out_buf self.output_buffers[i] out_data_buffer acl.mdl.create_data_buffer(out_buf, size) acl.mdl.add_dataset_buffer(output_dataset, out_data_buffer) ret acl.mdl.execute(self.model_id, input_dataset, output_dataset) assert ret 0, facl.mdl.execute failed: {ret} outputs [] for i in range(self.num_outputs): size acl.mdl.get_output_size_by_index(self.model_desc, i) out_data np.zeros(size, dtypenp.uint8) acl.rt.memcpy(out_data, size, self.output_buffers[i], size, acl.memcpy_kind.acl_rt_memcpy_device_to_host) outputs.append(out_data) # 释放 dataset acl.mdl.destroy_data_buffer(input_data_buffer) acl.mdl.destroy_dataset(input_dataset) acl.mdl.destroy_data_buffer(output_data_buffer) acl.mdl.destroy_dataset(output_dataset) return outputs这个类把 ACL 最核心的“申请资源、加载模型、送输入、取输出”都包进去了实际项目里可以在这个基础上扩展成线程池版本每个线程持有独立的输入输出 buffer避免频繁 malloc/free。4.2 预处理细节letterbox、归一化与格式转换YOLOv5 的预处理看似简单但每个细节都影响检测精度。标准流程是读图 - letterbox - BGR2RGB - 归一化 - HWC 转 CHW - 转 float32 并拷贝到设备侧。letterbox 的代码我直接复用 YOLOv5 官方 utils 的逻辑这里贴一个简化版本def letterbox(img, new_shape(640, 640), color(114, 114, 114)): shape img.shape[:2] r min(new_shape[0] / shape[0], new_shape[1] / shape[1]) new_unpad (int(round(shape[1] * r)), int(round(shape[0] * r))) dw (new_shape[1] - new_unpad[0]) / 2 dh (new_shape[0] - new_unpad[1]) / 2 img cv2.resize(img, new_unpad, interpolationcv2.INTER_LINEAR) top, bottom int(round(dh - 0.1)), int(round(dh 0.1)) left, right int(round(dw - 0.1)), int(round(dw 0.1)) img cv2.copyMakeBorder(img, top, bottom, left, right, cv2.BORDER_CONSTANT, valuecolor) return img, r, (dw, dh)推理前还要做数据类型转换YOLOv5 模型的输入类型是 float32所以要把 uint8 的图除以 255 转成 0-1 区间的 float32。如果你的 OM 模型里通过 AIPP 做了归一化那 Host 侧送到设备的图像必须是uint8并且通道顺序要按 AIPP 配置来。这一块我特别强调一下预处理的一致性直接决定检测精度哪怕是 1/255 多做了一次结果都会变得跟瞎了一样。我最开始就是在导出的 ONNX 里带归一化又在代码里除了一次 255导致小目标一个都检不出来排查了半天最后用一张纯色图对比了 OM 与 ONNX 的输出才发现的。4.3 后处理细节解码、NMS 与画框YOLOv5 的 ONNX 输出是1x25200x8585 4 个坐标 1 个目标分数 80 个类别分数。后处理要做的事从输出矩阵里读目标分数过滤低置信度的框。把中心点坐标 宽高解码成 x1,y1,x2,y2。做类别置信度过滤。按类别做 NMS去掉重叠框。根据 letterbox 的缩放比例把框坐标映射回原图。def postprocess(output, conf_thres0.25, iou_thres0.45, img_shape(640, 640), orig_shape(1080, 1920)): # output: (1, 25200, 85) float32 preds output[0] # (25200, 85) boxes [] scores [] class_ids [] xywh preds[:, :4] obj_conf preds[:, 4:5] cls_conf preds[:, 5:] cls_scores obj_conf * cls_conf # 转 xyxy xyxy np.concatenate([ xywh[:, :2] - xywh[:, 2:] / 2, xywh[:, :2] xywh[:, 2:] / 2 ], axis1) # 置信度过滤 类别过滤 max_cls np.max(cls_scores, axis1) max_cls_ids np.argmax(cls_scores, axis1) keep np.where(max_cls conf_thres)[0] if len(keep) 0: return [], [], [] boxes xyxy[keep] scores max_cls[keep] class_ids max_cls_ids[keep] # NMS可以用 cv2.dnn.NMSBoxes 或自己实现 indices cv2.dnn.NMSBoxes( boxes.tolist(), scores.tolist(), conf_thres, iou_thres ) if len(indices) 0: return [], [], [] indices indices.flatten() # 映射回原图坐标 r min(img_shape[0] / orig_shape[0], img_shape[1] / orig_shape[1]) dw (img_shape[1] - orig_shape[1] * r) / 2 dh (img_shape[0] - orig_shape[0] * r) / 2 final_boxes (boxes[indices] - [dw, dh, dw, dh]) / r return final_boxes, scores[indices], class_ids[indices]注意这里的orig_shape是原图的高宽NMS 和坐标映射的先后顺序不要搞反。实际多目标场景下 NMS 是最容易写出 bug 的地方我建议直接把cv2.dnn.NMSBoxes用起来省事且 C 实现速度比纯 Python 快很多。上面的后处理是纯 CPU 逻辑单帧 25200 个候选框在 Python 里做过滤大约耗时 3-8ms对大多数场景影响不大。但如果你要做极低延迟可以考虑在昇腾侧实现算子的办法那就是另一套玩法了我后面在优化部分展开。5. 性能调优与实测5.1 不同配置的性能对比思路一张 24G 的推理卡跑 YOLOv5s 到底能到多少帧这是大家最关心的问题。我先说结论在 640x640 输入、batch1 的静态模型下单张卡的模型推理时间可以做到几毫秒量级但端到端吞吐取决于你的预处理、后处理和数据搬运有多快。我第一次裸奔跑的时候端到端只有 30 FPS 出头因为全链路都是 Python预处理用 OpenCV、把图 copy 到 device、推理、再把结果 copy 回来、再做后处理每一步都有开销。后来做了两件事吞吐直接翻倍把预处理从函数调用改成批量 numpy 向量化避免逐像素循环。用多线程做“采集 预处理”和“推理”流水线让 NPU 在上一帧后处理时就开始下一帧推理。如果对延迟敏感还有一个关键配置是把模型转成 batch4 甚至 batch8 的静态模型然后用 batch 推理。虽然单帧延迟会略有增加要等 batch 填满但整体吞吐远高于 batch1。我实测在 batch4 时YOLOv5s 的模型推理总耗时比 batch1 单帧耗时 x4 还要低不少因为 NPU 对矩阵乘法的利用率上去了。5.2 多路并发与流水线优化要做多路视频流分析比如 16 路摄像头最稳妥的方案不是把一个大 batch 模型加满 16 路而是每个视频流独立推流主线程负责拉流和预处理推理线程池负责干活。昇腾的 ACL 接口支持在一个设备上并发执行多个模型实例也可以一个模型多线程并发acl.mdl.execute只要保证每个线程传入的 dataset 是独立的即可。我实际跑过的配置是一张 Atlas 300V 24G跑 YOLOv8s640x64016 路 1080p 视频流每路 10-15 FPSNPU 利用率大概 70%CPU 占用主要在前面预处理和后面跟踪逻辑上。这个性价比在同等功耗的 GPU 里基本找不到。再提一个容易忽略的点不要频繁acl.mdl.execute尽量在代码里用队列把请求串起来。如果每一帧都走一次 Python 侧 ACL API 调用Python 解释器开销会吃掉很大一块。更好的做法是后端用 C 封装一个推理服务Python 层只负责图像预处理和业务逻辑两者通过共享内存或本地 socket 通信。终极形态就是把整个 YOLO 推理封装成 gRPC 服务业务侧只发图片字节流。6. 避坑合集我踩过的那些坑6.1 问题速查表问题现象可能原因处理方式acl.rt.set_device报 507018当前设备已被占用或权限不足确认没有其他进程占用 NPU用户加入HwHiAiUser组后重新登录或者临时用 root 验证模型推理结果全 0输入数据格式或归一化不一致对比 ONNX 输出逐步排查预处理和 AIPP 是否双重归一化推理结果坐标偏移很大letterbox 的 scale 和 pad 没有同步到后处理把letterbox返回的r和dw/dh一路传到后处理函数acl.mdl.execute报 507033输出 buffer 空间不足或输出 shape 不匹配用acl.mdl.get_output_size_by_index重新读取大小不要硬编码多线程并发时程序崩溃每个线程共用了同一个 input/output buffer给每个线程独立创建 buffer不要共享 dataset长时间运行后 NPU 温度升高、帧率下降被动散热风道不畅检查机箱风扇转速必要时加装辅助风扇保持卡周围气流流动图像颜色异常发紫/发绿通道顺序和 AIPP 配置不一致确认输入是 RGB 还是 BGRAIPP 的input_format必须与送入数据保持一致碰到问题先别慌ACL 的报错码在 CANN 官方文档里有完整的错误码列表。我的经验是把报错码 文档链接 你的 CANN 版本号三个信息放一起搜比盲改代码要快十倍。6.2 超过官方文档的细节经验有些问题不是看文档能直接想到的我分享几条用真金白银换来的心得。第一NPU 设备号和推理并发要规划好。Ascend 300V 单卡默认逻辑设备只有一个但 CANN 支持通过ASCEND_RT_VISIBLE_DEVICES或者用acl.rt.set_device指定。多进程部署时每个进程绑定固定设备避免两个进程抢同一块卡导致推理抖动。如果有两块卡建议每块卡一个进程千万别开一堆线程去抢一块卡。第二AIPP 能省就省但要在模型结构稳定后再加。说到 AIPP它能省 Host 侧预处理时间但也把输入格式焊死在模型里。如果后面你突然想换 RGB 输入为 BGR或者想改变归一化参数必须重新转模型。项目前期多花点 CPU 预处理方便调试模型定稿后再把 AIPP 加上性能会明显改善。第三Python 推理的启动开销比你想的大。ACL 初始化、加载模型、申请 buffer 这些动作在 Python 层大概要几秒钟。如果是做长期运行的服务没问题但如果是命令行工具每跑一次都重新加载模型体验非常差。建议做一个常驻进程推理服务启动时加载模型之后一直保持推理状态业务侧通过接口调用。第四OM 模型和 CANN 版本强绑定。在 CANN 5.x 下转换好的 OM 模型换到 CANN 6.x 的机器上不一定能加载甚至可能直接报版本不匹配。团队协作时一定要统一 CANN 版本这比统一 Python 版本还要重要。第五ONNX 模型建议保留OM 模型别删。OM 是二进制格式反编译比较困难。一旦后续要调输入尺寸或增加 batch需要回退到 ONNX 重新转换。项目目录里至少保留两个文件yolov5s.onnx和yolov5s_bs1.om最好再配一个 AIPP 配置文件的备份。最后说点题外的如果你是为了学习 AI 部署昇腾这套东西的曲线比 CUDA 陡不少文档散、版本坑多、社区内容也没有 CUDA 丰富。但一旦摸熟了国产化场景下它的稳定性和性能都值得肯定。就我个人的体验来说Atlas 300V 24G 这张卡最适合的定位是“生产环境的稳定推理单元”而不是“搞研究的玩具”。如果你手里的模型已经验证完毕、部署场景又对功耗和体积敏感完全可以大胆选它要是还在频繁改模型结构的阶段还是先把思路理清楚再上车不然每天都是在跟工具链搏斗。
返回列表