Skip to main content
AI / ML
Sam Freund·2026年6月30日·← 所有文章

简介

当多个 AI 模型在 Qualcomm 设备上并发运行时,利用率的可见性变得至关重要。对于 CPU 工作负载,/proc/stat 提供了负载的直接视图。而对于基于 Hexagon DSP 的 NPU 工作负载,没有等效的标准 Linux 接口来实时展示 Q6、HVX(Hexagon Vector eXtensions)和 HMX(Hexagon Matrix eXtensions)的利用率。 没有直接的遥测数据,推理延迟只是一个间接信号。它可以表明性能发生了变化,但不能说明原因。团队无法可靠地判断加速器是否被启用、DSP 是否已饱和,或者是否还有余量运行更多模型。 本指南将带你从源码构建 libqcperf,并编写一个最小化的 C 程序,将实时 NPU 指标流式传输到你自己的应用中。

为什么现有途径不够用

官方的 Qualcomm Profiler 不适用于许多开放的工作流程,因为它需要 NDA 访问权限。 Hexagon SDK 中的 SysmonApp 可以通过 FastRPC 查询 CDSP 利用率,但它是离线流程:捕获为二进制 .bin,传输到主机,然后后处理为 HTML 或 CSV。这适用于一次性性能分析,而不是应用代码中持续的设备端遥测。 Hexagon QuRT PMU 计数器是另一个选择,但它们需要 DSP 侧的插桩,并需要用 Hexagon 工具链产物进行部署。当目标是从标准 Linux 进程进行应用层监控时,这个门槛太高了。

你将做什么

  1. 确认设备上存在 FastRPC。
  2. 克隆并构建带 NPU 后端的 libqcperf
  3. 使用 libqcperf API 编写并构建一个最小化的 C 程序。
  4. 运行它,观察实时的 Q6、HVX 和 HMX 指标流式输出到 stdout。

前提条件

libqcperf 通过 FastRPC 与 CDSP 通信。在下面的任何步骤生效之前,设备需要启用其 Qualcomm 外设并具备 FastRPC 用户态。还需要安装 DSP 服务的头文件。 请先按照 IQ8 设备页面完成设置,然后再回到这里: 重启后,确认 FastRPC 存在:
如果 /dev/fastrpc-cdsp 不存在,说明内核缺少 FastRPC 支持。这是 BSP 或镜像问题,无法在用户态修复。 你需要运行以下命令将用户添加到 fastrpc 组,然后注销并重新登录。
你还需要标准构建工具以及 DSP 头文件:

构建 libqcperf

所有工作都位于 ~/libqcperf-build 中。每个代码块都以自己的 cd 开头,因此你可以将任何代码块粘贴到新终端中,而无需记住当前处于哪个目录。

克隆仓库

配置和构建

NPU 后端默认关闭。需要显式启用它。此构建直接面向主机设备(原生 aarch64),因此不需要交叉编译工具链:
构建会生成 C 示例要链接的静态库归档:

编写 C 集成

对于应用层集成——将 NPU 遥测直接嵌入推理循环、将指标与延迟测量关联,或触发自适应行为——请直接使用 libqcperf API。 完整的生命周期是九个步骤。下面是一个最小但完整的程序,将全部四项 NPU 指标流式输出到 stdout。

程序

创建源文件:
将其保存为 ~/libqcperf-build/example/npu_monitor.c

构建示例

该示例链接前面构建产生的同一批静态库归档:

运行

预期输出(模型运行时每秒一个数据块):
Ctrl-C 停止。库在收到 SIGINT 时会干净地关闭。

深入原理

采样率与流传输率

这两个参数相互独立,用途也不同。 采样率(上例中为 100 ms)控制后台线程通过 FastRPC 调用 CDSP 读取原始硬件计数器的频率。较低的值提供更精细的时间分辨率,但会增加 FastRPC 开销。NPU 后端支持 1、5、10、50、100 和 200 ms。 流传输率(1000 ms)控制后台线程触发数据回调的频率。每次回调传递自上次传递以来收集的所有样本——在 100 ms 采样 / 1000 ms 流传输时为 10 个样本。回调以扁平的 metric_response 数组接收它们;上面的示例使用位掩码只提取每个指标的最新样本。 支持的流传输率为 100 ms 到 1000 ms,步长 100 ms。

FastRPC 路径

libqcperf 不打开内核驱动,也不读取 sysfs 文件。它通过 FastRPC 调用 sysmonquery_get_profdata——这与 llama.cpp 和 LiteRT-LM 用于将计算分派到 CDSP 的处理器间 RPC 机制相同。该调用穿过内核 FastRPC 桥(/dev/fastrpc-cdsp),并直接从 DSP 固件返回包含四个硬件计数器值的结构体。 运行时依赖是 libcdsprpc.so。这个共享库作为 FastRPC 用户态的一部分,已经存在于 Qualcomm Ubuntu 镜像中。如果它缺失,动态链接器会在到达 main 之前就无法启动进程。

后台线程

qcperf_start 会派生一个名为 qcperf_dsp_npu_thread 的后台线程。在监控会话期间,该线程拥有 FastRPC 会话。你的数据回调是从这个线程调用的,而不是调用 qcperf_start 的那个线程。保持回调足够快;任何阻塞性工作都应交给队列处理。

解读指标

实时遥测将 NPU 从黑盒变成可观测的子系统。 几个值得了解的模式: 量化推理期间 HMX 偏低是最常见的意外。如果你预期量化模型运行在 NPU 上,但 HMX 利用率接近零,说明工作负载没有走预期的加速器路径。常见原因:模型编译时未启用 HMX 算子、QNN 上下文二进制文件版本与设备上的运行时不匹配,或者模型回退到了 CPU。 HVX 高、HMX 低表明模型在向量化运行但未使用矩阵加速——这是 FP16 或非量化路径的典型特征,或者模型使用了适合 HVX 的算子(池化、归一化),但没有 INT8/INT4 矩阵乘法。 负载下 Q6 时钟逐级上升说明 DCVS 工作正常。如果利用率高时时钟不上升,请检查是否有功耗配置限制了 CDSP 频率。 推理运行时所有指标接近零通常意味着工作负载在 CPU 上执行,而不是 DSP。用 htop 确认,并检查模型的后端配置。

故障排查

后续步骤

有了实时 NPU 遥测,下一步自然是观察真实模型的运行: