


Ultralytics v8.4.56 于 2026年5月27日悄然发布,本次更新的核心目标十分明确——修复 QNN export 与 built-in provider wheels 之间的兼容性问题。如果你正在使用 Qualcomm QNN,尤其是针对 edge hardware 和 YOLO26 等模型进行导出,那么这次版本非常值得关注。它并非模型结构的大规模改动,也不是训练能力的重大升级,而是一次关乎部署稳定性的关键修补。
一、v8.4.56 发布概览
这次版本的核心诉求其实只有一个:确保 QNN 导出流程在不同 onnxruntime-qnn 打包形式下都能稳定运行。
问题的根源在于 onnxruntime-qnn。在不同平台以及不同 wheel 版本中,它暴露 QNN Execution Provider 的方式并不统一:有的采用 plugin-based 路线,有的则是 built-in 路线。旧逻辑在处理这类情况时,默认将所有场景都按照“插件方式”注册 QNN Execution Provider,这在某些 Linux x86-64 环境下容易引发问题——轻则导出卡住,重则因符号找不到而直接崩溃。
v8.4.56 的改进在于,先判断当前 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" 更新为 "8.4.56",这是标准版本迭代标识。
2. qnn_library_paths() 的返回类型和逻辑增强
在 ultralytics/utils/export/qnn.py 中,函数签名发生了变化:原来返回 tuple[str, str],更新后返回 tuple[str | None, str]。这意味着第一个返回值 ep_library_path 可能为 None。这个设计至关重要,因为它表达了一个新事实:QNN provider 可能已经内置,不再需要插件路径。
文档说明也随之更新
原先的描述为:onnxruntime-qnn 通过 onnxruntime_qnn helper module 暴露 QNN Execution Provider,Windows/Linux-aarch64 wheel 与 Linux x86-64 wheel 的差异只体现在库路径。更新后改为:plugin builds 暴露 onnxruntime_qnn helper module;monolithic builds 直接暴露 QNNExecutionProvider;backend libraries 仍然位于 onnxruntime/capi。这一变化本质上是将“QNN provider 可能存在两种形态”写入了逻辑和注释中。
3. 在 onnxruntime 可用 provider 中检测 QNNExecutionProvider
更新后的逻辑会在 onnxruntime 导入后检查 QNNExecutionProvider 是否已经存在于 onnxruntime.get_a vailable_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 场景下执行不必要的注销动作。
六、更新说明中的重点信息整理
根据本次更新内容,可以总结出几个关键事实:
- QNN now has two packaging styles:QNN 不再只有一种加载方式,而是分为 plugin-based 和 built-in。
- Ultralytics now detects provider a vailability:会检查
onnxruntime.get_a vailable_providers(),判断当前环境是否已内置QNNExecutionProvider。 - Linux x86-64 的注册失败问题被规避:直接针对某些 Linux x86-64 wheel 的已知问题,降低 undefined symbol error 风险。
- 代码逻辑更加自适应:不再把所有 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 导出流程从“固定假设”变成“动态适配”。这带来的直接收益包括:避免 Linux x86-64 上的 undefined symbol error、减少 QNN 导出失败、自动适配不同 wheel 打包风格、让 session 创建更智能、让部署流程更稳、更少依赖人工判断。
从版本性质上看,这不是一次“增加新模型能力”的更新,而是一次非常实用的导出与部署稳定性修复。对于日常训练和普通推理用户来说,体感可能不大;但对于走 QNN、Qualcomm、edge deployment 的用户而言,这个修复非常关键。
十、结语
代码地址就在 GitHub 上的 Ultralytics 官方仓库。如果你正在跟进 Ultralytics 的部署链路,尤其是 QNN 相关导出,那么 v8.4.56 值得尽快关注。它不改变模型架构,也不增加新训练特性,但它通过识别 onnxruntime-qnn 的不同包装方式,解决了一个非常实际、非常容易踩坑的问题。
简单来说,这次升级让 QNN 导出流程从“固定假设”变成了“动态适配”,这正是一个成熟部署工具链应该具备的能力。
