昇腾 ATC 模型转换入门指南把训练模型变成 NPU 能跑的 OM一句话让Agent变成昇腾专家昇腾任务轻松搞定。评测入口请按这个开源仓接入昇腾图谱 https://gitcode.com/agent0/kg-tools你花几天训练出一个深度学习模型满怀期待地拷到昇腾开发板上然后发现板子根本不认识这个文件。这不是板子的问题。训练框架产出的模型ONNX、Caffe、TensorFlow 等是为通用计算世界准备的而昇腾 NPU 有一套自己的方言——数据要按它喜欢的格式排布、算子要用它能执行的形态、内存要提前规划好。中间必须有人做一次翻译 备考这个角色就是ATC。这篇入门指南把 ATC 的使用场景、命令用法、内部流程、关键原理、常用参数和避坑事项一次讲清。所有关键事实都经昇腾知识图谱官方文档核实文末附来源清单。一、ATC 是什么模型的编译器ATCAscend Tensor Compiler昇腾张量编译器是昇腾 CANN 异构计算架构下的模型转换工具。官方定义一句话ATC 可以将开源框架的网络模型以及 Ascend IR 定义的单算子描述文件JSON 格式转换为 AI 处理器支持的.om格式离线模型。理解它最快的方式是类比 gccC 源码要经过 gcc 编译成可执行文件才能跑同样训练产出的模型文件要经过 ATC 编译成.omOffline Model离线模型才能在昇腾设备上高效推理。.c 源文件 --gcc-- 可执行文件 .onnx/.pb/.air 模型 --ATC-- .om 离线模型而且 ATC 不只是翻译。转换过程中它会做算子调度优化、权重数据重排、内存使用优化——相当于翻译的同时还替你把考试重点复习了一遍。这也是它叫编译器而不是格式转换器的原因。支持哪些输入--framework参数告诉 ATC 输入模型来自哪个框架注意填的是数字枚举不是字符串–framework 取值对应格式说明0Caffe双文件结构 权重输入命令写法请查所用版本的官方 ATC 文档1MindSpore.air格式模型3TensorFlow.pb等5ONNX最常用的路径官方文档口径支持 ONNX 1.12.0以所用 CANN 版本文档为准二、它能干什么典型使用场景场景一训练到部署的主线。这是 ATC 最经典的用法在训练机比如 910B上训练并导出 ONNX用 ATC 转成 OM拷到推理设备比如香橙派等 310 系列板子上通过推理接口加载执行。CANN 官方教程里就有这样一条端到端实验路径。场景二没有 NPU 的机器上也能转。官方文档明确模型转换阶段不依赖 AI 处理器。你可以在一台普通 x86 开发机上完成转换把 OM 拷到目标设备运行。两个约束要记住--soc_version必须填转换后实际运行的芯片型号转给谁就要填谁只要--soc_version相同不同产品只需转一次同一份 OM 可以分别部署。场景三单算子编译。ATC 不只能转整网还能把一个描述算子的 JSON 文件编译成单算子 OM--singleop算子开发调试时会用到。什么时候不需要 ATC也有不经过 ATC 的推理路径在线推理可以用 GE图引擎接口构图后由 GeSession 直接编译执行PyTorch 走图模式时由 TorchAir 组件对接 GE 编译。但对入门部署来说ATC 离线转 OM → 推理接口加载执行是最主线、最通用的路径。三、上手三步走环境、芯片型号、第一条命令第 1 步装好 CANN让 atc 命令可用CANN 装好后先 source 环境变量以实际安装路径为准不同版本路径略有差异# 常见路径FAQ 口径source/usr/local/Ascend/ascend-toolkit/set_env.sh# 新版 GE 文档口径为 /usr/local/Ascend/cann/set_env.sh# 带版本号目录的写法如 /usr/local/Ascend/cann-{version}/set_env.shecho$ASCEND_HOME_PATH# 有输出说明环境变量已生效两个易踩的环境点CANN 8.5.0 及之后版本转换时必须安装与目标 AI 处理器匹配的 ops 算子包否则编译失败文档两处一致强调在非昇腾设备上装 Toolkit 做转换还需把devlib目录加进LD_LIBRARY_PATH详见官方环境准备文档。atc命令本体位于 CANN 安装目录的bin下如/usr/local/Ascend/cann/binsource 之后直接敲atc --help能出帮助就说明装好了。第 2 步查芯片型号确定 --soc_versionnpu-smi info看回显里的Name字段--soc_version的值就是Ascend Name。例如 Name 显示 910B1参数就填--soc_versionAscend910B1常见值还有Ascend310P3、Ascend310B1等。少数产品如 950PR/950DT、A3 系列要用npu-smi info -t board取 Chip Name 与 NPU Name 组合填写具体以官方--soc_version文档为准。第 3 步跑第一条转换命令最简 ONNX 示例官方文档原文示例的整理版atc--model$HOME/module/resnet50.onnx\--framework5\--output$HOME/module/out/resnet50\--soc_versionAscend910B1参数含义--model原始模型文件路径与文件名--framework55 ONNX见第一节取值表--output输出路径与文件名不带.om后缀ATC 自动补上--soc_version目标芯片型号必填MindSpore 的.air模型同理只需把 framework 换成 1atc--model$HOME/module/ResNet50.air\--framework1\--output$HOME/module/out/ResNet50_air\--soc_versionAscend910B1一个更接近实战的例子真实部署往往还要固定输入尺寸、开启日志、甚至把预处理塞进模型。下面这条 YOLOv7 命令来自官方样例一次展示了这些常用参数atc--framework5\--modelyolov7.onnx\--outputyolov7_bs1\--input_formatNCHW\--input_shapeimages:1,3,640,640\--logerror\--insert_op_confaipp.cfg\--soc_versionAscend310P3--input_format输入数据格式。Caffe/MindSpore/ONNX 默认 NCHWTensorFlow 默认 NHWC与模型实际不符时显式指定--input_shape把动态输入固定下来格式输入名:N,C,H,W。ATC 是离线编译原则上需要确定的 shape动态分档见第五节--insert_op_confAIPP 预处理配置文件见第五节详解。转完怎么确认没翻车atc--mode1--om$HOME/module/out/resnet50.om--mode1会把 OM 模型的输入输出 shape 和数据类型打出来转换后先跑一下核对输入名、维度、dtype 与预期一致再上板。推理侧的标准流程是aclmdlLoadFromFile加载 OM →aclmdlExecute执行推理C/C 用 ACL 接口Python 用 pyACL本文不展开。给新手的工程建议来自官方迁移实践转换前先用 Netron 打开模型核对输入输出名/维度/dtype转换后做最小验证——OM 能加载 用 1~3 个固定输入跑通前向并保存输出范围再去对精度。四、ATC 里面发生了什么运行流程与关键原理一条atc命令敲下去到 OM 落盘内部是一条完整的编译流水线。先看全景图再逐段拆解Parser 解析训练框架模型.onnx / .pb / .air中间态 IR GraphAscend 图表示① 图准备图规范化 · Shape 推理 · 量化准备② 图优化常量折叠 · 算子融合 · 公共子表达式消除数据布局转换 NCHW/NHWC → NC1HWC0③ 图拆分 / 引擎分区按 AI Core / AI CPU 等引擎划分子图④ 图构建流分配 · 内存规划 · 任务生成.om 离线模型图结构 权重 算子二进制 tiling 参数拷贝到目标设备aclmdlLoadFromFile 加载aclmdlExecute 执行推理逐阶段拆解Parser 解析。把 ONNX/TensorFlow/MindSpore 的模型读进来统一翻译成中间态 IR Graph——类似编译器把各种语言先变成统一的中间表示IR后面所有优化都在这份统一表示上做。ATC 本身是 GEGraph Engine图引擎昇腾计算图编译和运行的控制中心对外提供的命令行入口这套流水线就是 GE 的编译器。① 图准备。做规范化、Shape 推理、量化准备等预处理把图整理成标准体位。② 图优化。编译器的核心收益环节重点认识三件事算子融合。把多个小算子合成一个大算子分硬件无关与硬件相关两类图融合做数学等价替换比如 Convolution BiasAdd 融合后直接在片上完成累加Conv2D BatchNorm 用数学推导合成一个算子UB 融合则消除相邻算子之间片上缓存 → 内存 → 片上缓存的往返搬运让数据留在 Unified Buffer 里流转。往返搬运是性能杀手融合是图模式相对逐算子执行的核心优势。常量折叠。输入全是常量的算子编译期就在主机侧提前算好替换成一个常量节点。典型的如维度计算——Shape/Reshape/Transpose 这类操作编译期就能求值没必要留到运行时。进阶用户可用--ge.oo.levelO1 --ge.oo.constantFoldingtrue控制融合 pass 级开关可用--fusion_switch_file。数据布局转换。框架模型常用的 NCHW/NHWC 会被转成 AI 处理器统一的NC1HWC0五维格式C0 对应矩阵单元 32B 对齐的元素数fp16 时 C016卷积权重则排成FRACTAL_Z分形格式送进 Cube 矩阵单元。入门篇记住数据被重新排成硬件最喜欢的队形即可细节官方概述文档有图解。此外还有公共子表达式消除CSE、死代码消除DCE等常规编译优化。③ 图拆分 / 引擎分区。按引擎把图切分成子图——大部分算子跑在 AI Core 上部分算子跑在 AI CPU 上分区器负责划界。④ 图构建。完成流分配、内存规划、任务生成产出编译产物并序列化成 OM。你在部署后感受到的加载即跑就是因为这些调度决策都在这一步提前做完了。OM 文件里装了什么转出来的.om不是一个简单的权重容器而是一个自包含的部署包按分区组织分区内容文件头ModelFileHeader模型元信息MODEL_DEF模型定义图结构、算子属性WEIGHTS_DATA权重数据已按目标格式重排TBE_KERNELS编译后的算子二进制kernelTILING_DATA预计算好的 tiling 参数切块策略SO_BINS / CUSTOM_OPS算子 so 与自定义算子数据按需打包用atc --mode6 --ommodel.om可以查看 OM 占用的关键资源信息和编译运行环境包括当初的 atc 命令行和 soc_version——排查这模型是谁在哪儿转的很有用。为什么要提前编译把编译挪到部署前完成收益不是省的那几秒启动时间而是全局视角做优化。逐算子下发执行时每个算子各自为战整图离线编译能看到全貌融合、内存复用、多流并行、模型下沉这些优化才做得起来有效减少 Host 与 Device 的调度交互部署侧自包含。传统部署要在目标机装完整算子包数百个 so、严格保证编译运行环境算子包版本一致、还要管理环境变量OM 把需要的都打包带走部署形态干净得多确定性与稳定性。一个真实的反例某推理框架的 CANN 后端在运行时编译生成 OM 缓存多卡并发写同一个缓存路径产生竞态问题——预编译 OM 文件可以完全避免这类运行时竞态。顺带一答常见疑问“GPU 上不是运行时 JIT 吗昇腾为啥搞离线”——官方文档没有做这样的对照论述这一段对比属于笔者的理解供参考两条路线本质都是把硬件差异和优化时机放在不同的位置昇腾选择把优化前置到转换期换取部署期的确定性与极致性能。遇到不支持的算子怎么办ATC 遇到算子库里没有的算子会直接报错、转换失败报错会点名算子类型长这样Op type NonMaxSuppression is not supported别慌按官方排错路径逐级尝试先化简模型用 onnx-simplifier 或 auto_optimizer 消除/化简有希望把不支持的融合算子拆成基本算子组合官方推荐按 auto_optimizer → onnxslim → 原模型 逐个回退尝试等价算子替换如 GroupNorm 换 InstanceNorm LayerNorm 组合、bicubic 插值换 bilinear让 AIPP 承担某些预处理类算子如离线 resize可下沉到 AIPP升级 CANN算子支持随版本持续完善自定义算子用 Ascend C 写 kernel 注册进算子库ATC 即可使用进阶话题。另外一个冷知识dtype 不匹配导致的编译失败可以通过自动插入 Cast 打通AI CPU Cast 自动插入模式详见官方文档。五、主要参数速查必选四件套--model、--framework、--output、--soc_version见第三节不再赘述。常用可选参数参数干什么备注 / 默认--input_format输入数据格式Caffe/MindSpore/ONNX 默认 NCHWTensorFlow 默认 NHWC--input_shape固定输入 shape如images:1,3,640,640动态维度用-1占位配合下面的动态参数--dynamic_batch_sizebatch 分档如1,2,4,8至少 2 档、最多 100 档只支持 N 在首位OM 会新增一个输入用于喂实际 batch 值新手常踩--dynamic_image_size分辨率分档如416,416;832,832与--input_shape配用H、W 位填 -1与 dynamic_batch_size 互斥--output_type指定输出数据类型—--out_nodes指定输出节点—--core_type使用的 Core 类型默认 AiCore含 Cube 算子的网络只能 AiCore--external_weight权重外置为单独文件默认 0适合超大模型拆分管理--log转换日志级别默认 null不出调试日志排错加--logdebug--insert_op_confAIPP 预处理配置文件见下文--singleop单算子 JSON 编译算子开发场景精度一族参数取值默认说明--precision_modeforce_fp32 / force_fp16 / allow_fp32_to_fp16 / allow_mix_precision / must_keep_origin_dtypeforce_fp16老版精度参数--precision_mode_v2fp16 / origin / cube_fp16in_fp32out / mixed_float16 / mixed_bfloat16 / mixed_hif8fp16官方推荐改用与老参数互斥--op_select_implmodehigh_precision / high_performancehigh_performance算子实现选高精度还是高性能某算子只实现一种模式时该参数对其不生效一个诚实提醒--optypelist_for_implmode按算子列表指定 implmode在网上老教程里出镜率不低但官方文档已明示该功能停止演进、后续版本会废弃请勿使用。另外--compression_optimize_conf是压缩优化的配置入口含首层量化融合、训练后量化等特性注意配了其中的 calibration 量化就不能再配高精度模式两者会互相抵消收益。AIPP把预处理焊进模型AIPPAI Pre-Processing把推理前的图像处理——色域转换YUV→RGB、抠图、归一化——以 Aipp 算子的形式固化进 OM推理时用专用加速模块完成省掉 CPU 上的预处理代码。开启方式就是--insert_op_confaipp.cfg一份官方静态 AIPP 配置示例YUV420SP 转 RGB 通道减均值aipp_op { aipp_mode : static related_input_rank : 0 # 作用于第几个输入 src_image_size_w : 608 src_image_size_h : 608 crop : false input_format : YUV420SP_U8 csc_switch : true # 色域转换开关 转换矩阵 matrix_r0c0 : 298 matrix_r0c1 : 0 matrix_r0c2 : 409 matrix_r1c0 : 298 matrix_r1c1 : -100 matrix_r1c2 : -208 matrix_r2c0 : 298 matrix_r2c1 : 516 matrix_r2c2 : 0 input_bias_0 : 16 input_bias_1 : 128 input_bias_2 : 128 mean_chn_0 : 104 # 各通道减均值 mean_chn_1 : 117 mean_chn_2 : 123 }约束提一句静态 AIPP 与动态分辨率共用时cfg 里不能开 Crop/Padding 且src_image_size_w/h须设 0。完整配置项见官方《AIPP 配置参考》。–modeATC 的六种运行模式取值作用0默认执行转换生成.om1查看模型信息输入输出 shape/dtype——自检常用3只做模型合法性预检查生成 check_result.json5把 dump 出的图结构文件转 JSON定位图问题用6查看已有 OM 的资源占用与编译运行环境30生成感知硬件调度的.exeom加载更快、内存峰值更低仅特定芯片支持顺手的两个环境变量exportTE_PARALLEL_COMPILER16# 算子并行编译进程数1~32默认 8大网转换提速exportASCEND_SLOG_PRINT_TO_STDOUT1# atc 日志直接打屏默认只落盘六、避坑指南常见报错与注意事项排错总表现象 → 原因 → 对策#现象原因对策1Op type XXX is not supported算子库无该算子见第四节五步排错路径2E10003 ... Value 1.1,2,4,8 for parameter --dynamic_batch_size is invalid档位值含非法字符小数点按提示改参数值错误信息里的 Reason 写得很直白3EZ0005 OP[xx] Nth input has incorrect shape size算子输入维度数不对核对--input_shape用 DUMP_GE_GRAPH见下在图里找问题节点4转换巨慢 / 内存耗尽失败动态档位过多过大整网过大减少档位/调低数值超大模型拆成多段分别转换官方大模型实战做法转换期可swapoff -a防止 swap 拖慢5转换成功但推理结果不对精度模式、输入 dtype/layout、AIPP 配置问题同输入对比 onnxruntime 与 NPU 输出余弦相似度/最大绝对误差换 precision_mode 对照日志里 grepreplace/fusion/unsupported6OM 无法加载 / 执行报acl.mdl.execute error 507011soc_version 与实际设备不符npu-smi info查实际型号重转atc --mode1核对 OM 信息勿复用旧 OM7ModuleNotFoundError: No module named decorator或tePython 依赖缺失按提示 pip 安装te报错说明装 CANN 时没带--pylocal建议带参数重装错误码怎么认ATC 生态的错误码按前缀分家认前缀就知道该往哪查前缀归属E1xxxxGE 图编译/校验E20101FE 算子融合EE1011RTS 运行时EH0001ACLEZxxxxATC 工具专属离线模型编译E*9*** 一类内部错误按报错信息排查无果的话收集日志联系技术支持。各家族的 Symptom/Solution 结构说明都在官方 troubleshooting 手册里。日志去哪看转换失败第一反应加--logdebug重跑日志格式形如[ERROR] GE(30741,atc.bin):2021-12-09-16:10:22.539 [error_manager.cc:263]...——方括号里的模块名就是定位思路GE 开头查图编译/参数FE 查算子融合TEFUSION 查融合算子编译TBE 查算子编译落盘路径$HOME/ascend/log/debug/plog/plog-pid-*.log调试日志、$HOME/ascend/log/run/plog/运行日志进阶--op_debug_level1生成 kernel 编译中间文件用于定位 AICore Error会影响性能仅排错时开看图结构export DUMP_GE_GRAPH1各阶段图描述生成ge_onnx*.pbtxt可以用 Netron 直接打开——肉眼看融合/拆分后的图排 shape 问题神器。版本与兼容最容易忽略的坑升级顺序不能乱固件 → 驱动 → CANN顺序不可颠倒升驱动后必须重启。查版本cat /usr/local/Ascend/ascend-toolkit/latest/version.cfg、npu-smi info -v。OM 与 CANN 版本绑定官方规则是运行环境 CANN 版本不低于转换环境即可——低版本 CANN 转出的 OM 可在高版本 CANN 上运行兼容 4 个版本周期社区经验进一步补充同一大版本内小升级一般兼容跨大版本不兼容。最稳的做法永远是在目标部署环境用当地 CANN 重转一次。OM 不跨芯片910B 转的 OM 不能拿到 910A 上用芯片型号 CANN 版本共同决定模型支持范围。两个特例场景要求更严动态 shape 算子场景和昇腾虚拟化实例vNPU场景转换环境的 CANN 版本必须与运行环境相同。新手好习惯清单转换前 Netron 核对输入输出名/维度/dtype转后atc --mode1自检固定输入跑通前向、对完精度余弦相似度等再上真实业务msame、ais_bench 等工具可做 OM 精度/性能对比模型与输出路径用纯英文、不含空格——这是经验习惯官方未将其列为通用约束但能少一类诡异问题大网转换前评估内存必要时分段转换。七、写在最后ATC 是昇腾部署链路的第一道门一条命令背后是解析 → 图准备 → 图优化 → 分区 → 构建 → 序列化的完整编译流水线把框架模型变成针对目标芯片深度定制的自包含 OM。入门阶段记住三件事就够了——soc_version 填运行环境的芯片、shape 策略想清楚再转、报错先看模块名和日志。想动手走一遍完整链路的话CANN 官方 learning-hub 有现成实验在 910B3 上训练导出 ONNX再到香橙派310B上用 ATC 编译为 OM 并用推理接口执行——从训练板到边缘板正好把本文所有知识点串起来。本文涉及的 API 语义、参数默认值、报错样例与兼容规则均经昇腾知识图谱ascend.wiki的官方文档节点核实主要来源包括GE 仓atc_tools/overview/atc_overview.md、atc_tools/CLI_options/系列参数文档、GE 编译器设计文档compiler.md、so_in_om.md、常量折叠与融合模式设计文档、AIPP 配置示例、官方 troubleshooting 错误码手册及 cann-recipes 实战样例。接入昇腾知识图谱 https://gitcode.com/agent0/kg-tools