网上充斥着ONNX runtime的简单科普,却没有一个系统介绍ONNX runtime的博客,因此本博客旨在基于官方文档进行翻译与进一步的解释。ONNX runtime的官方文档:https://onnxruntime.ai/docs/
如果尚不熟悉ONNX格式,可以参照该博客专栏,本专栏对onnx 1.16文档进行翻译与进一步解释,
ONNX 1.16学习笔记专栏:https://blog.csdn.net/qq_33345365/category_12581965.html
如果觉得有收获,麻烦点赞收藏关注,目前仅在CSDN发布,本博客会分为多个章节,目前尚在连载中。
开始编辑时间:2024/2/29;最后编辑时间:2024/2/29
所有资料均来自书写时的最新内容。
本专栏链接如下所示,所有相关内容均会在此处收录。
https://blog.csdn.net/qq_33345365/category_12589378.html
介绍
参考:https://onnxruntime.ai/docs/
定义
ONNX Runtime是由微软公司开发和维护的深度学习推理框架。是一个跨平台的机器学习模型加速器,具有灵活的接口,可以集成硬件特定的库。ONNX Runtime 可以与 PyTorch、Tensorflow/Keras、TFLite、scikit-learn 和其他框架中的模型一起使用。
ONNX Runtime推理
ONNX Runtime 推理支持关键的微软产品和服务,包括 Office、Azure、Bing,以及数十个社区项目中的机器学习模型。
ONNX Runtime 推理的示例用例包括:
- 提高各种机器学习模型的推理性能
- 在不同的硬件和操作系统上运行
- 在 Python 中训练,但在 C#/C++/Java 应用程序中部署
- 对在不同框架中创建的模型进行训练和推理
工作原理
- 获得一个模型。这可以是从任何支持导出/转换为ONNX格式的框架进行训练的模型。可以查看一些流行框架/库的tutorials。
- 使用ONNX Runtime加载并运行模型。可以查看basic tutorials,了解如何在不同编程语言中运行模型。
- (可选)使用各种运行时配置或硬件加速器进行性能调优。可以从Performance section作为起点来了解。
即使没有第三步,ONNX Runtime通常会比原始框架提供性能改进。
ONNX Runtime对模型图应用了一系列图优化,然后根据可用的硬件特定加速器将其分割成子图。核心ONNX Runtime中的优化计算内核提供了性能改进,并且分配给子图的进一步加速来自每个Execution Provider。
架构
此章节列出ONNX的高层次设计
参考https://onnxruntime.ai/docs/reference/high-level-design.html
关键目标
- 最大化并自动地利用不同平台上可用的定制加速器和运行时。
- 为定制加速器和运行时提供正确的抽象和运行时支持。我们称这种抽象为execution provider。它定义并向 ONNX Runtime 公开一组功能:它可以执行的一组单一或融合节点,其内存分配器等。定制加速器和运行时是execution providers的实例。
- 我们不希望execution providers总是能够完全在其设备上运行 ONNX 模型。这意味着 ONNX Runtime 必须能够在涉及多个execution providers的异构环境中执行单个模型。
- 提供支持高级优化,这些优化可以通过 graph-transformation API表达为模型到模型的转换。这些转换分为两类:全局转换(需要分析和转换整个图形)以及局部转换(可以被捕获为简单的(代数)重写规则(rewriting rules))。
高级系统架构
整个流程非常简单。
- 从一个 ONNX 模型开始,ONNX Runtime首先将模型图转换为其内存中的图表示形式。
- 它执行一系列与provider无关的优化。
- 它根据可用的execution provider将图分割成一组子图。
- 每个子图都分配给一个execution provider。通过使用
GetCapability()
API 查询执行提供者的能力,以确保一个子图可以由execution provider执行。
关于切分的更多信息
ONNX Runtime 根据可用的执行提供程序将模型图分割成子图,每个子图对应一个独立的provider。ONNX Runtime 提供了一个默认的execution provider,用作无法推送到更专业但更高效的execution providers的运算符的后备执行。直观地说,我们希望尽可能地将计算推送到更专业的execution providers。
我们使用一种简单的图分割技术。可用的execution provider将按照特定顺序考虑,并且每个provider将被分配它能够处理的最大子图(可能不止一个)。ONNX Runtime 提供的默认execution provider将作为最后一个考虑,以确保完整性。在将来可以考虑更复杂的优化方法(甚至可以实现为复合的execution provider)。
在概念上,每个分区都被简化为一个单一的融合运算符(fused operator)。通过调用execution provider的 Compile() 方法来创建它,并将其包装为自定义运算符。目前只支持同步执行模式。execution provider公开其内存分配器,用于为execution provider分配输入张量。重写和分区将初始模型图转换为由运算符组成的新图,这些运算符分配给默认execution provider或其他已注册的execution provider。ONNX Runtime 执行引擎负责运行此图。
关键设计
- 多个线程可以调用同一个推理会话对象上的
Run()
方法。详细信息请参阅 API文档(API doc)。 - 为了实现这一点,所有内核的
Compute()
函数都是const的,这意味着内核是无状态的。 - execution provider对运算符的实现称为内核(kernel)。每个execution provider支持一部分(ONNX)运算符/内核。
- ONNX Runtime 保证默认execution provider支持所有运算符。
- 张量表示:ONNX Runtime 使用标准的张量运行时值表示。execution provider可以在内部使用不同的表示,但是在其子图的边界上将值转换为标准表示(或从标准表示转换位值)是它们的责任。
扩展
- 添加一个定制运算符/内核
- 添加一个execution provider
- 添加一个新的图形转换
- 添加一个新的重写规则