Google Play 服務 C 和 C++ API 中的 LiteRT

您可以在 Google Play 服務執行階段使用 LiteRT 執行機器學習 (ML) 模型,不必將 LiteRT 程式庫靜態組合到應用程式中。本指南提供相關操作說明,說明如何使用 Google Play 服務的 C 或 C++ API。

使用 Google Play 服務 C API 或 C++ API 中的 LiteRT 前,請務必安裝 CMake 建構工具。

更新建構設定

(1) 將下列依附元件新增至應用程式專案程式碼,存取 LiteRT 的 Play 服務 API:

implementation "com.google.android.gms:play-services-tflite-java:16.4.0"

請注意,雖然套件名稱結尾為 -java,但該套件也包含 C 和 C++ API。

(2) 接著,啟用 Prefab 功能,更新模組 build.gradle 檔案的 android 區塊,從 CMake 指令碼存取 C API:

buildFeatures {
  prefab = true
}

(3) [僅限 C++ API] 如果您使用 C++ API,請將 tflite-java-extract-cpp-sdk.gradle 複製到專案的 app 目錄中,並在應用程式的 Gradle 指令碼 (例如 app/build.gradle) 開頭新增下列內容:

apply from: 'tflite-java-extract-cpp-sdk.gradle'

其中包含 Gradle 程式碼,可自動從 play-services-tflite-java 的 AAR 檔案解壓縮 C++ SDK。

(4) [僅限 C++ API] 如果使用 C++ API,請找出包含應用程式 CMake 設定檔 (通常為 CMakeLists.txt) 的目錄;該目錄通常是 app/src/main/cpp 目錄。然後將 Findtflite_cc_api.cmake 複製到專案中,位於該目錄的新 Modules 子目錄中。當中包含的程式碼,會找出 Gradle 指令碼在上一個步驟中解壓縮的 C++ SDK。

(5) 最後,您需要在 CMake 腳本中新增套件 tensorflowlite_jni_gms_client (以及 C++ API 的套件 tflite_cc_api),做為依附元件,這兩個套件都是從 AAR 匯入:

C

find_package(tensorflowlite_jni_gms_client REQUIRED CONFIG)

# Set up C/C++ compiler flags to enable use of LiteRT in Play services
# (rather than regular LiteRT bundled with the app).
add_compile_definitions(TFLITE_IN_GMSCORE)
add_compile_definitions(TFLITE_WITH_STABLE_ABI)

target_link_libraries(tflite-jni # your JNI lib target
        tensorflowlite_jni_gms_client::tensorflowlite_jni_gms_client
        android # other deps for your target
        log)
      

C++

# Set up LiteRT in Play services C API (tensorflowlite_jni_gms_client) dependency.

find_package(tensorflowlite_jni_gms_client REQUIRED CONFIG)

# Set up LiteRT in Play services C++ API (tflite_cc_api) dependency.

