LiteRT Next による GPU アクセラレーション

グラフィック プロセッシング ユニット(GPU)は、CPU と比較して並列スループットが非常に大きいため、ディープ ラーニングの高速化によく使用されます。LiteRT Next では、コンパイル済みモデル(CompiledModel)を作成するときにハードウェア アクセラレーションをパラメータとして指定できるため、GPU アクセラレーションの使用プロセスが簡素化されています。また、LiteRT Next では、LiteRT では提供されていない、新しく改善された GPU アクセラレーション実装も使用されます。

LiteRT Next の GPU アクセラレーションを使用すると、GPU に適した入力バッファと出力バッファを作成できます。また、GPU メモリ内のデータをゼロコピーで処理し、タスクを非同期で実行して並列処理を最大化できます。

GPU をサポートする LiteRT Next の実装例については、次のデモアプリをご覧ください。

GPU の依存関係を追加する

Kotlin または C++ アプリケーションに GPU 依存関係を追加する手順は次のとおりです。

Kotlin

Kotlin ユーザーの場合、GPU アクセラレータは組み込まれているため、スタートガイドの手順以外に追加の手順は必要ありません。

C++

C++ ユーザーの場合は、LiteRT GPU アクセラレーションを使用してアプリケーションの依存関係をビルドする必要があります。コア アプリケーション ロジックをパッケージ化する cc_binary ルール(main.cc)には、次のランタイム コンポーネントが必要です。

  • LiteRT C API 共有ライブラリ: data 属性には、LiteRT C API 共有ライブラリ(//litert/c:litert_runtime_c_api_shared_lib)と GPU 固有のコンポーネント(@litert_gpu//:jni/arm64-v8a/libLiteRtGpuAccelerator.so)を含める必要があります。
  • 属性の依存関係: 通常、deps 属性には GLES 依存関係 gles_deps() が含まれ、linkopts には gles_linkopts() が含まれます。LiteRT は Android で OpenGLES を使用することが多いため、どちらも GPU アクセラレーションに関連しています。
  • モデルファイルとその他のアセット: data 属性で指定します。

cc_binary ルールの例を次に示します。

cc_binary(
    name = "your_application",
    srcs = [
        "main.cc",
    ],
    data = [
        ...
        # litert c api shared library
        "//litert/c:litert_runtime_c_api_shared_lib",
        # GPU accelerator shared library
        "@litert_gpu//:jni/arm64-v8a/libLiteRtGpuAccelerator.so",
    ],
    linkopts = select({
        "@org_tensorflow//tensorflow:android": ["-landroid"],
        "//conditions:default": [],
    }) + gles_linkopts(), # gles link options
    deps = [
        ...
        "//litert/cc:litert_tensor_buffer", # litert cc library
        ...
    ] + gles_deps(), # gles dependencies
)

この設定により、コンパイルされたバイナリは GPU を動的に読み込み、機械学習推論の高速化に使用できます。

使ってみる

GPU アクセラレータの使用を開始するには、コンパイル済みモデル(CompiledModel)を作成するときに GPU パラメータを渡します。次のコード スニペットは、プロセス全体の基本的な実装を示しています。

C++

// 1. Load model
LITERT_ASSIGN_OR_RETURN(auto model, Model::CreateFromFile("mymodel.tflite"));

// 2. Create a compiled model targeting GPU
LITERT_ASSIGN_OR_RETURN(auto env, Environment::Create({}));
LITERT_ASSIGN_OR_RETURN(auto compiled_model, CompiledModel::Create(env, model, kLiteRtHwAcceleratorGpu));

// 3. Prepare input/output buffers
LITERT_ASSIGN_OR_RETURN(auto input_buffers, compiled_model.CreateInputBuffers());
LITERT_ASSIGN_OR_RETURN(auto output_buffers, compiled_model.CreateOutputBuffers());

// 4. Fill input data (if you have CPU-based data)
input_buffers[0].Write<float>(absl::MakeConstSpan(cpu_data, data_size));

// 5. Execute
compiled_model.Run(input_buffers, output_buffers);

// 6. Access model output
std::vector<float> data(output_data_size);
output_buffers.Read<float>(absl::MakeSpan(data));

Kotlin

// Load model and initialize runtime
val  model =
    CompiledModel.create(
        context.assets,
        "mymodel.tflite",
        CompiledModel.Options(Accelerator.GPU),
        env,
    )

// Preallocate input/output buffers
val inputBuffers = model.createInputBuffers()
val outputBuffers = model.createOutputBuffers()

// Fill the first input
inputBuffers[0].writeFloat(FloatArray(data_size) { data_value /* your data */ })

// Invoke
model.run(inputBuffers, outputBuffers)

// Read the output
val outputFloatArray = outputBuffers[0].readFloat()

詳細については、C++ を使ってみるまたは Kotlin を使ってみるのガイドをご覧ください。

LiteRT Next GPU アクセラレータ

LiteRT Next でのみ使用可能な新しい GPU アクセラレータは、大規模な行列乗算や LLM の KV キャッシュなどの AI ワークロードを、以前のバージョンよりも効率的に処理するように最適化されています。LiteRT Next GPU アクセラレータは、LiteRT バージョンと比較して次の重要な改善点があります。

  • 演算子のサポート範囲の拡大: より大規模で複雑なニューラル ネットワークを処理します。
  • バッファの相互運用性の向上: カメラ フレーム、2D テクスチャ、大規模な LLM 状態に GPU バッファを直接使用できるようにします。
  • 非同期実行のサポート: CPU 前処理と GPU 推論を重ねて実行します。

GPU アクセラレーションによるゼロコピー

ゼロコピーを使用すると、GPU は CPU がそのデータを明示的にコピーしなくても、独自のメモリ内のデータに直接アクセスできます。ゼロコピーでは、CPU メモリとの間でデータをコピーしないため、エンドツーエンドのレイテンシを大幅に短縮できます。

次のコードは、ベクター グラフィックのレンダリング用 API である OpenGL を使用したゼロコピー GPU の実装例です。このコードは、OpenGL バッファ形式の画像を LiteRT Next に直接渡します。

// Suppose you have an OpenGL buffer consisting of:
// target (GLenum), id (GLuint), size_bytes (size_t), and offset (size_t)
// Load model and compile for GPU
LITERT_ASSIGN_OR_RETURN(auto model, Model::CreateFromFile("mymodel.tflite"));
LITERT_ASSIGN_OR_RETURN(auto env, Environment::Create({}));
LITERT_ASSIGN_OR_RETURN(auto compiled_model,
    CompiledModel::Create(env, model, kLiteRtHwAcceleratorGpu));

// Create a TensorBuffer that wraps the OpenGL buffer.
LITERT_ASSIGN_OR_RETURN(auto tensor_type, model.GetInputTensorType("input_tensor_name"));
LITERT_ASSIGN_OR_RETURN(auto gl_input_buffer, TensorBuffer::CreateFromGlBuffer(env,
    tensor_type, opengl_buffer.target, opengl_buffer.id, opengl_buffer.size_bytes, opengl_buffer.offset));
std::vector<TensorBuffer> input_buffers{gl_input_buffer};
LITERT_ASSIGN_OR_RETURN(auto output_buffers, compiled_model.CreateOutputBuffers());

// Execute
compiled_model.Run(input_buffers, output_buffers);

// If your output is also GPU-backed, you can fetch an OpenCL buffer or re-wrap it as an OpenGL buffer:
LITERT_ASSIGN_OR_RETURN(auto out_cl_buffer, output_buffers[0].GetOpenClBuffer());

非同期実行

LiteRT の非同期メソッド(RunAsync() など)を使用すると、CPU または NPU を使用して他のタスクを続行しながら、GPU 推論をスケジュールできます。複雑なパイプラインでは、GPU は CPU や NPU とともに非同期で使用されることがよくあります。

次のコード スニペットは、ゼロコピー GPU アクセラレーションの例で提供されているコードを基にしています。このコードは CPU と GPU の両方を非同期で使用し、LiteRT Event を入力バッファにアタッチします。LiteRT Event は、さまざまなタイプの同期プリミティブを管理します。次のコードは、LiteRtEventTypeEglSyncFence タイプのマネージド LiteRT イベント オブジェクトを作成します。この Event オブジェクトにより、GPU が完了するまで入力バッファから読み取らないようにします。これらはすべて、CPU を介さずに行われます。

LITERT_ASSIGN_OR_RETURN(auto env, Environment::Create({}));
LITERT_ASSIGN_OR_RETURN(auto compiled_model,
    CompiledModel::Create(env, model, kLiteRtHwAcceleratorGpu));

// 1. Prepare input buffer (OpenGL buffer)
LITERT_ASSIGN_OR_RETURN(auto gl_input,
    TensorBuffer::CreateFromGlBuffer(env, tensor_type, opengl_tex));
std::vector<TensorBuffer> inputs{gl_input};
LITERT_ASSIGN_OR_RETURN(auto outputs, compiled_model.CreateOutputBuffers());

// 2. If the GL buffer is in use, create and set an event object to synchronize with the GPU.
LITERT_ASSIGN_OR_RETURN(auto input_event,
    Event::CreateManagedEvent(env, LiteRtEventTypeEglSyncFence));
inputs[0].SetEvent(std::move(input_event));

// 3. Kick off the GPU inference
compiled_model.RunAsync(inputs, outputs);

// 4. Meanwhile, do other CPU work...
// CPU Stays busy ..

// 5. Access model output
std::vector<float> data(output_data_size);
outputs[0].Read<float>(absl::MakeSpan(data));

サポートされているモデル

LiteRT Next は、次のモデルで GPU アクセラレーションをサポートしています。ベンチマークの結果は、Samsung Galaxy S24 デバイスで実施したテストに基づいています。

モデル LiteRT GPU アクセラレーション LiteRT GPU(ミリ秒)
hf_mms_300m 完全に委任されている 19.6
hf_mobilevit_small 完全に委任されている 8.7
hf_mobilevit_small_e2e 完全に委任されている 8.0
hf_wav2vec2_base_960h 完全に委任されている 9.1
hf_wav2vec2_base_960h_dynamic 完全に委任されている 9.8
isnet 完全に委任されている 43.1
timm_efficientnet 完全に委任されている 3.7
timm_nfnet 完全に委任されている 9.7
timm_regnety_120 完全に委任されている 12.1
torchaudio_deepspeech 完全に委任されている 4.6
torchaudio_wav2letter 完全に委任されている 4.8
torchvision_alexnet 完全に委任されている 3.3
torchvision_deeplabv3_mobilenet_v3_large 完全に委任されている 5.7
torchvision_deeplabv3_resnet101 完全に委任されている 35.1
torchvision_deeplabv3_resnet50 完全に委任されている 24.5
torchvision_densenet121 完全に委任されている 13.9
torchvision_efficientnet_b0 完全に委任されている 3.6
torchvision_efficientnet_b1 完全に委任されている 4.7
torchvision_efficientnet_b2 完全に委任されている 5.0
torchvision_efficientnet_b3 完全に委任されている 6.1
torchvision_efficientnet_b4 完全に委任されている 7.6
torchvision_efficientnet_b5 完全に委任されている 8.6
torchvision_efficientnet_b6 完全に委任されている 11.2
torchvision_efficientnet_b7 完全に委任されている 14.7
torchvision_fcn_resnet50 完全に委任されている 19.9
torchvision_googlenet 完全に委任されている 3.9
torchvision_inception_v3 完全に委任されている 8.6
torchvision_lraspp_mobilenet_v3_large 完全に委任されている 3.3
torchvision_mnasnet0_5 完全に委任されている 2.4
torchvision_mobilenet_v2 完全に委任されている 2.8
torchvision_mobilenet_v3_large 完全に委任されている 2.8
torchvision_mobilenet_v3_small 完全に委任されている 2.3
torchvision_resnet152 完全に委任されている 15.0
torchvision_resnet18 完全に委任されている 4.3
torchvision_resnet50 完全に委任されている 6.9
torchvision_squeezenet1_0 完全に委任されている 2.9
torchvision_squeezenet1_1 完全に委任されている 2.5
torchvision_vgg16 完全に委任されている 13.4
torchvision_wide_resnet101_2 完全に委任されている 25.0
torchvision_wide_resnet50_2 完全に委任されている 13.4
u2net_full 完全に委任されている 98.3
u2net_lite 完全に委任されている 51.4
hf_distil_whisper_small_no_cache 部分的に委任 251.9
hf_distilbert 部分的に委任 13.7
hf_tinyroberta_squad2 部分的に委任 17.1
hf_tinyroberta_squad2_dynamic_batch 部分的に委任 52.1
snapml_StyleTransferNet 部分的に委任 40.9
timm_efficientformer_l1 部分的に委任 17.6
timm_efficientformerv2_s0 部分的に委任 16.1
timm_pvt_v2_b1 部分的に委任 73.5
timm_pvt_v2_b3 部分的に委任 246.7
timm_resnest14d 部分的に委任 88.9
torchaudio_conformer 部分的に委任 21.5
torchvision_convnext_tiny 部分的に委任 8.2
torchvision_maxvit_t 一部委任済み 194.0
torchvision_shufflenet_v2 部分的に委任 9.5
torchvision_swin_tiny 部分的に委任 164.4
torchvision_video_resnet2plus1d_18 部分的に委任 6832.0
torchvision_video_swin3d_tiny 部分的に委任 2617.8
yolox_tiny 部分的に委任 11.2