NPU 管理器

Android 17 及更高版本支持神经处理单元 (NPU) 管理器 (com.android.npumanager),该管理器负责协调系统服务和应用工作负载之间的 NPU 资源分配和调度。通过将资源仲裁从自定义供应商守护程序移至 Android 平台,NPU 管理器可提高可预测性、防止资源匮乏、管理热边界并提升整体设备性能。

背景和动机

在 NPU 管理器出现之前,应用和系统模块直接向供应商驱动程序或专有服务提交工作负载。这种方法存在以下几个缺点:

  • 资源竞争效率低下: 繁重的机器学习工作负载(例如大语言模型 (LLM) 推理引擎或设备端视觉系统)直接与其他高优先级系统争用有限的 NPU 资源(例如 SRAM、权重内存和执行通道)。
  • 系统不稳定: 如果需求超出硬件容量,未经协调的工作负载可能会触发热节流、内存页面错误或低内存终止守护程序 (LMKD)。
  • 优先级划分效率低下: 系统服务器无法根据上下文变化调整 NPU 优先级,例如后台任务加载大型模型,而延迟敏感型相机流水线或用户助理在前台处于活跃状态。

NPU 管理器通过充当系统级仲裁器来解决这些挑战,该仲裁器会控制模型加载并根据当前设备健康状况和应用状态动态调整执行优先级。

系统架构

NPU 管理器作为在 Android 框架内运行的名为 npu 的系统服务实现。NPU 管理器将调度政策的高级别协调与低级别供应商驱动程序实现隔离开来。

下图说明了 NPU 管理器环境层:

NPU 管理器环境层

图 1. NPU 管理器环境层。

关键组件

  • 框架 API 客户端 (android.npumanager.NpuManager): 客户端用于请求模型加载预留的入口点
  • 系统服务 (npu): 一种系统服务,用于根据调度优先级规则控制模型加载审批和管理抢占命令
  • NPU 调度 HAL (android.hardware.npu): 一种基于 AIDL 的接口,用于在框架和驱动程序之间中继 Android 应用优先级回调
  • 供应商驱动程序: 一种低级别驱动程序,用于控制硬件执行块并实现低级别优先级划分机制

SDK 和框架 API

在调用低级别神经网络库或加载模型文件之前,框架客户端必须与 NpuManager 服务进行交互。为此,客户端首先定义模型加载请求,然后执行请求和审批流程。

模型加载请求

模型加载请求由 ModelLoadRequest 表示。此对象包含:

  • 唯一请求 ID
  • 估计的模型大小类,例如 NPU_MODEL_SIZE_LESS_THAN_1GBNPU_MODEL_SIZE_GREATER_THAN_2G
  • 预期优先级,例如 NPU_MODEL_PRIORITY_BACKGROUNDNPU_MODEL_PRIORITY_NORMALNPU_MODEL_PRIORITY_OPPORTUNISTIC

以下代码示例构建了一个大小限制大于 2 GB 且执行优先级为正常的 ModelLoadRequest

ModelLoadRequest request = new ModelLoadRequest.Builder(requestId)
        .setSize(NPU_MODEL_SIZE_GREATER_THAN_2G)
        .setPriority(NPU_MODEL_PRIORITY_NORMAL)
        .build();

请求和审批流程

客户端异步调用 requestCanLoadModel

npuManager.requestCanLoadModel(request, callback, executor);

当 NPU 资源可用时,框架会使用 ModelLoadRequestCallback 响应以下事件:

  • onCanLoadModel(request, status, listener):在请求获得批准时触发。客户端会收到 NpuManager.ModelLoadStatusListener 令牌。客户端在驱动程序内存中完全加载模型后,必须调用 listener.notifyModelLoaded(request)
  • onRequestUnloadModel(request)onRequestUnloadModel(request, reason):当系统遇到资源压力(例如传入的前台请求或热峰)并要求客户端释放其模型时触发。在回收 NPU 资源后,客户端会调用 listener.notifyModelUnloaded(request)
  • onModelLoadRequestComplete(request, status):通知客户端最终请求生命周期更改,例如取消。

客户端可以使用 cancelModelLoad(request) 取消待处理的邀请。

HAL 和供应商集成

如需支持 NPU 管理器,特定于设备的供应商实现必须符合 android.hardware.npu AIDL 服务接口。

调度配置

系统使用 SchedulingConfig AIDL 中定义的 SchedulingConfig AIDL 结构 IScheduling.aidl中继应用优先级:

package android.hardware.npu;

@VintfStability
parcelable SchedulingConfig {
    int minPriority;
    int maxPriority;
    int uid;
    int appPriority;
    boolean hasDirectAccess;
    boolean canAttributeOtherUid;
}

借助此结构,NPU 管理器可以协调优先级对齐。例如,如果后台应用提交了高优先级作业,则优先级会向下调整,以防止干扰前台图形。

任务状态和分析

供应商驱动程序必须向管理器报告 NPU 执行组的生命周期状态。WorkInfo 会跟踪任务(在 WorkInfo.aidl 中定义):

package android.hardware.npu;

import android.hardware.npu.NpuUuid;

@VintfStability
parcelable WorkInfo {
    int id;
    @nullable NpuUuid groupId;
    int uid;
    int debugPid;
    int originalUid;
    @nullable String debugFeatureId;
    int jobPriority;
    int effectivePriority;
    long timestampMs;
    int deviceNumber;
}

事件去抖动

调度框架支持使用调度回调注册中的 debounce_duration_ms 参数进行事件去抖动。这样可以避免日志泛滥并抑制快速通知,例如重复模型的连续开始和结束事件。

回调生命周期状态报告如下:

  • onWorkRequested:工作负载由供应商服务排队。
  • onWorkStarted:工作负载执行开始。
    • NPU_START_REASON_INITIAL:首次执行运行。
    • NPU_START_REASON_RESUMED:抢占后恢复执行。
  • onWorkEnded:工作负载执行结束。
    • NPU_END_REASON_COMPLETED:成功完成运行。
    • NPU_END_REASON_CANCELLED_USER:由客户端取消。
    • NPU_END_REASON_CANCELLED_SYSTEM:被系统政策抢占。
    • NPU_END_REASON_FAILED:执行错误或驱动程序失败。
    • NPU_END_REASON_PAUSED:因优先级较高的任务而暂时暂停。

设备就绪情况和测试

在验证设备健康状况之前,请确保这些配置已就位。

应用声明

寻求 NPU 调度优先级划分的客户端必须在其 AndroidManifest.xml 中声明 NPU 硬件功能:

<uses-feature android:name="android.hardware.npu" android:required="false" />

对于部署在较新一代合作伙伴硬件上的模型,可能需要此声明才能实现最佳引擎创建。

VTS 集成测试

可以使用 VTS 功能测试(例如 VtsHalNpuSchedulingTargetTest)验证 NPU HAL 实现。