optimizer
ONNX 模型的图级别优化工具,通过 56 个 Pass 对计算图进行等价变换,提升推理性能
加载项目详情…
本应用为开源项目,仅供学习研究,请遵守其开源协议。
ONNX 模型的图级别优化工具,通过 56 个 Pass 对计算图进行等价变换,提升推理性能
加载项目详情…
本应用为开源项目,仅供学习研究,请遵守其开源协议。
你在本地训练好了一个 ResNet-50 模型,导出为 ONNX 格式,迫不及待想部署到服务器上跑推理——结果一测延迟,傻眼了:同样一个模型,比 PyTorch 原生推理慢了整整 30%。更离谱的是模型文件体积还膨胀了 15%。同事告诉你"跑一下优化试试",你照做了,延迟直接降到了接近 PyTorch 的水平。
这个过程中,你很可能就用到了 ONNX Optimizer。
ONNX Optimizer 是 ONNX 官方维护的模型优化工具库,通过对 ONNX 计算图进行等价变换(Equivalent Graph Transformations),在不改变模型语义的前提下,降低推理延迟、减少内存占用、压缩模型体积。它的目标不是重新训练模型,而是让"已经训练好的模型"在部署阶段跑得更高效。

ONNX(Open Neural Network Exchange)是 Facebook(Meta)和微软于 2017 年联合推出的神经网络模型交换格式。它的核心价值在于"一次训练,多处部署"——你可以在 PyTorch 或 TensorFlow 中训练模型,导出为 .onnx 文件,然后在 ONNX Runtime、TensorRT、OpenVINO、NNAPI、Core ML 等任意推理引擎上运行。
但问题来了:ONNX 作为一种中间表示(IR),其图结构经过了各框架的导出器(exporter)生成,而导出器通常优先保证正确性而非最优性。导出的图往往包含大量冗余操作:
这些问题在模型迁移、跨框架导出时尤为突出。ONNX Optimizer 的出现,就是为了系统性地解决这些图级别的冗余。
ONNX Optimizer 的核心架构是一套基于 Pass 的图优化框架(Pass-based Graph Optimization Framework)。整个系统围绕三个核心概念展开:
1. Graph(计算图)
ONNX 的计算图是一个有向无环图(DAG),节点(Node)代表算子(Operator),边代表张量(Tensor)的数据流向。ONNX Optimizer 操作的对象就是这个计算图。
2. Pass(优化通道)
每个 Pass 是一个独立的优化规则,负责检测图中是否存在某种可优化的模式,并用更高效的等价结构替换它。ONNX Optimizer 目前注册了 56 个优化 Pass,可以分为几大类:
| 类别 | 示例 Pass | 效果 |
|---|---|---|
| 消除类(Elimination) | eliminate_identity、eliminate_nop_dropout | 删除无意义节点,减小图规模 |
| 融合类(Fuse) | fuse_bn_into_conv、fuse_qkv | 将相邻算子合并,减少计算量 |
| 代数简化类 | eliminate_common_subexpression | 消除重复计算 |
| 数据类型处理 | rewrite_input_dtype、bitscast | 优化数据类型转换 |
| 语义优化 | lift_lexical_references、replace_einsum_with_matmul | 处理复杂语义模式 |
3. PassManager(调度器)
PassManager 负责管理所有 Pass 的注册、排序与执行。系统内置了两组预制 Pass 组合:
fuse_and_elimination_passes:融合类 + 消除类 Pass 的组合,适用于大多数场景(这是命令行工具的默认行为)。exchange_passes:用于图结构等价变换。import onnx
from onnxoptimizer import optimize
# 加载模型
model = onnx.load("model.onnx")
# 执行优化(默认使用 fuse_and_elimination_passes)
optimized_model = optimize(model)
# 保存
onnx.save(optimized_model, "model_optimized.onnx")
# 一键优化(使用默认 fuse_and_elimination_passes)
python -m onnxoptimizer input.onnx output.onnx
# 打印所有可用 Pass
python -m onnxoptimizer --print_all_passes
# 指定自定义 Pass 列表
python -m onnxoptimizer -p eliminate_identity eliminate_nop_dropout input.onnx output.onnx
# 固定点迭代(反复执行直到图不再变化)
python -m onnxoptimizer --fixed_point input.onnx output.onnx
对于深度集成的生产环境,C++ API 是更自然的选择:
#include <onnxoptimizer/optimize.h>
ONNX_NAMESPACE::ModelProto model;
onnx::optimization::loadModel(&model, "model.onnx", true);
// 执行默认优化流水线
auto optimized = onnx::optimization::Optimize(
model,
onnx::optimization::GetFuseAndEliminationPass());
onnx::optimization::saveModel(&optimized, "model_optimized.onnx", true);
ONNX Optimizer 很少单独使用,通常与推理引擎配合:
项目核心逻辑用 C++ 实现(onnxoptimizer/ 目录下约 30 个 .cc/.h 文件),确保了优化的执行效率。Python 层通过 pybind11 绑定暴露接口,使 Python 开发者可以无缝调用。pyproject.toml 显示支持 Python 3.10+。
项目在代码质量上下了功夫:使用 mypy 做类型检查(配置为 strict 模式)、ruff 做 lint、clang-format 做格式化、reuse.toml 确保 SPDX 许可证头规范。CI 包含 lint、build-and-test、C++ 专项测试等 pipeline,测试覆盖较为全面。
并非所有 Pass 都适合所有场景——某些 Pass 需要特定的数据类型或图结构支持。GetFuseAndEliminationPass() 通过 PassType 过滤(Fuse 或 Nop 类型),自动选择适用的 Pass,降低了用户的认知负担。
1. 优化效果不稳定
ONNX Optimizer 的优化效果高度依赖 ONNX 模型的导出质量。不同框架的 ONNX 导出器(PyTorch 1.12+ 的 torch.onnx.export、TensorFlow-ONNX 等)产生的图结构差异很大,同一个 Pass 在某些导出图上效果显著,在另一些导出图上可能完全没有匹配机会。实际使用时建议先用 onnx.checker.check_model() 验证模型合法性,再运行优化。
2. 不保证最优性
ONNX Optimizer 做的是贪心局部优化(Greedy Local Optimization),而非全局最优化。它的 Pass 各自独立执行,不做全局搜索或整数线性规划(ILP)式的全局最优解搜索。对于需要全局最优化的场景(例如算子调度全局规划),还需要更专业的工具。
3. 不支持图修改类的优化
项目 Roadmap(自述文件中)至今仍标注为 open 的 issue #9 指出:当前系统不支持"分离图重写(graph rewriting)和常量折叠(constant folding)",即无法在图重写时保留纯语义优化能力。这在需要精细控制优化粒度的场景中构成限制。
4. 依赖 Protobuf 编译工具链
从源码构建需要 CMake >= 3.22 和 protobuf >= 4.25.1,在某些受限环境中(嵌入式设备、无 C++ 编译器的环境)部署门槛较高。官方虽然提供了 PyPI wheel,但 wheel 本身绑定了特定平台和 Python 版本。
ONNX Optimizer 是 ONNX 生态中被引用最广泛的基础设施之一。它的核心价值在于建立了一个标准化的图优化框架,使得不同推理后端(ONNX Runtime、TensorRT、OpenVINO)可以在共享优化结果的基础上进一步发挥各自硬件加速的优势。
从趋势上看,随着边缘 AI 部署需求的增长(手机、IoT 设备、汽车 SoC),对模型体积和推理延迟的优化需求将持续扩大。ONNX Optimizer 作为"图级别的手术刀",在模型部署流水线中的地位将越来越重要。
其 825 颗 GitHub Stars 和 Apache-2.0 许可证表明它已经是一个成熟的、被广泛采用的基础设施库,而非实验性项目。
| 维度 | 评价 |
|---|---|
| 优化能力 | 56 个 Pass,覆盖主流图优化场景 |
| 集成便利性 | Python/C++ 双接口,PyPI 一键安装 |
| 生态价值 | ONNX 生态关键基础设施 |
| 局限性 | 依赖导出质量,无全局最优化 |
| 推荐指数 | ⭐⭐⭐⭐(4/5)适合 ONNX 部署工作流的开发者 |
如果你正在做 ONNX 模型的部署优化,ONNX Optimizer 是值得优先尝试的工具——pip install 一行命令即可体验,它的优化效果往往超出预期。