1. 课程导入

在深度学习工程实践中,模型从研究代码走向部署硬件,往往要跨越多个中间表示。PyTorch 负责训练与算法表达,ONNX 负责跨框架的模型交换,MLIR 负责面向多硬件、多后端的编译优化。理解三者的定位与衔接关系,是掌握模型转换与编译优化的第一步。

一、核心原理:三种表示,三种职责

PyTorch 是动态图优先的深度学习框架,其 torch.nn.Module 与 torch.Tensor 构成了模型训练与推理的原始表达。它的优势在于灵活、易调试,但直接部署到异构硬件时,缺少统一的中间层来描述算子语义与硬件约束。

ONNX(Open Neural Network Exchange)是一种开放的模型交换格式,用计算图描述算子、张量、属性与初始化器。它把 PyTorch 的模块结构固化为静态图,使模型可以脱离 Python 运行时,被不同推理引擎加载。ONNX 的价值在于“交换”,而不是“优化”。

MLIR(Multi-Level Intermediate Representation)是编译器基础设施,提供可扩展的方言(Dialect)体系。在模型编译中,常见路径是 ONNX → torch-mlir / onnx-mlir → linalg / tosa / stablehlo → LLVM IR 或硬件专用 IR。MLIR 的价值在于“逐层下降”和“可复用优化”。

PyTorch → ONNX → MLIR 转换链路与职责分工 PyTorch 动态图 / nn.Module 训练与算法表达 torch.export / trace ONNX 静态计算图 算子 / 张量 / 属性 跨框架交换格式 MLIR 多级方言体系 逐层下降与优化 linalg / tosa / llvm 硬件 CPU / GPU NPU / DSP 专用加速器 导出 导入 下降 MLIR 内部典型下降路径 onnx / torch linalg / tensor tosa / stablehlo llvm dialect 目标代码 转换价值 • 解耦训练框架与部署硬件,降低重复适配成本 • 在 MLIR 中复用算子融合、循环优化、内存规划等编译能力 • 通过方言分层,支持 CPU / GPU / NPU 多后端 • 保留可调试性:每层 IR 可 dump、可验证、可回退

二、方法流程:从训练脚本到可编译 IR

一个典型的转换流程可以拆成四步。第一步,在 PyTorch 中完成模型定义与权重加载,使用 torch.export 或 torch.onnx.export 得到静态图。第二步,对导出的 ONNX 做检查与简化,确认算子版本、输入输出形状和动态轴设置。第三步,将 ONNX 导入 MLIR,得到高层方言表示。第四步,在 MLIR 中执行逐层下降与优化,最终生成目标后端代码。

# 1. PyTorch 导出 ONNX
torch.onnx.export(
    model, dummy_input, "model.onnx",
    input_names=["input"], output_names=["output"],
    opset_version=17, dynamic_axes={"input": {0: "batch"}}
)

# 2. 检查 ONNX 图
python -m onnxruntime.tools.onnx_model_utils model.onnx

# 3. 导入 MLIR(以 torch-mlir 为例)
torch-mlir-import-onnx model.onnx -o model.mlir

# 4. 查看并下降
mlir-opt model.mlir --convert-torch-to-linalg -o linalg.mlir

这条链路的关键不是“跑通命令”,而是理解每一步 IR 的语义边界:PyTorch 图带有 Python 语义,ONNX 图带有算子规范,MLIR 图带有方言与类型系统。只有边界清晰,排障时才能快速定位问题发生在哪一层。

三、案例场景:一次典型的部署需求

假设团队训练了一个包含卷积、LayerNorm 和注意力的模型,需要部署到边缘 NPU。直接使用 PyTorch 推理会依赖 Python 运行时,体积大、启动慢;直接手写 NPU 算子又成本高。此时可以走 ONNX 交换、MLIR 编译的路线:先把模型导出为 ONNX,再导入 MLIR,利用 linalg 做算子融合,最后下降到 NPU 厂商提供的方言或 LLVM IR。

提示:如果目标硬件已有成熟的 ONNX Runtime 或 TensorRT 后端,不必强行引入 MLIR。MLIR 更适合需要自定义优化、多后端复用或深度硬件适配的场景。

四、学习路径与实战环境

本课程的学习路径遵循“先通链路,再抠细节”的原则:先建立 PyTorch → ONNX → MLIR 的整体认知,再分别深入导出、导入、方言下降、算子映射、性能调优与排障。每一章都会围绕一个可运行的最小示例展开,避免只讲概念不落地。

阶段 核心任务 关键工具 产出物
环境搭建 安装 PyTorch、ONNX、MLIR 工具链 pip、conda、cmake 可运行的转换环境
模型导出 PyTorch 转 ONNX,处理动态轴与算子版本 torch.onnx.export model.onnx
MLIR 导入 ONNX 转 MLIR 高层方言 torch-mlir、onnx-mlir model.mlir
下降与优化 方言转换、算子融合、内存规划 mlir-opt、mlir-translate linalg / llvm IR
部署验证 生成目标代码并做数值一致性比对 目标后端工具链 可执行模型

实战环境建议使用 Python 3.10 及以上版本,安装 PyTorch 2.x、ONNX 1.15+、ONNX Runtime,以及 torch-mlir 或 onnx-mlir 的预编译包。若需要从源码构建 MLIR,请确保 LLVM/MLIR 版本与工具链匹配,否则容易出现方言注册失败或 pass 不兼容的问题。

# 建议的基础环境
python -m venv venv
source venv/bin/activate
pip install torch torchvision onnx onnxruntime
pip install torch-mlir

# 验证 MLIR 工具
mlir-opt --version
mlir-translate --version

常见误区:很多初学者认为“导出 ONNX 成功就等于转换成功”。实际上,ONNX 导出成功只说明图结构合法,后续导入 MLIR 时仍可能因为算子不支持、动态形状未固化、属性类型不匹配而失败。建议每完成一步都保存并检查中间 IR,而不是等到最后才排障。

五、复盘:为什么值得学习这条链路

掌握 PyTorch → ONNX → MLIR 的转换,不只是学会几个命令,而是建立一种“分层看待模型”的工程思维。训练框架关注算法表达,交换格式关注算子规范,编译器关注优化与硬件映射。三者各司其职,才能在模型规模增长、硬件碎片化的今天,保持部署链路的可维护性与可扩展性。

接下来的章节将沿着这条链路逐步展开:从环境搭建与最小示例开始,进入 ONNX 导出细节、MLIR 方言体系、算子映射、优化 pass、性能分析与故障排查。每一节都会给出可复现的代码与检查点,帮助你把“能转换”推进到“转得对、跑得快、查得清”。