
拿到Atlas 300V 24G这块卡的第一天我就在项目群里被人问了一个特别直接的问题“这卡是运算加速卡吗能拿来部署YOLO吗”说实话刚拆包装的时候我也愣了一下它跟常见的GPU长得不太一样没有风扇没有视频输出口安安静静一块半高卡。等到真正把YOLO模型在这个卡上跑通、把视频流接进去、看着延迟和功耗数据我才确认了一件事它确实是加速卡但它不是给你训练的而是给“已经训练好的模型”上线跑量用的。这篇东西我就围绕atlas部署yolo这条主线把从环境搭建到模型转换、再到推理调优的完整过程写出来顺便把“24G到底是不是显存”这类基础问题一次讲透。写这篇内容的初衷是因为网上关于Atlas 300V的资料太散要么是官方文档的术语堆砌要么是有人跑了个demo就发帖中间缺了太多“为什么会这样”的解释。我希望这篇文章能成为一份真正能照着做完的实操笔记而不是那种看完了还是不知道从哪下手的东西。它适合谁看如果你手头正好有昇腾的推理卡或者你正准备把YOLO从GPU迁移到国产推理硬件上再或者你只是好奇ATLAS这条产品线和普通显卡有什么区别这篇都能给你省不少时间。1. 先别急着装环境Atlas 300V 24G到底是什么定位1.1 这卡确实是加速卡但它是“推理加速卡”Atlas 300V是基于昇腾310P芯片的AI推理板卡300V Pro型号配备24GB板载内存。它最大的特点就是插上PCIe就能工作专门负责把ONNX、TensorFlow这些框架训练出来的模型在端侧或边缘侧持续跑推理任务。对应到YOLO这个场景它要干的事情就是不停地把图像或视频帧吃进去、吐出检测框和类别而不是去迭代权重、做反向传播。很多人第一次看到规格表里的“24G”本能地把它当成显存以为跟RTX 3090那种24GB显存是一回事。这里我得把话说清楚它不是显存是板载内存也就是LPDDR4X颗粒共同组成这个推理卡的运行空间。它的作用是给模型权重、中间特征图、多路并发任务提供存储而不是像GPU显存那样靠高带宽去支撑大规模并行计算。打一个不太严谨但好理解的比方GPU像一个大厨煎炒烹炸什么都能做速度也快但耗电、发热大、需要很好的厨房环境Atlas 300V更像一条专门做固定菜品的流水线你让它开发新菜它不行但让它每天稳定出几千份同款菜它功耗低、跑得稳、几乎不用管。1.2 24G内存到底用在哪一开始我也觉得YOLOv5s的权重也就二三十MB24G内存是不是浪费了实际用起来才明白这个容量主要是为“并发和驻留”准备的。推理场景跟训练最大的不同在于训练是一批一批地算算完就释放推理是常年在线地算模型加载进内存后不退出。一个视频分析项目往往不止一个模型可能是YOLO做人车检测、另一个模型做车牌识别、再来一个做行为分类还要同时处理多路视频流。这种情况下24G内存可以让你把多个模型全部常驻在卡上不需要反复加载卸载配合多线程并发执行整个系统的吞吐量一下子就上去了。所以“24G是不是浪费”取决于你怎么用你只跑一个YOLOv5s确实用不满但如果你把它当成一台专用的AI视频分析盒子24G反而是很实际的设计。1.3 这块卡的规格速览我这边拿到的是一张Atlas 300V Pro下面这张表是我整理的关键参数方便你对照自己手头的卡项目Atlas 300VAtlas 300V Pro芯片型号昇腾310P昇腾310P板载内存24GB LPDDR4X24GB LPDDR4XINT8算力约80 TOPS约140 TOPS典型功耗约50W约72W散热方式被动散热依赖服务器风道被动散热适用场景轻量推理、边缘盒视频解析、多路检测、复杂模型需要注意具体算力和功耗会因批次、固件版本有差异最准确的方式是安装驱动后通过npu-smi info查看。如果你的卡是Atlas 300V而不是Pro算力会弱一些但部署YOLOv5s这种量级的模型依然没有问题。想清楚这几点之后后面所有操作目标就清晰了我们不是拿它做训练而是把一个训练好的YOLO模型转成昇腾的离线格式然后用AscendCL推理让它稳定地出结果。2. 驱动、固件、CANN三件套版本配套是第一步也是最大的坑2.1 软件栈到底有哪几层Atlas卡要跑起来光插到PCIe槽上是没用的需要三层软件配合驱动与固件HDK负责让操作系统识别硬件创建/dev/davinci0这样的设备节点提供npu-smi工具。这一层相当于显卡驱动的角色。CANN Toolkit昇腾的计算软件包包含atc模型转换工具、AscendCL开发库、调试工具等。开发机上必须装这个。CANN NNRT纯推理运行环境体积更小适合部署到生产服务器。如果你只在别人已经转好的om模型上做推理装NNRT就够如果你还要自己转模型那就必须装Toolkit。很多人的第一个坑就在这开发机上装了Toolkit交付部署时把整个环境复制过去结果对方那台机器只装了一个NNRT或者干脆直接拷贝了Python依赖一跑就报“libascendcl.so not found”。这个问题的根源是没有理解Toolkit和NNRT的定位差异。Toolkit是“大而全”的开发环境包含编译器、转换工具、头文件NNRT是“小而精”的运行环境只保留推理运行库。部署时只需要NNRT但如果你交付的是源码而不是编译好的程序对方机器上连atc都没有那当然要装Toolkit。2.2 版本配套真的不能乱昇腾这套软件的版本强绑定关系是新手最容易踩的坑。驱动版本、固件版本、CANN版本三者必须匹配否则会出现各种看不懂的报错比如npu-smi info显示“driver not initialized”或者跑推理时直接报版本不一致。我这边用的组合是CANN 6.3.RC2 驱动固件 23.0.RC3系统是Ubuntu 22.04aarch64。为什么这么选因为这是官方配套表里明确支持的组合也是目前社区里反馈比较稳的版本。你在实际操作时建议按这个流程来确认版本在昇腾社区官网找到“CANN版本配套表”。确认你的操作系统架构x86_64还是aarch64这两个架构的安装包不通用。根据你要用的CANN版本反查配套的驱动和固件版本四个数字最好完全一致。安装顺序也很讲究先装驱动固件再装CANN Toolkit。装完驱动固件后不要急着装Toolkit先重启服务器然后执行npu-smi info确认卡已经正常识别再继续下一步。不要问我为什么知道要重启我第一次就是没重启直接装CANN结果设备节点虽然存在但推理时数据根本进不去排查了半天发现驱动没有真正加载。2.3 一步一步装的实操命令以Ubuntu 22.04 aarch64为例我记录一下完整过程# 安装系统依赖 apt-get update apt-get install -y gcc g make cmake zlib1g-dev pciutils net-tools # 安装驱动固件包假设你已经下载好A300-3010-npu-driver_23.0.rc3_linux-aarch64.run chmod x A300-3010-npu-driver_23.0.rc3_linux-aarch64.run ./A300-3010-npu-driver_23.0.rc3_linux-aarch64.run --full驱动固件装完后重启然后验证npu-smi info正常情况下能看到卡的型号、芯片名称、驱动版本、固件版本芯片名称那一栏会显示类似Ascend 310P3的字样这个信息后面转模型时要用。然后装CANN Toolkitchmod x Ascend-cann-toolkit_6.3.RC2_linux-aarch64.run ./Ascend-cann-toolkit_6.3.RC2_linux-aarch64.run --install --quiet装完配置环境变量source /usr/local/Ascend/ascend-toolkit/set_env.sh echo source /usr/local/Ascend/ascend-toolkit/set_env.sh ~/.bashrc验证Toolkit是否可用which atc which npu-smi如果atc能找到说明Toolkit装好了。这里有一个很多人会漏掉的细节如果你把驱动固件装在了非默认路径或者你用的是非root用户环境变量里的路径就要相应调整。非root用户还需要把当前用户加入HwHiAiUser组否则访问/dev/davinci0会没有权限。2.4 Docker部署时容易漏掉的设备映射现在很多人的生产环境都是Docker化部署Atlas卡进容器比GPU稍微麻烦一点因为不仅仅是--gpus就行。需要把几个设备节点全部映射进容器docker run -it \ --device/dev/davinci0 \ --device/dev/davinci_manager \ --device/dev/hisi_hdc \ --device/dev/devmm_svm \ -v /usr/local/Ascend:/usr/local/Ascend \ ...少一个节点都可能导致模型加载不了或者推理超时尤其是/dev/hisi_hdc很多人漏掉它结果卡在acl.mdl.load_from_file这一步半天没反应。如果你在容器里遇到类似问题先检查设备映射是不是全的再去查日志。3. 用ATC把YOLO模型转成OMONNX到昇腾离线模型的关键一跳3.1 为什么不能直接跑ONNX这个问题我在社区里看到很多人问。ONNX是通用的中间表示昇腾的推理引擎其实有能力解析ONNX但直接解析执行的效率很低而且很多算子没有针对昇腾的AI Core做过优化。ATC工具做的事情是把ONNX等格式的模型做一轮完整的图编译算子选择、图优化、内存规划、算子融合。你可以把它理解成把C语言源码编译成机器码ONNX是源码OM是编译后的可执行文件。服务器推理场景下如果每次都在运行时“解释执行”模型性能和稳定性都达不到生产要求。所以atlas部署yolo的标准姿势是PyTorch导出ONNX再用ATC把ONNX转成OM推理时加载OM模型。3.2 导出ONNX时的三个关键决策第一步用YOLOv5官方代码导出ONNX。一般命令是python export.py --weights yolov5s.pt --include onnx --opset 11但真正到了生产环境我建议手动导出因为你要对导出图里的算子有完全的控制。以YOLOv5为例需要关注三件事关闭NMS。YOLOv5源码里的模型类带了NMS模块导出ONNX如果处理不好会把torchvision.ops.nms写进图里。ATC遇到这种算子基本必挂。正确做法是只导出前向推理部分后处理全部拿到CPU上做。固定输入尺寸。把模型输入固定成1x3x640x640这样转换时shape完全静态ATC能做的优化最多。如果你有动态尺寸需求后期可以用--dynamic_dims配置多档位但别一上来就搞动态先把静态跑通再说。确认opset版本。opset 11在CANN 6.3上支持得最稳opset过新反而容易触发不支持的算子分支。3.3 atc转换命令和参数逐项解析我用的转换命令长这样atc --modelyolov5s.onnx \ --framework5 \ --outputyolov5s_bs1 \ --soc_versionAscend310P3 \ --input_shapeimages:1,3,640,640 \ --insert_op_confaipp.cfg \ --output_typeFP16 \ --loginfo--framework5表示输入是ONNX格式。--soc_version是关键中的关键填错直接转换报错。怎么知道填什么前面让你记下来的npu-smi info的芯片名称这里就派上用场了。如果显示Ascend 310P3就填Ascend310P3如果显示Ascend 310P1就填Ascend310P1。这一步我见过太多人填错填成Ascend310就挂了。--input_shape要和导出ONNX时的输入张量名、shape完全一致YOLOv5默认的输入名是images。--insert_op_conf指向AIPP配置文件用来把图像预处理塞进模型里后面单独讲。--output_typeFP16让模型输出FP16数据减小从device往host拷贝的数据量。如果你的后处理代码不想处理FP16的字节可以保持FP32但性能和带宽会有一定牺牲我建议还是用FP16后处理时转一下就完事。--loginfo在首次转换时开启方便看报错日志转换稳定后建议改成--logerror因为info日志量太大。转换成功的标志是最后输出一行“ATC run success”。如果失败常见的是E10001和E40022。E10001一般是环境问题比如当前用户没权限写输出目录E40022是模型算子问题日志里会明确告诉你哪个算子不支持。遇到不支持的算子先检查ONNX版本和opset再考虑简化模型结构比如把一些自定义算子替换成标准组合。3.4 AIPP配置文件把预处理塞进硬件AIPP是昇腾提供的一个非常实用但也容易被玩坏的功能。它的作用是在模型执行前由硬件直接完成图像的颜色空间转换、缩放、归一化等操作。这样做的好处很明显图像从host拷贝到device之后不需要先把数据交给AI Core做预处理省掉了一次内存读写。我的aipp.cfg长这样aipp_op { aipp_mode: static input_format: RGB888_U8 src_image_size_w: 640 src_image_size_h: 640 csc_switch: true rbuv_swap_switch: true min_chn_0: 0 min_chn_1: 0 min_chn_2: 0 var_reci_chn_0: 0.003921569 var_reci_chn_1: 0.003921569 var_reci_chn_2: 0.003921569 }解释几个关键字段input_format填RGB888_U8意味着你喂给模型的原始数据是RGB、每个通道8位的图像。如果你的代码里用的是BGR就把rbuv_swap_switch打开让硬件帮你做颜色通道交换。var_reci_chn就是归一化时用的1/255填进去之后你的Python代码里就别再手动除以255了否则变成双重归一化模型输出会全部乱掉。csc_switch是颜色空间转换开关具体要不要打开取决于你的模型训练时用的颜色通道顺序这个和rbuv_swap_switch一样属于“错了就全错”的配置项。我踩过一次很典型的坑模型训练时用的是RGB我在预处理里先把BGR转成RGB然后AIPP里又打开了rbuv_swap_switch结果送入模型的数据R和B通道被莫名交换了检测准确率直线下降。排查半天才意识到双重转换的问题。所以AIPP配置一旦定下来代码里的预处理逻辑一定是对着配置来写的不能各干各的。4. 基于AscendCL的推理代码从初始化到输出检测框的完整链路4.1 先理解推理的整体流程OM模型转换成功后接下来就是用AscendCLACL写推理代码。如果你用过其他推理框架会发现流程大同小异初始化运行时、设置设备、加载模型、准备输入输出内存、执行推理、取回结果。但昇腾的几个细节跟CUDA生态不太一样需要重点注意。整体流程可以概括为acl.init初始化运行时acl.rt.set_device指定使用哪张卡acl.mdl.load_from_file加载OM模型然后创建输入输出的数据缓冲把图像数据拷到device内存执行模型最后从device内存拷回结果。关键一点是模型的输入buffer和输出buffer最好在初始化阶段就分配好推理循环里反复复用不要每帧都重新malloc否则时间全耗在内存分配上了。4.2 一个最小可运行的推理代码下面这段代码是基于Python的pyACL写的它依赖CANN Toolkit自带的acl模块不需要额外安装。我尽量精简了但保留了完整的流程骨架import acl import cv2 import numpy as np MODEL_PATH yolov5s_bs1.om def letterbox(img, new_shape(640, 640)): h, w img.shape[:2] r min(new_shape[0] / h, new_shape[1] / w) new_w, new_h int(w * r), int(h * r) resized cv2.resize(img, (new_w, new_h)) canvas np.full((new_shape[0], new_shape[1], 3), 114, dtypenp.uint8) dx (new_shape[1] - new_w) // 2 dy (new_shape[0] - new_h) // 2 canvas[dy:dy new_h, dx:dx new_w] resized return canvas, dx, dy, r def init_device(device_id0): ret acl.init() assert ret 0, facl.init failed: {ret} ret acl.rt.set_device(device_id) assert ret 0, fset_device failed: {ret} context, ret acl.rt.create_context(device_id) assert ret 0, fcreate_context failed: {ret} return context def load_model(model_path): model_id, ret acl.mdl.load_from_file(model_path) assert ret 0, fload model failed: {ret} return model_id def prepare_buffers(model_id): desc acl.mdl.create_desc() ret acl.mdl.get_desc(desc, model_id) assert ret 0 num_inputs acl.mdl.get_num_inputs(desc) input_infos [] for i in range(num_inputs): size acl.mdl.get_input_size_by_index(desc, i) ptr, ret acl.rt.malloc(size, 2) assert ret 0 input_infos.append((ptr, size)) num_outputs acl.mdl.get_num_outputs(desc) output_infos [] for i in range(num_outputs): size acl.mdl.get_output_size_by_index(desc, i) ptr, ret acl.rt.malloc(size, 2) assert ret 0 output_infos.append((ptr, size)) input_dataset acl.mdl.create_dataset() for ptr, size in input_infos: buffer acl.create_data_buffer(ptr, size) acl.mdl.add_dataset_buffer(input_dataset, buffer) output_dataset acl.mdl.create_dataset() for ptr, size in output_infos: buffer acl.create_data_buffer(ptr, size) acl.mdl.add_dataset_buffer(output_dataset, buffer) return desc, input_infos, output_infos, input_dataset, output_dataset def inference(model_id, input_infos, output_infos, input_dataset, output_dataset, image, stream): # 预处理仅做letterbox别忘了AIPP里面已经做了归一化和通道转换 bgr_img cv2.imread(image) if isinstance(image, str) else image rgb_img cv2.cvtColor(bgr_img, cv2.COLOR_BGR2RGB) padded, _, _, _ letterbox(rgb_img) input_data padded.transpose(2, 0, 1).astype(np.uint8) # host数据拷贝到device input_ptr, input_size input_infos[0] ret acl.rt.memcpy(input_ptr, input_size, input_data.tobytes(), input_size, 2) assert ret 0, fmemcpy host-device failed: {ret} # 异步执行推理 ret acl.mdl.execute_async(model_id, input_dataset, output_dataset, stream) assert ret 0, fexecute failed: {ret} ret acl.rt.synchronize_stream(stream) assert ret 0 # 从device拷回输出 outputs [] for ptr, size in output_infos: out_np np.zeros(size, dtypenp.uint8) ret acl.rt.memcpy(out_np.ctypes.data, size, ptr, size, 1) assert ret 0 outputs.append(out_np) return outputs if __name__ __main__: context init_device(0) model_id load_model(MODEL_PATH) desc, input_infos, output_infos, input_dataset, output_dataset prepare_buffers(model_id) stream, ret acl.rt.create_stream() assert ret 0 outputs inference(model_id, input_infos, output_infos, input_dataset, output_dataset, test.jpg, stream) print(output tensors:, [len(out) for out in outputs])这段代码有几个细节值得说明预处理里没有除以255因为AIPP已经做了归一化。这一点前面强调过再重复一次AIPP配置和Python预处理必须严格对应各做一半就是灾难。acl.rt.memcpy的最后一个参数是拷贝方向2代表host到device1代表device到host。我第一次写的时候把这个参数搞反了结果输出全为零还以为是模型转换出了问题。execute_async是异步接口执行完必须synchronize_stream否则拿到的数据可能是上一次的。4.3 后处理把原始输出变成检测框YOLOv5在ONNX里的输出是三个尺度的feature map形状分别为1x255x80x80、1x255x40x40、1x255x20x20。255这个数字的含义是3个anchor乘以854个坐标加1个目标置信度加80个类别置信度。拿到输出后要做的动作是把三个tensor做sigmoid压缩到0到1。重新排列成bx85的结构。用anchor解码出中心坐标和宽高。按目标置信度过滤掉低分框。最后做NMS去掉重叠框。后处理代码不太适合塞在推理主流程里我一般单独写一个函数输入是模型原始输出和原始图像的letterbox参数输出是最终的检测框列表。这部分的计算量在CPU上完全可以承受不需要放到卡上。4.4 一个容易忽略的问题FP16输出怎么处理如果你按我前面的命令设置了--output_typeFP16那么模型输出的原始字节是FP16的不是普通numpy默认的float32。你在后处理代码里要先把字节转成np.float16再转成np.float32否则数字会完全不对。我见过一个案例对方模型转出来结果全是“nan”排查到最后发现就是因为输出类型是FP16但代码按float32去解析。这个坑其实很好避开如果你不想碰FP16转换命令里直接把--output_type去掉用默认的FP32类型但推理性能和拷贝带宽会略差一些。我的建议是先用默认跑通业务再考虑用FP16做优化。5. 实测数据与调优方向batch、AIPP、多路并发怎么用5.1 一张表看懂性能基线先给一组我这边实测的数据硬件是Atlas 300V ProCANN 6.3.RC2模型为YOLOv5s和YOLOv8s输入640x640模型输入格式batch单帧平均推理时间说明YOLOv5s640x6401约5ms单帧延迟优先YOLOv5s640x6404约3.5ms/帧吞吐提升明显YOLOv8s640x6401约6ms模型稍重算子差异YOLOv8s640x6404约4.2ms/帧多batch更划算需要说明的是这个数据会随CANN版本、固件版本、服务器CPU性能有一些波动但整体趋势是有参考意义的batch从1提到4单帧均摊时间能下降30%到40%这是推理卡很典型的特征。5.2 batch和异步流简单有效的吞吐优化对YOLO这类目标检测任务如果业务对单帧延迟不敏感比如离线批量分析、批量巡检直接把batch开大是最省事的方式。做法很简单把多张图拼成一个batch代码里就是预处理循环执行多次然后把数据连续拷到device内存一次execute完成推理。如果业务是实时视频流batch1通常更合适因为要保证每一帧的延迟稳定。这时候应该用多路并发让多个线程共用一个model_id每个线程有自己的stream和输入输出buffer互不干扰。Atlas 300V Pro的AI Core数量足够支撑这种并发模式。简单估算单路25fps的视频流每帧推理5ms理论上单卡可以支撑8路左右实际考虑到CPU后处理和拷贝开销6到7路是比较稳的数字。这里有个架构上的小建议后处理不要放在推理线程里同步做。正确做法是推理线程只负责把模型输出拷回host丢进队列另外一组后处理线程从队列里取数据算检测框。这样即使后处理偶尔慢一点也不会阻塞下一帧推理。5.3 AIPP是否开启差别比想象的大我专门做过一次对比实验同一台机器同一批图AIPP开启和关闭的差距大约在15%到20%的性能差。差异来源不是因为AIPP本身能省多少计算而是它避免了图像在host、device之间的多次往返拷贝。如果你不开启AIPP常规做法是host读图用OpenCV做resize、颜色转换、归一化全部算完再拷贝到device。这些操作本身不算慢但在视频流场景下每一帧都来一遍累积开销不可忽视。开启AIPP后host只需要把原始图拷过去其余全部交给硬件。对于CPU资源紧张、内存带宽受限的边缘服务器这个优化尤其显著。5.4 定位清楚了再说性能瓶颈在哪很多人跑完推理发现吞吐上不去第一反应是卡不行但实际瓶颈往往在别处CPU预处理、内存拷贝、后处理NMS。我在调优时习惯先看这几个点nvidia-smi... 不对昇腾这边是npu-smi info看卡的AI Core利用率是否接近饱和。如果利用率只有十几卡上很多时间是在等着host给它送数据瓶颈在预处理或者拷贝。如果卡的利用率高但吞吐还是不够才需要考虑换更大的卡或者多卡并行。如果卡利用率高但端到端延迟依然很大大概率是后处理NMS没优化好比如用了Python循环逐框比较换成向量化的numpy实现或者cv2.dnn.NMSBoxes速度能快一个数量级。6. 踩坑总结这些弯路希望你别再走6.1 别把24G当显存更别拿它做训练这个我在开头就提过但还是值得放在踩坑总结里再说一次。Atlas 300V 24G不是给你跑训练用的它的内存带宽和计算架构设计目标是推理任务。如果你尝试用它做反向传播训练先不提算子支持的问题很多训练逻辑在推理卡上根本跑不通。它的正确归宿就是模型训练好了转成OM插上电稳定跑三年。6.2 为什么我的模型加载总是超时模型加载超时最常见的原因是容器里漏映射了设备节点尤其是/dev/hisi_hdc。如果你是在裸机上跑排查方向是驱动和固件版本是否匹配以及当前用户有没有权限访问/dev/davinci0。用ls -l /dev/davinci0看一下用户组如果不是HwHiAiUser组用chmod或者把用户加进组里解决。6.3 一个看起来是玄学但很实际的小问题我在测试中发现同样的OM模型、同样代码有时候前几十帧正常跑一会之后延迟突然变高。后来发现是服务器风扇策略问题。Atlas 300V是被动散热完全依赖机箱风道如果机箱里风扇转速不够温度超过85度后芯片会降频。这个问题在GPU上也会有但被动散热的卡更敏感。解决办法很朴素别把卡放在闷罐小机箱里保证风道畅通如果是自己搭的测试平台直接拿一个风扇对着卡的散热片吹万事大吉。6.4 优先用官方文档的配套表而不是网上教程的版本号网上很多教程写“某某版本亲测可行”但你不知道自己机器的架构、固件批次是不是跟对方一样。最稳妥的做法永远是先查官方配套表确认驱动、固件、CANN三者版本匹配再动手装。版本匹配这件事没有捷径我也不建议你看某个博主的版本就照抄环境不同抄作业翻车的概率很高。6.5 关于“部署YOLO”这件事的最后一点体会跑完整个流程之后我对atlas部署yolo这件事最大的感受是它比在GPU上部署多了一道模型转换的工序但也正是因为这道工序让模型在推理阶段变得特别省心。你可以把ATC转换理解成一次面向特定硬件的深度优化转换得好不好直接影响后续推理的效率和稳定性。所以我建议你花时间把AT C日志里的警告也看一遍尤其是关于算子精度下降的部分它会在你真正上线前就暴露很多隐患。如果你准备在项目里正式用Atlas 300V我还有一个很实际的小建议把模型转换步骤写进一个脚本输入是ONNX文件输出是OM文件和AIPP配置全程记录版本号。因为过三个月你回来看这个项目大概率会忘记当时的CANN版本和AIPP参数是怎么配的有一个脚本和一份记录能帮你省下一整天的回忆时间。好了技术上的东西就是这些希望这篇笔记能让你少走一些我走过的弯路。