Unit Pemrosesan Grafis (GPU) umumnya digunakan untuk akselerasi deep learning karena throughput paralelnya yang sangat besar dibandingkan dengan CPU. LiteRT
menyederhanakan proses penggunaan akselerasi GPU dengan memungkinkan pengguna
menentukan akselerasi hardware sebagai parameter saat membuat Model yang Dikompilasi
(CompiledModel).
Dengan akselerasi GPU LiteRT, Anda dapat membuat buffer input dan output yang kompatibel dengan GPU, mencapai penyalinan nol dengan data Anda di memori GPU, dan menjalankan tugas secara asinkron untuk memaksimalkan paralelisme.
Untuk contoh penerapan GPU LiteRT, lihat aplikasi demo berikut:
Menambahkan dependensi GPU
Gunakan langkah-langkah berikut untuk menambahkan dependensi GPU ke aplikasi Kotlin atau C++ Anda.
Kotlin
Untuk pengguna Kotlin, akselerator GPU sudah tersedia dan tidak memerlukan langkah tambahan di luar panduan Mulai.
C++
Untuk pengguna C++, Anda harus membuat dependensi aplikasi dengan akselerasi GPU LiteRT. Aturan cc_binary yang mengemas logika aplikasi inti
(misalnya, main.cc) memerlukan komponen runtime berikut:
- Library bersama LiteRT C API: atribut
dataharus menyertakan library bersama LiteRT C API (//litert/c:litert_runtime_c_api_shared_lib) dan komponen khusus GPU (@litert_gpu//:jni/arm64-v8a/libLiteRtGpuAccelerator.so). - Dependensi atribut: Atribut
depsbiasanya mencakup dependensi GLESgles_deps(), danlinkoptsbiasanya mencakupgles_linkopts(). Keduanya sangat relevan untuk akselerasi GPU, karena LiteRT sering menggunakan OpenGLES di Android. - File model dan aset lainnya: Disertakan melalui atribut
data.
Berikut adalah contoh aturan 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
)
Penyiapan ini memungkinkan biner yang dikompilasi Anda memuat dan menggunakan GPU secara dinamis untuk inferensi machine learning yang dipercepat.
Menggunakan GPU dengan CompiledModel API
Untuk mulai menggunakan akselerator GPU, teruskan parameter GPU saat membuat
Model yang Dikompilasi (CompiledModel). Cuplikan kode berikut menunjukkan
implementasi dasar dari seluruh proses:
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()
Untuk mengetahui informasi selengkapnya, lihat panduan Mulai Menggunakan C++ atau Mulai Menggunakan Kotlin.
Tanpa salinan dengan akselerasi GPU
Penggunaan salinan nol memungkinkan GPU mengakses data secara langsung di memorinya sendiri tanpa perlu CPU menyalin data tersebut secara eksplisit. Dengan tidak menyalin data ke dan dari memori CPU, salinan nol dapat mengurangi latensi end-to-end secara signifikan.
Kode berikut adalah contoh penerapan GPU Zero-Copy dengan OpenGL, API untuk merender grafik vektor. Kode meneruskan gambar dalam format buffer OpenGL langsung ke LiteRT:
// 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());
Eksekusi asinkron
Metode asinkron LiteRT, seperti RunAsync(), memungkinkan Anda menjadwalkan inferensi GPU
sambil melanjutkan tugas lain menggunakan CPU atau NPU. Dalam pipeline yang kompleks, GPU sering digunakan secara asinkron bersama CPU atau NPU.
Cuplikan kode berikut dibuat berdasarkan kode yang diberikan dalam contoh Akselerasi GPU salinan nol. Kode menggunakan CPU dan GPU secara asinkron dan melampirkan Event LiteRT ke buffer input. LiteRT Event
bertanggung jawab untuk mengelola berbagai jenis primitif sinkronisasi, dan
kode berikut membuat objek Peristiwa LiteRT terkelola berjenis
LiteRtEventTypeEglSyncFence. Objek Event ini memastikan bahwa kita tidak membaca
dari buffer input hingga GPU selesai. Semua ini dilakukan tanpa melibatkan 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));
Model yang didukung
LiteRT mendukung akselerasi GPU dengan model berikut. Hasil benchmark didasarkan pada pengujian yang dijalankan di perangkat Samsung Galaxy S24.
| Model | Akselerasi GPU LiteRT | GPU LiteRT (ms) |
|---|---|---|
| hf_mms_300m | Didelegasikan sepenuhnya | 19,6 |
| hf_mobilevit_small | Didelegasikan sepenuhnya | 8.7 |
| hf_mobilevit_small_e2e | Didelegasikan sepenuhnya | 8.0 |
| hf_wav2vec2_base_960h | Didelegasikan sepenuhnya | 9.1 |
| hf_wav2vec2_base_960h_dynamic | Didelegasikan sepenuhnya | 9.8 |
| isnet | Didelegasikan sepenuhnya | 43.1 |
| timm_efficientnet | Didelegasikan sepenuhnya | 3.7 |
| timm_nfnet | Didelegasikan sepenuhnya | 9.7 |
| timm_regnety_120 | Didelegasikan sepenuhnya | 12.1 |
| torchaudio_deepspeech | Didelegasikan sepenuhnya | 4,6 |
| torchaudio_wav2letter | Didelegasikan sepenuhnya | 4,8 |
| torchvision_alexnet | Didelegasikan sepenuhnya | 3.3 |
| torchvision_deeplabv3_mobilenet_v3_large | Didelegasikan sepenuhnya | 5.7 |
| torchvision_deeplabv3_resnet101 | Didelegasikan sepenuhnya | 35.1 |
| torchvision_deeplabv3_resnet50 | Didelegasikan sepenuhnya | 24,5 |
| torchvision_densenet121 | Didelegasikan sepenuhnya | 13,9 |
| torchvision_efficientnet_b0 | Didelegasikan sepenuhnya | 3,6 |
| torchvision_efficientnet_b1 | Didelegasikan sepenuhnya | 4,7 |
| torchvision_efficientnet_b2 | Didelegasikan sepenuhnya | 5,0 |
| torchvision_efficientnet_b3 | Didelegasikan sepenuhnya | 6.1 |
| torchvision_efficientnet_b4 | Didelegasikan sepenuhnya | 7.6 |
| torchvision_efficientnet_b5 | Didelegasikan sepenuhnya | 8.6 |
| torchvision_efficientnet_b6 | Didelegasikan sepenuhnya | 11.2 |
| torchvision_efficientnet_b7 | Didelegasikan sepenuhnya | 14.7 |
| torchvision_fcn_resnet50 | Didelegasikan sepenuhnya | 19,9 |
| torchvision_googlenet | Didelegasikan sepenuhnya | 3,9 |
| torchvision_inception_v3 | Didelegasikan sepenuhnya | 8.6 |
| torchvision_lraspp_mobilenet_v3_large | Didelegasikan sepenuhnya | 3.3 |
| torchvision_mnasnet0_5 | Didelegasikan sepenuhnya | 2,4 |
| torchvision_mobilenet_v2 | Didelegasikan sepenuhnya | 2.8 |
| torchvision_mobilenet_v3_large | Didelegasikan sepenuhnya | 2.8 |
| torchvision_mobilenet_v3_small | Didelegasikan sepenuhnya | 2.3 |
| torchvision_resnet152 | Didelegasikan sepenuhnya | 15,0 |
| torchvision_resnet18 | Didelegasikan sepenuhnya | 4.3 |
| torchvision_resnet50 | Didelegasikan sepenuhnya | 6.9 |
| torchvision_squeezenet1_0 | Didelegasikan sepenuhnya | 2.9 |
| torchvision_squeezenet1_1 | Didelegasikan sepenuhnya | 2,5 |
| torchvision_vgg16 | Didelegasikan sepenuhnya | 13.4 |
| torchvision_wide_resnet101_2 | Didelegasikan sepenuhnya | 25,0 |
| torchvision_wide_resnet50_2 | Didelegasikan sepenuhnya | 13.4 |
| u2net_full | Didelegasikan sepenuhnya | 98,3 |
| u2net_lite | Didelegasikan sepenuhnya | 51,4 |
| hf_distil_whisper_small_no_cache | Didelegasikan sebagian | 251,9 |
| hf_distilbert | Didelegasikan sebagian | 13.7 |
| hf_tinyroberta_squad2 | Didelegasikan sebagian | 17.1 |
| hf_tinyroberta_squad2_dynamic_batch | Didelegasikan sebagian | 52.1 |
| snapml_StyleTransferNet | Didelegasikan sebagian | 40,9 |
| timm_efficientformer_l1 | Didelegasikan sebagian | 17,6 |
| timm_efficientformerv2_s0 | Didelegasikan sebagian | 16.1 |
| timm_pvt_v2_b1 | Didelegasikan sebagian | 73,5 |
| timm_pvt_v2_b3 | Didelegasikan sebagian | 246,7 |
| timm_resnest14d | Didelegasikan sebagian | 88,9 |
| torchaudio_conformer | Didelegasikan sebagian | 21,5 |
| torchvision_convnext_tiny | Didelegasikan sebagian | 8.2 |
| torchvision_maxvit_t | Didelegasikan sebagian | 194,0 |
| torchvision_shufflenet_v2 | Didelegasikan sebagian | 9.5 |
| torchvision_swin_tiny | Didelegasikan sebagian | 164,4 |
| torchvision_video_resnet2plus1d_18 | Didelegasikan sebagian | 6832.0 |
| torchvision_video_swin3d_tiny | Didelegasikan sebagian | 2617,8 |
| yolox_tiny | Didelegasikan sebagian | 11.2 |