服务质量

从 Android 11 开始,NNAPI 通过允许应用指示其模型的相对优先级、给定模型预计准备的最长时间以及给定执行预计完成的最长时间,从而提供更优质的服务 (QoS)。此外,Android 11 还引入了其他 NNAPI 错误值,使服务能够更准确地指示发生故障时出现的问题,以便客户端应用能够更好地做出反应和恢复。

优先级

对于 Android 11 或更高版本,模型在 NN HAL 1.3 中以优先级进行准备。此优先级相对于同一应用拥有的其他准备好的模型。与较低优先级的执行相比,较高优先级的执行可以使用更多的计算资源,并且可以抢占或饿死较低优先级的执行。

包含 Priority 作为显式参数的 NN HAL 1.3 调用是 IDevice::prepareModel_1_3。请注意,IDevice::prepareModelFromCache_1_3 隐式地在缓存参数中包含 Priority

根据驱动程序和加速器的功能,有很多支持优先级的可能策略。以下是几种策略

  • 对于具有内置优先级支持的驱动程序,直接将 Priority 字段传播到加速器。
  • 使用每个应用的优先级队列来支持不同的优先级,即使在执行到达加速器之前也是如此。
  • 暂停或取消正在执行的低优先级模型,以释放加速器来执行高优先级模型。通过在低优先级模型中插入检查点来实现这一点,当到达检查点时,查询标志以确定是否应过早停止当前执行,或者通过将模型划分为子模型并在子模型执行之间查询标志来实现这一点。请注意,在以优先级准备的模型中使用检查点或子模型可能会引入额外的开销,这在 NN HAL 1.3 以下版本中没有优先级的模型中是不存在的。

    • 为了支持抢占,请保留执行上下文,包括要执行的下一个操作或子模型以及任何相关的中间操作数数据。使用此执行上下文以便稍后恢复执行。
    • 完全抢占支持不是必需的,因此无需保留执行上下文。由于 NNAPI 模型执行是确定性的,因此可以在稍后从头开始重新启动执行。

Android 使服务能够通过使用 AID (Android UID) 来区分不同的调用应用。HIDL 具有内置机制,可以通过方法 ::android::hardware::IPCThreadState::getCallingUid 检索调用应用的 UID。AID 列表可以在 libcutils/include/cutils/android_filesystem_config.h 中找到。

截止时间

从 Android 11 开始,可以使用 OptionalTimePoint 截止时间参数启动模型准备和执行。对于可以估计任务需要多长时间的驱动程序,如果驱动程序估计任务无法在截止时间之前完成,则此截止时间允许驱动程序在任务开始之前中止任务。同样,截止时间允许驱动程序中止正在进行的任务,如果它估计该任务在截止时间之前不会完成。如果任务在截止时间之前未完成或截止时间已过,则截止时间参数不会强制驱动程序中止任务。截止时间参数可用于释放驱动程序内的计算资源,并将控制权返回给应用,速度比没有截止时间时更快。

包含 OptionalTimePoint 截止时间作为参数的 NN HAL 1.3 调用是

  • IDevice::prepareModel_1_3
  • IDevice::prepareModelFromCache_1_3
  • IPreparedModel::execute_1_3
  • IPreparedModel::executeSynchronously_1_3
  • IPreparedModel::executeFenced

要查看上述每种方法的截止时间功能的参考实现,请参阅 frameworks/ml/nn/driver/sample/SampleDriver.cpp 中的 NNAPI 示例驱动程序。

错误代码

Android 11 在 NN HAL 1.3 中加入了四个错误代码值,以改进错误报告,从而使驱动程序能够更好地传达其状态,并使应用能够更优雅地恢复。以下是 ErrorStatus 中的错误代码值。

  • MISSED_DEADLINE_TRANSIENT
  • MISSED_DEADLINE_PERSISTENT
  • RESOURCE_EXHAUSTED_TRANSIENT
  • RESOURCE_EXHAUSTED_PERSISTENT

在 Android 10 或更低版本中,驱动程序只能通过 GENERAL_FAILURE 错误代码来指示失败。从 Android 11 开始,可以使用两个 MISSED_DEADLINE 错误代码来指示工作负载由于达到截止时间或驱动程序预测工作负载无法在截止时间前完成而被中止。可以使用两个 RESOURCE_EXHAUSTED 错误代码来指示任务由于驱动程序内部的资源限制而失败,例如驱动程序没有足够的内存来执行调用。

这两个错误的 TRANSIENT 版本都表示问题是暂时的,并且在短暂延迟后,将来对同一任务的调用可能会成功。例如,当驱动程序正忙于先前的长时间运行或资源密集型工作时,应返回此错误代码,但如果驱动程序不忙于先前的工作,则新任务将成功完成。这两个错误的 PERSISTENT 版本都表示将来对同一任务的调用始终预计会失败。例如,当驱动程序估计即使在理想条件下任务也无法在截止时间前完成,或者模型本身太大并超出驱动程序的资源时,应返回此错误代码。

验证

服务质量功能在 NNAPI VTS 测试 (VtsHalNeuralnetworksV1_3Target) 中进行测试。这包括一组用于验证的测试 (TestGenerated/ValidationTest#Test/),以确保驱动程序拒绝无效优先级;以及一组名为 DeadlineTest 的测试 (TestGenerated/DeadlineTest#Test/),以确保驱动程序正确处理截止时间。