m0_51628808 2025-10-11 15:07 采纳率: 100%
浏览 3
已结题

QNN 模型转化转换的疑问

https://blog.csdn.net/jx232515/article/details/147590568
这篇文章中介绍了在android 系统上qnn sdk转换,运行模型的方法
有一个疑问,就是对于第七步 进一步编译得到bin 模型文件一事
目标device应该是基于aarch64-android ARM 的android设备,下面qnn-context-binary-generator
执行的时候为什么选择的都是x86_64-linux-clang? 请帮忙解答 多谢!


我们使用htp 后端进行推理,可以构建一个后端backend配置文件,然后将配置文件作为输入,转换得到和硬件相关联的bin 文件,类似于c++ 代码实现中的构建context的那一步

${QNN_SDK_ROOT}/bin/x86_64-linux-clang/qnn-context-binary-generator
--model ./output-so/x86_64-linux-clang/libbge_real_data_qnn.so
--backend ${QNN_SDK_ROOT}/lib/x86_64-linux-clang/libQnnHtp.so
--output_dir ./bin --binary_file bge_8295_qnn.serialized
--config_file ./htp_backend_extension.json


  • 写回答

5条回答 默认 最新

  • 宝码香车 优质创作者: JavaScript技术领域 2025-10-11 15:10
    关注

    让【宝码香车】来帮您解答,本回答参考DeepSeek编写,并整理提供。

    如果答案让您满意,请采纳、点赞、关注,非常感谢!
    .
    每日一句正能量,让它带给您好心情:困难像一面墙,翻过去,就能看到不一样的风景。
    .

    您好!您提出的这个问题非常专业,也确实是很多初次使用QNN SDK的开发者会感到困惑的地方。您对目标设备(aarch64-android)和编译工具(x86_64-linux-clang)之间不匹配的质疑是完全合理的。

    下面我来为您详细解释这背后的原因。

    核心原因:模型转换与模型执行的分离

    关键在于,qnn-context-binary-generator 这个工具执行的是一个 “编译” 步骤,这个步骤通常是在你的 开发主机(例如 x86_64 架构的 Linux/Windows PC) 上完成的,而不是在最终的 目标设备(aarch64 Android 手机) 上。

    我们可以把这个过程类比成传统的 C/C++ 程序开发:

    1. 在 PC 上编译(Compile): 你在 x86 电脑上使用交叉编译工具链(比如 aarch64-linux-android-g++),将 C++ 源代码编译成可执行文件。这个可执行文件本身是 ARM 架构的,无法在你的 x86 PC 上直接运行。
    2. 在设备上运行(Execute): 你将编译好的 ARM 架构可执行文件推送到 Android 设备上,它就可以完美运行。

    QNN 的模型转换过程与此高度相似:

    详细步骤解析

    让我们分解您提供的命令:

    ${QNN_SDK_ROOT}/bin/x86_64-linux-clang/qnn-context-binary-generator \
      --model ./output-so/x86_64-linux-clang/libbge_real_data_qnn.so \
      --backend ${QNN_SDK_ROOT}/lib/x86_64-linux-clang/libQnnHtp.so \
      --output_dir ./bin \
      --binary_file bge_8295_qnn.serialized \
      --config_file ./htp_backend_extension.json
    
    • qnn-context-binary-generator (x86_64-linux-clang):
    • 这是什么: 这是 Qualcomm 提供的一个工具程序
    • 为什么是 x86_64: 因为它需要在你的 开发主机(PC) 上运行。你的 PC 很可能是 x86_64 架构的,所以 Qualcomm 提供了这个架构的预编译版本给你使用。
    • --model .../libbge_real_data_qnn.so (x86_64-linux-clang):
    • 这是什么: 这是由 qnn-model-lib-generator 生成的模型库文件
    • 为什么是 x86_64: 同样,qnn-model-lib-generator 也是一个在开发主机上运行的工具。它生成的 .so 文件包含了模型的图结构和权重数据,但这个 .so 本身也是一个需要在开发主机上被 qnn-context-binary-generator 读取和处理的中间文件。它并不是最终要部署到手机上的二进制文件。
    • --backend .../libQnnHtp.so (x86_64-linux-clang):
    • 这是什么: 这是 HTP 后端的接口库
    • 为什么是 x86_64: qnn-context-binary-generator 在编译生成最终的 .serialized.bin 文件时,需要调用 HTP 后端提供的特定功能(例如,根据你的 htp_backend_extension.json 配置来优化模型,使其与骁龙芯片的 HTP 硬件特性对齐)。这个调用过程发生在开发主机上,所以需要一个能在开发主机上运行的 HTP 后端接口库。
    • --config_file ./htp_backend_extension.json
    • 这个配置文件指明了最终的目标硬件特性(例如 socModel: "SM8550" 指向骁龙 8 Gen 2)。qnn-context-binary-generator 会结合这个配置信息和 HTP 后端库,生成一个针对指定骁龙芯片高度优化的二进制模型文件。
    • 输出:bge_8295_qnn.serialized.bin
    • 这是什么: 这是最终产物,一个与硬件平台强相关的、序列化后的二进制模型文件
    • 它的架构是? 这个 .bin 文件是 中立 的,它不依赖于 x86_64 或 aarch64。它里面包含的是为指定骁龙 HTP 优化过的指令和数据。当你在 Android 设备上使用 QNN 的 HTP 后端加载这个 .bin 文件时,HTP 驱动和固件能够直接理解并执行它。

    总结

    简单来说,整个过程可以这样理解:

    1. 准备阶段(在 x86 PC 上):
    • 使用 x86_64 的工具链处理模型、后端库和配置文件,目的是为了生成一个优化的二进制文件。
    • 这个过程就像用 aarch64-linux-android-g++ 在 x86 PC 上编译出 ARM 程序。
    1. 执行阶段(在 aarch64 Android 设备上):
    • 你将生成的 bge_8295_qnn.serialized.bin 文件和 aarch64-android 版本的 libQnnHtp.so 打包到你的 Android App 中。
    • 你的 App(通过 QNN 的 aarch64 运行时库)在手机上加载 libQnnHtp.so,然后 HTP 后端再加载并执行那个 .bin 文件,完成推理。

    所以,命令中出现的 x86_64-linux-clang 指的是工具和中间库的运行环境(你的开发机),而最终 .bin 文件的目标环境则由你的 htp_backend_extension.json 配置文件决定,也就是 aarch64-android 设备上的骁龙 HTP。

    希望这个解释能解决您的疑问!这是一个非常典型的交叉编译工作流。

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(4条)

报告相同问题?

问题事件

  • 系统已结题 10月19日
  • 已采纳回答 10月11日
  • 创建了问题 10月11日