AI 推理引擎如何分配算子?理解 ONNX Runtime 的执行提供程序

解释 ONNX Runtime 如何按 EP 能力与优先级分配节点,区分可用列表、会话注册和实际节点记录,并用 CPU profiling 演示核对。

ONNX Runtime 分配算子时,会先取得执行提供程序的能力,再按注册优先级把模型图中的节点或子图交给合适的实现。执行提供程序简称 EP,例如 CPUExecutionProvider 和 CUDAExecutionProvider;它们告诉引擎哪些计算可以由自己处理。

“安装包里有 CUDA EP”“当前会话注册了 CUDA EP”“某个节点真的由 CUDA 执行”是三种不同证据。本篇解释这个差别,并在 Windows、Python 3.11.15、ONNX 1.23.1、ONNX Runtime 1.28.0、NumPy 2.4.3 中读取真实 CPU 节点记录。未测试 CUDA EP 或多设备性能;小图为人工构造的教学模型,不评价真实模型能力。

AI 推理引擎如何分配算子?理解 ONNX Runtime 的执行提供程序

从模型图到实际执行,发生什么

ONNX Runtime 架构说明给出图表示、与提供程序无关的优化、图分区和执行流程。GetCapability 是运行时向 EP 查询可执行节点或子图的能力接口,不是一个“请求 GPU 加速”的用户按钮。

  1. 读取 ONNX 图,理解输入、输出、算子和常量。
  2. 执行相应图变换,再查询已注册 EP 能处理的节点或子图。
  3. 按优先级分配可处理部分;有些节点可由高优先级 EP 承接,其他部分交给后续 EP。
  4. 运行分配后的图,并处理分区间的数据交换。

官方 EP 文档用 ['CUDAExecutionProvider', 'CPUExecutionProvider'] 表示优先尝试 CUDA,能力不覆盖的节点再交 CPU。这个列表不是“所有计算必定放在 GPU”。如果没有任何可用实现支持目标算子、opset 或自定义节点,会话可能无法建立;CPU 后备不能把不存在的实现变出来。

三层证据分别回答什么

检查 能回答 不能据此推断
ort.get_available_providers() 当前 ORT 安装可提供哪些 EP 名称 所列加速器一定在本机成功初始化
session.get_providers() 该会话实际注册了哪些 EP 每个 EP 都处理了节点,或所有节点都在首选 EP
节点 profiling 事件的 provider 这次执行中有记录的节点由哪个实现处理 其他模型或其他输入也有相同分区和性能

Python API提供会话、provider 和 profiling 入口;官方 profiling 说明解释记录文件用途。1.28.0 的官方执行器源码将 provider 写入节点事件参数,因此本例按该字段读取。

生成一个小图,并检查节点实际位置

在空练习目录用 Python 3.11 建立环境。以下 Windows PowerShell 命令安装 CPU 推理包,不需要 GPU:

py -3.11 -m venv .venv-ep
.\.venv-ep\Scripts\python.exe -m pip install "onnx==1.23.1" "onnxruntime==1.28.0" "numpy==2.4.3"

保存代码为 provider_check.py,运行 .\.venv-ep\Scripts\python.exe -X utf8 provider_check.py。它写入专用 provider-demo.onnx,并记录一条输入的 MatMul 和 Relu。ONNX helper 文档是图构建接口依据。为了易于观察两个节点,本例关闭图优化;真实优化后可能融合成更少节点,不能直接对比原图节点数量。

from pathlib import Path
import json
import numpy as np
import onnx
from onnx import TensorProto, helper, numpy_helper
import onnxruntime as ort

graph = helper.make_graph(
    [helper.make_node('MatMul', ['features', 'weights'], ['z']),
     helper.make_node('Relu', ['z'], ['result'])],
    'provider-demo',
    [helper.make_tensor_value_info('features', TensorProto.FLOAT, ['batch', 2])],
    [helper.make_tensor_value_info('result', TensorProto.FLOAT, ['batch', 2])],
    [numpy_helper.from_array(np.eye(2, dtype=np.float32), 'weights')],
)
model = helper.make_model(graph, opset_imports=[helper.make_opsetid('', 17)])
model.ir_version = 10
onnx.checker.check_model(model)
onnx.save(model, 'provider-demo.onnx')
options = ort.SessionOptions()
options.enable_profiling = True
options.intra_op_num_threads = 1
options.graph_optimization_level = ort.GraphOptimizationLevel.ORT_DISABLE_ALL
session = ort.InferenceSession('provider-demo.onnx', sess_options=options,
                              providers=['CPUExecutionProvider'])
x = np.array([[-1, 2]], dtype=np.float32)
result = session.run(None, {'features': x})[0]
np.testing.assert_array_equal(result, np.array([[0, 2]], dtype=np.float32))
profile = Path(session.end_profiling())
events = json.loads(profile.read_text(encoding='utf-8'))
nodes = [e for e in events if e.get('cat') == 'Node'
         and e.get('args', {}).get('provider')]
if not nodes:
    raise RuntimeError('没有节点provider记录,不能判断节点设备')
providers = sorted({e['args']['provider'] for e in nodes})
assert providers == ['CPUExecutionProvider']
print('available:', ort.get_available_providers())
print('session:', session.get_providers())
print('node_events:', len(nodes))
print('node_providers:', providers)
print('output:', result.tolist())
print('profile:', profile.name)

本次记录证明了什么

available: ['AzureExecutionProvider', 'CPUExecutionProvider']
session: ['CPUExecutionProvider']
node_events: 2
node_providers: ['CPUExecutionProvider']
output: [[0.0, 2.0]]

本次会话只注册 CPU EP,两个节点事件的 provider 都为 CPUExecutionProvider;输入 [-1,2] 经过单位矩阵乘法和 Relu 得到 [0,2]。available 中还出现 Azure EP,并不表示本例使用它;更不能把这个 CPU 实验写成已经验证 GPU 回退。

profile 文件名包含时间,代码使用 end_profiling 返回的真实路径,避免猜文件名。若没有带 provider 的节点记录,脚本报错而不凭会话列表推断节点位置。版本、构建选项和图融合都可能影响事件;应保存实际日志并按当前版本核对。

实际模型出现 CPU 节点,怎么继续查

先确认目标 EP 在当前包及依赖环境中能初始化,再看会话注册列表和节点记录。若节点由 CPU 处理,核对目标 EP 对该算子、数据类型和形状的支持;不要仅凭模型文件能打开就断言全图受支持。跨设备数据交换也可能影响整体延迟,设备名称不是性能结论。

读者下一步是对自己的同一模型、输入和 EP 配置保留一次节点记录,再据此决定要核查哪项算子支持或依赖。普通 CPU 推理输入检查可参照ONNX Runtime CPU 推理教程;它与本文的引擎分图原理是不同检查。

Ai菜鸟网。发布者:AI小管家,转载请注明出处:https://www.alyyhw.com/32902.html

赞 (0)
AI小管家的头像AI小管家
AI 工具检测不到 CUDA?用 PyTorch 核对安装包、驱动与实际设备
上一篇 1小时前
AI 模型怎么部署为本机 HTTP 服务?用 FastAPI 加载模型并验证输入
下一篇 1小时前

相关推荐

联系我们

联系我们

1

在线咨询: QQ交谈

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信
关注微信
分享本页
返回顶部