list(PREPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/Modules")

find_package(tflite_cc_api REQUIRED MODULE)
include_directories(${tflite_cc_api_INCLUDE_DIR})
add_subdirectory(${tflite_cc_api_DIR} tflite_cc_api_build)

# Set up C/C++ compiler flags to enable use of LiteRT in Play services
# (rather than regular LiteRT bundled with the app).
add_compile_definitions(TFLITE_IN_GMSCORE)
add_compile_definitions(TFLITE_WITH_STABLE_ABI)

target_link_libraries(tflite-jni # your JNI lib target
        tflite_cc_api::tflite_cc_api
        tensorflowlite_jni_gms_client::tensorflowlite_jni_gms_client
        android # other deps for your target
        log)
      

初始化 LiteRT 執行階段

呼叫 LiteRT C 或 C++ API 之前,您必須先在 Java 或 Kotlin 程式碼中初始化 TfLiteNative 執行階段。

Java

Task tfLiteInitializeTask = TfLiteNative.initialize(context);
      

Kotlin

val tfLiteInitializeTask: Task = TfLiteNative.initialize(context)
        

使用 Google Play 服務 Task API,TfLiteNative.initialize 從 Google Play 服務將 LiteRT 執行階段非同步載入至應用程式的執行階段程序。使用 addOnSuccessListener() 確保 TfLite.initialize() 工作完成,再執行存取 LiteRT API 的程式碼。工作順利完成後,您就可以叫用所有可用的 LiteRT Native API。

實作原生程式碼

如要在 Google Play 服務中使用 LiteRT 和 C/C++ 程式碼,您可以執行下列一項 (或兩項) 操作:

  • 宣告新的 JNI 函式,從 Java 程式碼呼叫 C 或 C++ 函式
  • 從現有的 C 或 C++ 程式碼呼叫 LiteRT Native API。

JNI 函式

您可以宣告新的 JNI 函式,讓 Java/Kotlin 程式碼存取 C/C++ 程式碼中宣告的 LiteRT 執行階段,如下所示:

Java

package com.google.samples.gms.tflite.c;

public class TfLiteJni {
  static {
    System.loadLibrary("tflite-jni");
  }
  public TfLiteJni() { /**/ };
  public native void loadModel(AssetManager assetManager, String assetName);
  public native float[] runInference(float[] input);  // For example.
}
      

Kotlin

package com.google.samples.gms.tflite.c

class TfLiteJni() {
  companion object {
    init {
      System.loadLibrary("tflite-jni")
    }
  }
  external fun loadModel(assetManager: AssetManager, assetName: String)
  external fun runInference(input: FloatArray): FloatArray  // For example.
}
        

比對下列 loadModelrunInference C 或 C++ 函式:

#ifdef __cplusplus
extern "C" {
#endif

void Java_com_google_samples_gms_tflite_c_loadModel(
  JNIEnv *env, jobject tflite_jni, jobject asset_manager, jstring asset_name){
  //...
}

jfloatArray Java_com_google_samples_gms_tflite_c_TfLiteJni_runInference(
  JNIEnv* env, jobject tfliteJni, jfloatArray input) {
  //...
}

#ifdef __cplusplus
}  // extern "C".
#endif

接著,您就可以從 Java/Kotlin 程式碼呼叫 C/C++ 函式:

Java

tfLiteHandleTask.onSuccessTask(unused -> {
    TfLiteJni jni = new TfLiteJni();
    jni.loadModel(getAssets(), "add.bin");
    //...
});
    

Kotlin

tfLiteHandleTask.onSuccessTask {
    val jni = TfLiteJni()
    jni.loadModel(assets, "add.bin")
    // ...
}
      

原生程式碼中的 LiteRT

加入適當的 API 標頭檔案,將 LiteRT 納入 Google Play 服務 API:

C

#include "tensorflow/lite/c/c_api.h"
      

C++

#include "tensorflow/lite/interpreter.h"
#include "tensorflow/lite/model_builder.h"
      

然後即可使用一般的 LiteRT C 或 C++ API:

C

TfLiteModel* model = TfLiteModelCreate(model_asset, model_asset_length);
// ...
TfLiteInterpreterOptions* options = TfLiteInterpreterOptionsCreate();
// ...
TfLiteInterpreter* interpreter = TfLiteInterpreterCreate(model, options);
      

C++

  // Load the model.
  auto model = tflite::FlatBufferModel::VerifyAndBuildFromBuffer(
      model_asset, model_asset_length);
  ...
  // Initialize the interpreter.
  BuiltinOpResolver op_resolver;
  InterpreterBuilder interpreter_builder(*model, op_resolver);
  interpreter_builder(&interpreter);
  std::unique_ptr<Interpreter>` interpreter;
  interpreter_builder(&interpreter);
      

支援的 API

C

LiteRT with Google Play 服務 C API 標頭提供的 API 與一般 LiteRT C API 相同,但已淘汰或實驗性功能除外。目前可使用下列標頭的函式和型別。

TensorFlow Lite API ,用於載入及執行模型:

tensorflow/lite/c/c_api.h
tensorflow/lite/c/c_api_types.h
      

TensorFlow Lite 擴充功能 API ,用於定義自訂作業和委派 (例如用於硬體加速):

tensorflow/lite/c/c_api_opaque.h
tensorflow/lite/c/common.h
tensorflow/lite/c/builtin_op_data.h
tensorflow/lite/builtin_ops.h
      

委派外掛程式 API,以使用現有委派項目:

tensorflow/lite/acceleration/configuration/c/gpu_plugin.h
tensorflow/lite/acceleration/configuration/c/xnnpack_plugin.h
      

請注意,系統不支援 c_api_experimental.h 標頭中的函式。

如要使用 Google Play 服務的 LiteRT 專屬函式,請加入下列標頭:

tensorflow/lite/abi/tflite.h

C++

LiteRT with Google Play 服務 C++ API 標頭提供的 API 與一般 LiteRT C++ API 相同,但已排除已淘汰或實驗性功能,且有少數例外狀況 (詳見本節後續內容)。您可以使用下列標題的功能:

tensorflow/lite/model_builder.h
tensorflow/lite/interpreter_builder.h
tensorflow/lite/interpreter.h
tensorflow/lite/signature_runner.h
tensorflow/lite/acceleration/configuration/delegate_registry.h
tensorflow/lite/kernels/builtin_op_kernels.h
tensorflow/lite/kernels/register.h
tensorflow/lite/tools/verifier.h
      

對於 tensorflow/lite/interpreter.h,Play 服務支援的 API 會排除 tflite::Interpreter 的部分成員,因為 LiteRT 不提供穩定的 ABI:

Interpreter::variables()
Interpreter::nodes_size()
Interpreter::node_and_registration(int node_index)
Interpreter::kTensorsReservedCapacity
Interpreter::kTensorsCapacityHeadroom
Interpreter::OpProfilingString(const TfLiteRegistration&, const TfLiteNode*)
Interpreter::SetExternalContext(TfLiteExternalContextType type, TfLiteExternalContext* ctx)