


Ultralytics v8.4.56 已于 2026年5月27日发布,这一版本的重点非常明确:修复 QNN export 与 built-in provider wheels 的兼容问题 。
如果你正在使用 Qualcomm QNN 相关部署流程,尤其是面向 edge hardware、YOLO26 等模型导出场景,那么这次更新值得重点关注。它不是一次模型结构更新,也不是训练能力的大版本升级,而是一次非常关键的部署稳定性修复。
一、v8.4.56 发布概览
Ultralytics v8.4.56 的核心目标只有一个:
让 QNN 导出流程在不同 onnxruntime-qnn 打包形式下都能正常工作。
这次更新的背景是,onnxruntime-qnn 在不同平台和不同 wheel 版本中,暴露 QNN Execution Provider 的方式并不一致:
- 有些是 plugin-based QNN wheels
- 有些是 built-in QNN wheels
旧逻辑在处理这些情况时,倾向于一律按"插件方式"去注册 QNN Execution Provider,这在部分 Linux x86-64 环境下会引发问题,甚至可能因为符号找不到而崩溃。
v8.4.56 的改动,就是让 Ultralytics 能够先判断当前 onnxruntime-qnn 属于哪种布局,再选择正确的 session 创建方式:
- 如果是插件式 QNN wheels:继续沿用原先的注册路径
- 如果是内建式 QNN wheels:则不再强行注册插件,而是直接使用已经内置好的 QNN provider
这意味着 QNN 导出流程变得更智能,也更稳。
二、这次更新解决了什么问题
1. 修复 built-in provider wheels 的 QNN 导出问题
这是本次更新的标题级修复点。
以前 Ultralytics 在导出 QNN 时,会默认尝试注册 QNNExecutionProvider,但对于某些新版本的 onnxruntime-qnn 来说,QNN provider 已经是 直接内置在 ONNX Runtime 里 的,不需要再作为独立插件注册。
如果还按照旧流程去注册,就可能导致导出失败。
2. 避免 Linux x86-64 上的已知失败
更新说明里特别提到一个痛点:
Linux x86-64 wheels 在插件注册时可能会触发 undefined symbol error。
这类错误通常意味着:
- 运行时尝试加载一个本不该再加载的插件
- 或者库之间的符号解析方式与当前 wheel 打包结构不匹配
v8.4.56 通过区分 built-in 和 plugin-based 两种 QNN 包装方式,避免了这类失败。
3. 兼容两种 QNN 打包风格
这次更新明确支持了两种形式:
plugin-based QNN wheels
这种情况下,QNN provider 需要手动注册。
Ultralytics 会继续使用原本的逻辑,先注册执行 provider 库,再创建 session。
built-in QNN wheels
这种情况下,QNN 已经是 ONNX Runtime 的内置 provider,不需要再注册 。
Ultralytics 会直接用 QNN provider 创建 ONNX Runtime session。
这就让 QNN 导出流程不再依赖"你安装的到底是哪一种 wheel"而报错。
三、为什么这次修复很重要
1. QNN 导出本身就是高敏感部署流程
QNN 导出不是普通推理流程,而是典型的部署前处理环节,主要用于把模型转换成适合 Qualcomm QNN 环境的上下文二进制文件。
这种流程本身就对环境、依赖、库版本、平台结构非常敏感。
因此,任何一个 provider 注册逻辑上的偏差,都可能导致:
- 导出失败
- 运行时报错
- 生成失败但日志不够直观
- 平台兼容性问题
2. 之前的固定注册方式已经不适配新 packaging
过去一套固定逻辑,适合的是"QNN 以插件形式存在"的情况。
但随着 onnxruntime-qnn 的打包方式演进,QNN provider 可能已经被直接集成在 ONNX Runtime 内部。
如果程序没有识别这个变化,就会产生"重复注册"或者"错误加载"的问题。
3. 对 Linux 环境特别关键
官方说明中强调了 Linux x86-64 的风险。
这意味着在这类环境中,旧流程可能会因为插件注册引发底层符号错误,导致导出失败。
v8.4.56 的价值就在于,它把这类环境问题前置识别掉了,从而提升了导出稳定性。
四、这次更新在用户体验上的变化
1. 导出更稳定
最直接的结果就是:
QNN 导出不再因为 provider 注册方式不匹配而轻易失败。
2. 环境适配更强
用户不再需要手动猜测当前安装的是 plugin-based wheel 还是 built-in wheel。
Ultralytics 会自动处理。
3. 对部署流程更友好
如果你面向 Qualcomm 和 edge hardware 做部署,这类修复会明显降低导出时的折腾成本。
简单说,就是减少环境配置和导出阶段的故障概率。
五、代码层面的具体变化
这次版本更新虽然只有 1 个 commit、2 个文件变化,但内容非常精准,几乎全部聚焦在 QNN export 路径上。
1. 版本号从 8.4.55 升级为 8.4.56
在 ultralytics/__init__.py 中,版本号更新为:
__version__ = "8.4.55"- 改为
__version__ = "8.4.56"
这是标准版本迭代标识,说明本次发布是一次正式更新。
2. qnn_library_paths() 的返回类型和逻辑增强
在 ultralytics/utils/export/qnn.py 中,函数签名发生了变化:
原来返回:
tuple[str, str]
更新后返回:
tuple[str | None, str]
这意味着第一个返回值 ep_library_path 可能为 None。
这个设计非常关键,因为它表达了一个新事实:
当 QNN 已经内置在 ONNX Runtime 中时,不需要再返回可注册的 provider 库路径。
文档说明也随之更新
原先描述是:
onnxruntime-qnn通过onnxruntime_qnnhelper module 暴露 QNN Execution Provider- Windows/Linux-aarch64 wheel 与 Linux x86-64 wheel 的差异只体现在库路径
更新后改为:
- plugin builds 暴露
onnxruntime_qnnhelper module - monolithic builds 直接暴露
QNNExecutionProvider - backend libraries 仍然位于
onnxruntime/capi
这个变化本质上是把"QNN provider 可能存在两种形态"写进了逻辑和注释中。
3. 在 onnxruntime 可用 provider 中检测 QNNExecutionProvider
更新后的逻辑会在 onnxruntime 导入后检查:
QNNExecutionProvider是否已经存在于onnxruntime.get_available_providers()
如果存在,说明当前属于 built-in QNN wheels,处理方式不同:
ep_lib = None
如果不存在,则继续按原先路径寻找插件库:
- Windows 下:
onnxruntime_providers_qnn.dll - Linux 下:
libonnxruntime_providers_qnn.so
也就是说,Ultralytics 现在不是"默认认为要注册",而是"先判断需不需要注册"。
4. QNN session 创建逻辑分支处理
在 onnx2qnn() 中,session 创建逻辑也发生了关键变化。
旧逻辑
旧逻辑的流程比较固定:
- 注册 QNN provider library
- 获取 QNN devices
- 添加 provider 配置
- 创建
InferenceSession - 反注册 provider library
新逻辑
新逻辑会根据 ep_library 是否存在分成两条路径:
情况一:ep_library 存在
说明是 plugin-based wheels,继续按以前的流程:
- 注册 execution provider library
- 通过
ort.get_ep_devices()查找 QNN device - 如果找不到 device,就抛出错误:
QNN EP registered but no QNN devices were found by ONNX Runtime.
- 将 devices 与 provider options 传给 session
- 创建
InferenceSession - 最后 unregister
情况二:ep_library 不存在
说明 QNN 已经 built-in,不需要注册插件:
- 直接创建
InferenceSession - 传入:
providers=[ep_name]provider_options=[ep_options]
这就是本次更新最重要的行为变化。
它避免了"明明已经内置,却还要手动注册"的问题。
5. 资源清理也同步调整
在 finally 中,旧逻辑会直接 unregister_execution_provider_library(ep_name)。
更新后则是:
- 只有当
ep_library存在时才执行 unregister
这样可以避免在 built-in 场景下执行不必要甚至可能有副作用的注销动作。
六、更新说明中的重点信息整理
根据本次更新内容,可以总结出几个非常关键的事实。
1. QNN now has two packaging styles
QNN 不再只有一种加载方式,而是分为:
- plugin-based
- built-in
2. Ultralytics now detects provider availability
Ultralytics 会检查 onnxruntime.get_available_providers(),判断当前环境是不是已经内置了 QNNExecutionProvider。
3. Linux x86-64 的注册失败问题被规避
这次修复直接针对某些 Linux x86-64 wheel 的已知问题,减少 undefined symbol error 风险。
4. 代码逻辑更加自适应
不再把所有 wheel 当成同一种情况处理,而是根据实际环境动态分支。
七、文档注释也做了同步更新
这次不仅改了逻辑,还修订了说明文字,让代码语义和实际行为保持一致。
新的注释中明确提到:
onnxruntime-qnn可能暴露为 plugin- 也可能暴露为 built-in provider
onnxruntime/capi中仍然包含 backend libraries- QNN 在不同 wheels 中的布局不同
这对后续维护很重要,因为它避免了开发者继续沿用"QNN 一定要注册插件"的旧认知。
八、这次更新对哪些用户最有价值
1. 使用 QNN 导出流程的用户
如果你正在使用 QNN 导出模型,这次修复会明显影响你的体验。
2. 面向 Qualcomm 平台部署的用户
如果你的目标是 Qualcomm 相关硬件或 edge hardware 场景,这次更新能减少导出故障。
3. Linux x86-64 环境用户
这是受影响最明显的一类环境。
旧版本可能会因为 provider 注册导致失败,而 v8.4.56 专门处理了这个问题。
4. 使用新版本 onnxruntime-qnn 的用户
如果你安装的是 built-in provider wheels,那么这次更新几乎就是为你准备的。
九、这次更新的总结
Ultralytics v8.4.56 的内容非常聚焦,核心就是一个方向:
让 QNN export 同时兼容 plugin-based wheels 和 built-in provider wheels。
这带来的直接收益包括:
- 避免 Linux x86-64 上的 undefined symbol error
- 减少 QNN 导出失败
- 自动适配不同 wheel 打包风格
- 让 session 创建更智能
- 让部署流程更稳、更少依赖人工判断
从版本性质上看,这不是一次"增加新模型能力"的更新,而是一次非常实用的导出与部署稳定性修复 。
对于日常训练和普通推理用户来说,体感可能不大;但对于走 QNN、Qualcomm、edge deployment 的用户来说,这个修复非常关键。
十、结语
代码地址:github.com/ultralytics/ultralytics
如果你正在跟进 Ultralytics 的部署链路,尤其是 QNN 相关导出,那么 v8.4.56 值得尽快关注。
它不改变模型架构,也不增加新训练特性,但它通过识别 onnxruntime-qnn 的不同包装方式,解决了一个非常实际、非常容易踩坑的问题。
简单来说,这次升级让 QNN 导出流程从"固定假设"变成了"动态适配",这正是一个成熟部署工具链应该具备的能力。