第9篇:ONNX Runtime推理实现 — 备用推理引擎方案

发布时间:2026/7/7 12:44:41
第9篇:ONNX Runtime推理实现 — 备用推理引擎方案 第9篇:ONNX Runtime推理实现 — 备用推理引擎方案一、ONNX Runtime简介1.1 什么是ONNX RuntimeONNX Runtime是微软推出的一款跨平台推理引擎,专门用于运行ONNX格式的模型。它和ONNX格式是"亲兄弟"——ONNX定义了模型的标准格式,ONNX Runtime则是这个格式的"官方御用"推理引擎。ONNX Runtime的设计目标:高性能:通过各种图优化和算子优化,提供最佳的推理性能跨平台:支持Windows、Linux、macOS、Android、iOS等几乎所有平台跨硬件:支持CPU、GPU、NPU等各种硬件(通过Execution Provider机制)灵活性:既可以用于服务器端部署,也可以用于移动端和边缘设备如果说OpenVINO是"Intel CPU御用引擎",那ONNX Runtime就是"全能型选手"——它在哪都能跑,通用性极强。1.2 ONNX Runtime的核心优势ONNX Runtime之所以能成为最流行的推理引擎之一,有几个关键优势:通用性强原生支持ONNX格式,不存在兼容性问题支持的算子最全面,几乎所有ONNX算子都能跑各种框架导出的ONNX模型,在ONNX Runtime上基本都能直接运行跨平台能力Windows / Linux / macOS 桌面端Android / iOS 移动端嵌入式设备浏览器(WebAssembly版本)一套代码,到处运行Execution Provider机制这是ONNX Runtime最具特色的设计。它本身是一个"调度器",真正的计算可以交给不同的后端(Execution Provider)来执行:CPU:默认的CPU后端,基于MLAS(Microsoft Linear Algebra Subroutine)CUDA:NVIDIA GPU加速TensorRT:NVIDIA GPU深度优化OpenVINO:Intel硬件加速DirectML:Windows平台的GPU加速CoreML:Apple设备加速NNAPI:Android神经网络API…这种"插件化"的设计,让ONNX Runtime可以轻松扩展到各种硬件平台。性能优秀图优化能力强(算子融合、常量折叠、死代码消除等)内存优化到位支持量化(INT8、FP16)在CPU上的性能已经非常接近甚至超过很多专用引擎1.3 为什么需要双引擎GrainServer项目同时集成了OpenVINO和ONNX Runtime两个推理引擎。你可能会问:有一个不就行了吗?为什么要搞两个?这其实是一种很经典的工程设计思想——主备方案 + 灵活选择。让我们从几个维度分析双引擎的价值:维度1:容错与兼容性OpenVINO虽然在Intel CPU上性能好,但可能遇到某些算子不支持的问题ONNX Runtime的算子支持最全面,兼容性最好如果OpenVINO跑不起来(比如驱动问题、依赖缺失),可以立刻切换到ONNX Runtime双引擎相当于给系统上了"双保险"维度2:性能对比与选择不同的模型、不同的硬件、不同的batch size,最优引擎可能不一样有两个引擎可以实际跑一跑对比性能,选最快的那个比如在AMD CPU上,ONNX Runtime可能比OpenVINO更快在Intel CPU上,通常OpenVINO更快,但也不是绝对的维度3:部署灵活性用户的电脑千差万别,有的装了OpenVINO运行时,有的没有ONNX Runtime的依赖更简单,部署更方便可以根据部署环境灵活选择使用哪个引擎维度4:验证与交叉核对同一个模型,两个引擎都跑一遍,可以互相验证结果是否一致如果结果差异很大,说明可能哪里有bug这是一种很实用的质量保障手段在GrainServer项目中,OpenVINO是默认的主力引擎(openvino_predict是默认调用的),ONNX Runtime是备用方案(onnx_predict被注释掉了,但代码是完整的)。这种"主备双引擎"的设计,体现了很强的工程思维。二、InferenceSession创建2.1 会话(Session)的概念在ONNX Runtime中,推理是通过InferenceSession(推理会话)来完成的。什么是会话?你可以把它理解为"模型的一个运行实例"。创建会话的过程,相当于:把模型从磁盘加载到内存进行图优化分配内存准备好一切运行时需要的资源会话创建好之后,就可以反复调用它的run方法来执行推理了。让我们看OnnxRuntimeInfer类的构造函数:importonnxruntimeclassOnnxRuntimeInfer(object):def__init__(self,onnx_path,input_shape,num_classes):self.model_tools=ModelTools()self.model_config=ModelConfig(onnx_path,input_shape,num_classes)self.onnx_path=self.model_config.get_config("onnx_path")self.input_shape=self.model_config.get_config("input_shape")self.num_classes=self.model_config.get_config("num_classes")self.onnx_session=onnxruntime.InferenceSession(self.onnx_path)self.input_name=[input.nameforinputinself.onnx_session.get_inputs()]self.output_name=[output.nameforoutputinself.onnx_session.get_outputs()]# ... 颜色映射表 ...self.model_tools.show_config(self.model_config.config)核心的一行是:self.onnx_session=onnxruntime.InferenceSession(self.onnx_path)这行代码创建了一个推理会话。让我们看看它背后发生了什么:模型加载:读取ONNX文件,解析计算图图优化:根据设置的优化级别,对计算图进行各种优化执行提供程序选择:选择合适的Execution Provider(默认是CPU)内存规划:规划推理时的内存使用内核编译:为每个算子选择并编译最优的内核实现创建会话是一次性的开销,创建完成后,每次推理的速度就很快了。2.2 与OpenVINO加载流程的对比同样是加载模型,ONNX Runtime和OpenVINO的API风格有什么不同呢?步骤OpenVINOONNX Runtime