Android Neural Networks API (NNAPI) 在所有執行 Android 8.1 (API 級別 27) 或更高版本的 Android 裝置上均可使用。它為 Android 裝置上的 TensorFlow Lite 模型提供加速,支援的硬體加速器包括
- 圖形處理單元 (GPU)
- 數位訊號處理器 (DSP)
- 神經網路處理單元 (NPU)
效能會因裝置上可用的特定硬體而異。
本頁說明如何在 Java 和 Kotlin 中搭配 TensorFlow Lite Interpreter 使用 NNAPI 委派。如需 Android C API,請參閱 Android Native Developer Kit 文件。
在您自己的模型上試用 NNAPI 委派
Gradle 匯入
NNAPI 委派是 TensorFlow Lite Android Interpreter 1.14.0 或更高版本的一部分。您可以將以下內容新增至模組 gradle 檔案,將其匯入您的專案
dependencies {
implementation 'org.tensorflow:tensorflow-lite:+'
}
初始化 NNAPI 委派
在初始化 TensorFlow Lite Interpreter 之前,新增程式碼以初始化 NNAPI 委派。
kotlin
import android.content.res.AssetManager
import org.tensorflow.lite.Interpreter
import org.tensorflow.lite.nnapi.NnApiDelegate
import java.io.FileInputStream
import java.io.IOException
import java.nio.MappedByteBuffer
import java.nio.channels.FileChannel
...
val options = Interpreter.Options()
var nnApiDelegate: NnApiDelegate? = null
// Initialize interpreter with NNAPI delegate for Android Pie or above
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
nnApiDelegate = NnApiDelegate()
options.addDelegate(nnApiDelegate)
}
val assetManager = assets
// Initialize TFLite interpreter
val tfLite: Interpreter
try {
tfLite = Interpreter(loadModelFile(assetManager, "model.tflite"), options)
} catch (e: Exception) {
throw RuntimeException(e)
}
// Run inference
// ...
// Unload delegate
tfLite.close()
nnApiDelegate?.close()
...
@Throws(IOException::class)
private fun loadModelFile(assetManager: AssetManager, modelFilename: String): MappedByteBuffer {
val fileDescriptor = assetManager.openFd(modelFilename)
val inputStream = FileInputStream(fileDescriptor.fileDescriptor)
val fileChannel = inputStream.channel
val startOffset = fileDescriptor.startOffset
val declaredLength = fileDescriptor.declaredLength
return fileChannel.map(FileChannel.MapMode.READ_ONLY, startOffset, declaredLength)
}
...
java
import android.content.res.AssetManager;
import org.tensorflow.lite.Interpreter;
import org.tensorflow.lite.nnapi.NnApiDelegate;
import java.io.FileInputStream;
import java.io.IOException;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
...
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);
}
AssetManager assetManager = getAssets();
// Initialize TFLite interpreter
try {
tfLite = new Interpreter(loadModelFile(assetManager, "model.tflite"), options);
} catch (Exception e) {
throw new RuntimeException(e);
}
// Run inference
// ...
// Unload delegate
tfLite.close();
if(null != nnApiDelegate) {
nnApiDelegate.close();
}
...
private MappedByteBuffer loadModelFile(AssetManager assetManager, String modelFilename) throws IOException {
AssetFileDescriptor fileDescriptor = assetManager.openFd(modelFilename);
FileInputStream inputStream = new FileInputStream(fileDescriptor.getFileDescriptor());
FileChannel fileChannel = inputStream.getChannel();
long startOffset = fileDescriptor.getStartOffset();
long declaredLength = fileDescriptor.getDeclaredLength();
return fileChannel.map(FileChannel.MapMode.READ_ONLY, startOffset, declaredLength);
}
...
最佳做法
部署前測試效能
由於模型架構、大小、作業、硬體可用性和執行階段硬體使用率,執行階段效能可能會大幅變化。例如,如果應用程式大量使用 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 Interpreter 的效能差,因此在 Android 10 (API 級別 29) 或更高版本的 NNAPI 委派中,預設會停用此選項。若要覆寫此行為,請在 NnApiDelegate.Options
物件中將 setUseNnapiCpu
設定為 true
。