尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

高通跃龙IQ-9075平台的开发记录(3): AI部署的SDK选择

高通跃龙IQ-9075平台的开发记录(3): AI部署的SDK选择 设备: 高通跃龙 IQ-9075 EVKSA8775PHexagon v73运行时: Qualcomm GenieQAIRT 2.42 附带示例源码 / 设备侧 Genie 1.14.0模型: Qwen2.5-7B-Instruct本地编译依据: Qualcomm AI Hub Models 导出代码QAIRT SDK 中 Geniequalla引擎源码板上实测引言高通 AI 部署时的SNPE、QNN、Genie 怎么选了解 QAIRT SDK 的读者都知道高通 AI 部署有三套推理 SDKSNPE、QNN、Genie。三者在文档里并列出现功能有重叠但适用场景差异很大。需要根据实际应用场景选用合适的。QAIRT官方文档对三者的定位描述是SNPE 是更简单的 API允许模型在多种处理器上执行代价是文件更大、对单个算子的控制粒度更粗QNN 面向特定处理器提供对每个算子执行方式的精细控制Genie 扩展 QNN专门服务于生成式 AI 场景。但文档没有展开讲的是实际部署中这三个 SDK 的适用边界到底在哪里。一、三者的定位SNPE是高通较早推出的 AI 推理 SDK全称 Snapdragon Neural Processing SDK品牌命名沿用的是骁龙平台的早期体系。模型格式是 DLC转换工具snpe-onnx-to-dlc和snpe-tensorflow-to-dlc负责把 ONNX 和 TensorFlow 模型转成 DLC。运行时 API 层次较高调用snpe-net-run或 SNPE C/Java API框架会自动在 CPU/GPU/DSP 之间调度算子。文档里能找到的教程和示例集中在 2D CNN图像分类、目标检测、语义分割。算子不支持的部分需要写 UDOUser Defined Op文档有专门一章讲 UDO 的写法但开发成本不低。QNN全称 Qualcomm AI Engine Direct是后来推出的底层推理引擎定位上更接近硬件。不依赖 DLC 格式直接面向 HTPHexagon Tensor Processor提供 7 种硬件后端CPU、GPU、HTP 都有。算子以 Op Package 的形式组织粒度比 SNPE 细。量化方案支持 INT8、INT16、FP16以及 w8a16INT8 权重 FP16 激活这类混合精度模式。工具链包括qnn-model-lib-generator编译模型库和qnn-context-binary-generator生成 Context Binary最终产物是.bin文件运行时用qnn-net-runCLI 或 QNN C/C API 加载执行。文档里对 HTP 架构、量化 Schema、算子包开发都有独立章节细节程度明显高于 SNPE。Genie构建在 QNN 之上专门为 LLM 推理设计。不参与模型编译——编译仍然走 QNN 工具链。Genie 消费编译好的 Context Binary在上面封装了 tokenizer、KV Cache 管理、采样temperature、top-k、top-p、流式输出。运行时 API 以 Dialog 为核心创建 Dialog、发送 Query、通过回调接收 token。文档里预置了 16 种主流 LLM 的配置模板覆盖 Llama v2/v3、Qwen2/Qwen2.5、Mistral、Phi-3.5 等。概括地说SNPE 是较早的高层 APIQNN 是后来推出的底层引擎Genie 是 QNN 上的 LLM 专用层。从 QAIRT 2.x 版本的演进来看新算子、新量化方案优先在 QNN 侧提供SNPE 侧的更新活跃度明显下降。下面以几个实际案例说明选用SDK的原则。二、跑 LLM首选 Genie以 QCS9075 上部署千问 2.5 大语言模型为例SDK 选 Genie不是 QNN 直接调用更不是 SNPE。Genie 封装了 LLM 推理的全部运行时逻辑。C 推理服务器通过dlopen动态加载libGenie.so核心调用就几行g_genie.config_create(config_str.c_str(),g_config_handle);g_genie.dialog_create(g_config_handle,g_dialog);g_genie.dialog_query(g_dialog,prompt.c_str(),GENIE_DIALOG_SENTENCE_COMPLETE,stream_callback,state);dialog_query一调token 通过回调逐个返回前端 SSE 实时显示。模型加载一次常驻内存后续请求只需重置 KV Cachedialog_reset首 token 延迟从子进程方案的 ~20 秒降到了 ~176ms。如果不用 Genie直接用 QNN C API 跑 LLM当然也可以但是很太东西需要自己实现tokenizer 的加载和编码、KV Cache 的分配和轮转、位置编码RoPE的计算、采样策略、多分片模型的串联调度。千问 2.5 的 7B 模型被分成 6 个 Context Binary每片包含一部分 Transformer 层片间数据传递和 KV Cache 同步都得自己管。而Genie 恰好以最优方式或最佳实践实现了这些。genie_config.json里写好ctx-bins列表和positional-encoding参数运行时自动处理这些。编译阶段的细节仍然属于 QNN。必须设置soc_model77和dsp_archv73否则会出现各种不可预期的异常比如输出乱码。--float_bitwidth 32不能设成 16QAIRT 2.35 有 bugweights_packingTrue必须打开否则模型体积膨胀 2 倍。这些参数走qnn-context-binary-generatorGenie 运行时不参与编译只消费编译好的.bin文件。如果用 SNPE 跑 LLM基本走不通。SNPE 没有为 LLM 设计的运行时接口DLC 格式不支持 LLM 所需的动态形状sequence length 可变和 KV Cache 机制。SNPE 的推理 API 是给定输入张量 → 得到输出张量的一次性模式没有多轮对话 增量推理的概念。高通官方的应用 demo 里LLM 相关的 ChatAppAndroid 和 Windows也都用 Genie模型是 Llama 3.2 3B分成 3 个 Context Binary。genie_config.json配好ctx-bins、positional-encoding、sampler参数htp_config.json指定soc_model和dsp_arch。两个平台做法一致。三、跑扩散模型QNN 是唯一现实选项在 Linux 上部署 Stable Diffusion 2.1目标平台 QCS9075 / QCS9100整条推理链路用 QNN 的qnn-net-run驱动。三个子模型Text Encoder、U-Net、VAE都是预编译的 QNN Context Binary量化方案 w8a16后端libQnnHtp.so。核心调用长这样qnn-net-run\--retrieve_contextunet_w8a16.bin\--backendlibQnnHtp.so\--input_listinput_list.txt\--output_dirtmp/Python 脚本负责 tokenizer、DPM-Solver 调度器、CFG 噪声组合这些轻量计算重活全部交给 HTP。每次推理通过os.system()调qnn-net-run输入输出走临时.raw文件。整个项目是一个 370 行的 Python 单文件没有 C/C 代码没有 Makefile。为什么不用 SNPE模型转换这一步就卡住了。SNPE 的snpe-onnx-to-dlc对 Stable Diffusion 2.1 这种大模型的算子覆盖不全w8a16 量化在 SNPE 工具链里没有直接对应的选项。就算转换成功运行时性能也很难达到 HTP 的最佳状态——SNPE 的调度逻辑会多一层抽象对 HTP 的直接控制力不如 QNN。为什么不用 GenieGenie 是 LLM 专用运行时API 为对话和文本生成设计。Stable Diffusion 的推理逻辑是文本编码 → 多步去噪 → 图像解码跟 Genie 的 Dialog/Query 模型对不上。用 Genie 跑扩散模型相当于拿聊天框架去做图像生成API 不匹配。高通官方 demo 里 Windows 端的 Stable Diffusion 走的是 ONNX Runtime QNN Execution Provider底层仍然是 QNN。路径不同到达 HTP 的方式一样。四、跑 3D 视觉模型QNN 的算子覆盖优势部署 3D ResNet 做视频动作识别输入 16 帧 112×112 RGB输出 Kinetics-400 的 400 类分类。目标平台 QCS6490RB3 Gen 2HTP v68。这个案例走了 Edge Impulse 的 Linux Runner 做封装但模型文件名里的qnn已经说明了一切。部署时仍然需要把 QAIRT SDK 的 QNN 库拷到设备上scp/opt/qcom/aistack/qairt/2.31.0.250130/lib/aarch64-ubuntu-gcc9.4/* userdevice:/usr/libscp.../lib/hexagon-v68/unsigned/libQnnHtpV68Skel.so userdevice:/usr/lib/rfsa/adsp/Edge Impulse Runner 底层调用的就是 QNN 的 HTP 后端.eim文件是 QNN Context Binary 的封装。Runner 在外面包了一层 HTTP 服务Node.js 应用通过端点发推理请求。架构上分两层Node.js Express 服务负责视频解码和预处理Edge Impulse Runner 负责模型推理。选 QNN 而不是 SNPE原因和扩散模型类似但不完全相同。3D ResNet 的算子3D 卷积、时序池化在 QNN 的算子包里覆盖更好。SNPE 文档里能找到的教程和示例都是 2D CNN3D 卷积在 SNPE 里需要写 UDO开发成本高。QNN 的 Op Package 机制同样支持自定义算子但 3D ResNet 的标准算子在 QNN 里已经有了不需要额外开发。如果用 SNPE3D 卷积算子大概率要手写 UDO而且 UDO 跑在 HTP 上的性能调优是个黑洞——需要自己管量化、内存布局、skel 库编译。Edge Impulse 选 QNN 后端而不是 SNPE 后端也是这个原因。五、传统 2D 视觉模型上层框架 QNN Delegate高通官方 demo 里传统的 2D 视觉应用图像分类、目标检测、语义分割、超分辨率没有直接用 QNN C API而是通过上层框架对接 QNNAndroid 端TFLite QNN Delegate。Delegate 优先级是 QNN_NPU → GPU → XNNPack(CPU)自动降级publicstaticfinalDelegateType[][]delegatePriorityOrder{{QNN_NPU,GPUv2},// NPU GPU XNNPack{GPUv2},// GPU XNNPack{}// XNNPack only (CPU)};Windows 端ONNX Runtime QNN EPqnn_options[backend_path]QnnHtp.dll;// NPUsession_options.AppendExecutionProvider(QNN,qnn_options);Ubuntu 端TFLite QNN DelegatePython 调用delegateDelegate(libQnnTFLiteDelegate.so,{backend_type:htp,htp_performance_mode:2,# burst})interpreterInterpreter(PalmDetector.tflite,experimental_delegates[delegate])这些路径最终都经过 QNN 到达 HTP只是上层封装不同。用 TFLite 或 ONNX Runtime 的好处是模型不用转格式直接用.tflite或.onnxDelegate/EP 负责把支持的算子放到 NPU 上跑不支持的留在 CPU。对 2D CNN 来说这种方式开发效率最高。SNPE 在这个场景下理论上可行——2D CNN 的算子覆盖没有问题DLC 转换工具也成熟。但 TFLite Delegate 和 ONNX Runtime EP 的生态对接都在 QNN 侧用 SNPE 意味着脱离这条路径自己走 DLC 转换 SNPE API 的老路。高通官方示例库里完全没有 SNPE 的身影说明官方的推荐方向已经明确。六、SNPE 为什么逐渐被跳过从 QAIRT 文档的更新重心和实际项目的选择来看SNPE 被跳过有几点原因。模型格式限制。SNPE 用 DLC 格式转换工具对复杂模型扩散模型、LLM、3D CNN的算子覆盖不全。QNN 用 Context Binary编译工具直接面向 HTP 架构算子支持更广。运行时 API 差距。SNPE 的推理 API 是静态的固定输入、固定输出、一次性执行。LLM 需要的 KV Cache 轮转、流式输出、动态 sequence lengthSNPE 都不原生支持。QNN 的 Graph/Context 模型更灵活Genie 在 QNN 之上补齐了 LLM 运行时。工具链演进方向。QAIRT SDK 2.x 版本的更新重心在 QNN 和 Genie。新算子、新量化方案如 w8a16、w4a16优先在 QNN 侧提供。文档里 QNN 部分有约 87 页SNPE 约 86 页页数接近但 QNN 的内容更新频率明显更高。实际项目中用到的 QNN 版本从 2.31 到 2.44不到一年跳了好几版每次都带来新的算子支持和 bug 修复。生态对接。Edge Impulse 的 Linux Runner 选了 QNN 后端AI Hub 的模型导出工具支持 QNN 运行时TFLite 的 QNN Delegate 和 ONNX Runtime 的 QNN EP 都对接 QNN。SNPE 在这些生态接口里没有位置。七、什么情况下还会考虑 SNPE这里并不是说 SNPE 没用。满足这几个条件SNPE 仍然是最佳选择模型是标准的 2D CNN图像分类、目标检测、语义分割算子在 SNPE 支持列表内模型已经用 DLC 格式部署过迁移成本高需要 SNPE 的多处理器自动调度功能SNPE 会自动在 CPU/GPU/DSP 之间分配算子QNN 需要手动指定后端目标设备的 HTP 架构较老如 v65 以下QNN 对老架构的支持可能不如 SNPE 成熟但如果是新项目模型涉及 LLM、扩散模型、3D CNN或者需要 w8a16 等新量化方案直接上 QNN 或 Genie不要在 SNPE 上花时间。八、选型决策把上面几个案例的经验归纳成几条规则。跑 LLM → Genie。Genie 封装了 LLM 运行时的全部逻辑直接调 QNN 会陷入 KV Cache 和采样策略的实现细节。在 9075 上部署千问 2.5 和高通官方 ChatApp 都验证了这条路径。动态加载libGenie.so避免了编译时对专有头文件的依赖是一个值得参考的开源兼容做法。跑扩散模型 → QNN。Genie 不支持图像生成场景。QNN 的 Context Binary 能直接控制 HTP 的量化精度和算子调度。Linux 上部署 Stable Diffusion 用qnn-net-runCLI 就完成了端到端推理不需要写 C 代码。如果后续需要更低延迟可以改为 QNN C API 直接调用去掉进程创建和文件 I/O 的开销。跑 3D 视觉模型 → QNN。3D 卷积在 SNPE 里要手写 UDOQNN 算子包里已有标准 3D 算子。不管上层用 Edge Impulse Runner 还是直接调 QNN C API底层都是 QNN HTP 后端。跑传统 2D 视觉模型 → 看平台。Android 上用 TFLite QNN DelegateDelegate 链自动处理 NPU/GPU/CPU 降级。Windows 上用 ONNX Runtime QNN EP。Ubuntu 上用 TFLite QNN Delegate 或直接用 QNN CLI。这些路径最终都经过 QNN 到达 HTP。不要用 SNPE 起新项目。如果已有 DLC 模型且运行正常维持现状。新模型走 QNN 工具链LLM 走 Genie。
返回列表