Android Neural Networks API (NNAPI) 在所有运行 Android 8.1(API 级别 27)或更高版本的 Android 设备上可用。在具有支持的硬件加速器的 Android 设备上,它可以为 TensorFlow Lite 模型提供加速。支持的硬件加速器包括:
- 图形处理单元 (GPU)
- 数字信号处理器 (DSP)
- 神经处理单元 (NPU)
根据设备上可用的特定硬件,性能可能有所不同。
本页介绍在 Java 和 Kotlin 中如何将 NNAPI 委托与 TensorFlow Lite 解释器结合使用。对于 Android C API,请参阅 Android Native Development Kit 文档。
在自己的模型上尝试 NNAPI 委托
Gradle 导入
NNAPI 委托是 TensorFlow Lite Android 解释器(1.14.0 或更高版本)的一部分。您可以通过将以下代码添加到模块的 Gradle 文件,将其导入项目:
dependencies {
implementation 'org.tensorflow:tensorflow-lite:2.0.0'
}
初始化 NNAPI 委托
添加以下代码,先初始化 NNAPI 委托,然后再初始化 TensorFlow Lite 解释器。
注:虽然从 API 级别 27 (Android Oreo MR1) 开始就支持 NNAPI,但是,在 API 级别 28 (Android Pie) 及以后的版本上,对运算的支持大有改善。因此,对于大多数情形,我们建议开发者为 Android Pie 或更高的版本使用 NNAPI 委托。
import org.tensorflow.lite.Interpreter;
import org.tensorflow.lite.nnapi.NnApiDelegate;
Interpreter.Options options = (new Interpreter.Options());
NnApiDelegate nnApiDelegate = null;
// Initialize interpreter with NNAPI delegate for Android Pie or above
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
nnApiDelegate = new NnApiDelegate();
options.addDelegate(nnApiDelegate);
}
// Initialize TFLite interpreter
try {
tfLite = new Interpreter(loadModelFile(assetManager, modelFilename), options);
} catch (Exception e) {
throw new RuntimeException(e);
}
// Run inference
// ...
// Unload delegate
tfLite.close();
if(null != nnApiDelegate) {
nnApiDelegate.close();
}
最佳做法
在部署前测试性能
由于模型架构、大小、运算、硬件可用性和运行时硬件利用率不同,运行时性能可能会有显著差异。例如,如果某个应用使用大量 GPU 资源进行渲染,则 NNAPI 加速可能因资源竞争而无法改善性能。我们建议使用调试记录器运行简单的性能测试,以便衡量推断时间。在正式环境中启用 NNAPI 之前,先在代表您的用户群体的几部手机上运行测试。这些手机具有不同的芯片组(来自不同制造商或同一制造商的不同型号)。
对于高级开发者,TensorFlow Lite 还提供了一个适用于 Android 的模型基准测试工具。
创建设备排除列表
在正式环境中,NNAPI 可能出现无法按预期执行的情况。我们建议开发者维护一个不应将 NNAPI 加速与特定型号结合使用的设备列表。您可以根据 "ro.board.platform"
的值创建此列表。使用以下代码段可以检索该值:
String boardPlatform = "";
try {
Process sysProcess =
new ProcessBuilder("/system/bin/getprop", "ro.board.platform").
redirectErrorStream(true).start();
BufferedReader reader = new BufferedReader
(new InputStreamReader(sysProcess.getInputStream()));
String currentLine = null;
while ((currentLine=reader.readLine()) != null){
boardPlatform = line;
}
sysProcess.destroy();
} catch (IOException e) {}
Log.d("Board Platform", boardPlatform);
对于高级开发者,可以考虑通过远程配置系统维护此列表。TensorFlow 团队正在积极研究简化和自动化发现并应用最佳 NNAPI 配置的方式。
量化
通过为计算使用 8 位整数或 16 位浮点数(而不是 32 位浮点数),量化可以缩减模型大小。8 位整数模型的大小是 32 位浮点版本的四分之一;16 位浮点版本的大小则为其一半。量化可以显著提高性能,不过这可能对模型的准确率有一定影响。
目前有多种训练后量化技术可用,但是为了在最新的硬件上获得最佳支持和加速,我们建议使用全整数量化。这种方式会将权重和运算都转换成整数。此量化过程需要一个代表数据集才能运行。
使用支持的模型和运算
如果 NNAPI 委托不支持模型中的某些运算或参数组合,则框架只会在加速器上运行受支持的计算图部分。剩下的计算图将在 CPU 上运行,这会产生执行拆分。由于 CPU/加速器同步的开销很大,因此,这会导致性能比完全在 CPU 上执行整个网络时更低。
当模型仅使用支持的运算时,NNAPI 表现最佳。已知下面的模型与 NNAPI 兼容:
- MobileNet v1 (224x224) 图像分类(浮点模型下载) (量化模型下载)
(专为基于移动设备和嵌入式设备视觉应用设计的图像分类模型) - MobileNet v2 SSD 目标检测 (下载)
(使用边界框检测多个目标的图像分类模型) - MobileNet v1(300x300) 单样本检测器 (SSD) 目标检测 (下载)
- 用于姿态预测的 PoseNet (下载)
(预测图像或视频中人物姿态的视觉模型)
当模型包含动态大小的输出时,也不支持 NNAPI 加速。在这种情况下,您会收到如下所示的警告:
ERROR: Attempting to use a delegate that only supports static-sized tensors \
with a graph that has dynamic-sized tensors.
启用 NNAPI CPU 实现
无法完全由加速器处理的计算图可以回退到 NNAPI CPU 实现。但是,由于这种做法的性能通常不如 TensorFlow 解释器,因此在 Android 10(API 级别 29)或更高版本的 NNAPI 委托中,默认情况下会停用此选项。若要重写此行为,请在 NnApiDelegate.Options
对象中将 setUseNnapiCpu
设置为 true
。