Unit Pemrosesan Grafis (GPU) biasanya digunakan untuk akselerasi
deep learning karena throughput paralelnya yang masif dibandingkan dengan CPU. LiteRT
Next menyederhanakan proses penggunaan akselerasi GPU dengan memungkinkan pengguna
menentukan akselerasi hardware sebagai parameter saat membuat Model Kompilasi
(CompiledModel
). LiteRT Next juga menggunakan implementasi akselerasi GPU
baru dan yang ditingkatkan, yang tidak ditawarkan oleh LiteRT.
Dengan akselerasi GPU LiteRT Next, Anda dapat membuat buffering input dan output yang cocok dengan GPU, mencapai zero-copy dengan data Anda di memori GPU, dan menjalankan tugas secara asinkron untuk memaksimalkan paralelisme.
Untuk contoh penerapan LiteRT Next dengan dukungan GPU, 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 terintegrasi dan tidak memerlukan langkah tambahan selain panduan Memulai.
C++
Untuk pengguna C++, Anda harus mem-build dependensi aplikasi dengan akselerasi GPU LiteRT. Aturan cc_binary
yang memaketkan logika aplikasi inti
(misalnya, main.cc
) memerlukan komponen runtime berikut:
- Library bersama LiteRT C API: atribut
data
harus 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
deps
biasanya menyertakan dependensi GLESgles_deps()
, danlinkopts
biasanya menyertakangles_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 memuat dan menggunakan GPU secara dinamis untuk inferensi machine learning yang dipercepat.
Mulai
Untuk mulai menggunakan akselerator GPU, teruskan parameter GPU saat membuat
Model yang Dikompilasi (CompiledModel
). Cuplikan kode berikut menunjukkan implementasi dasar
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 informasi selengkapnya, lihat panduan Memulai C++ atau Memulai Kotlin.
Akselerator GPU LiteRT Next
GPU Accelerator baru, yang hanya tersedia dengan LiteRT Next, dioptimalkan untuk menangani workload AI, seperti perkalian matriks besar dan cache KV untuk LLM, dengan lebih efisien daripada versi sebelumnya. Akselerator GPU LiteRT Next menampilkan peningkatan utama berikut dibandingkan versi LiteRT:
- Cakupan Operator yang Diperluas: Menangani jaringan saraf yang lebih besar dan lebih kompleks.
- Interoperabilitas Buffer yang Lebih Baik: Mengaktifkan penggunaan langsung buffer GPU untuk frame kamera, tekstur 2D, atau status LLM besar.
- Dukungan Eksekusi Asinkron: Tumpang-tindih prapemrosesan CPU dengan inferensi GPU.
Zero-copy dengan akselerasi GPU
Penggunaan zero-copy memungkinkan GPU mengakses data secara langsung di memorinya sendiri tanpa memerlukan CPU untuk menyalin data tersebut secara eksplisit. Dengan tidak menyalin data ke dan dari memori CPU, zero-copy dapat secara signifikan mengurangi latensi menyeluruh.
Kode berikut adalah contoh implementasi GPU Zero-Copy dengan OpenGL, API untuk merender grafik vektor. Kode akan meneruskan gambar dalam format buffering OpenGL langsung ke 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());
Eksekusi asinkron
Metode asinkron LiteRT, seperti RunAsync()
, memungkinkan Anda menjadwalkan inferensi GPU
sembari 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
tanpa salin. Kode menggunakan CPU dan GPU secara asinkron dan melampirkan Event
LiteRT ke buffering input. LiteRT Event
bertanggung jawab untuk mengelola berbagai jenis primitif sinkronisasi, dan
kode berikut membuat objek Peristiwa LiteRT terkelola dari jenis
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 Next mendukung akselerasi GPU dengan model berikut. Hasil benchmark didasarkan pada pengujian yang dijalankan di perangkat Samsung Galaxy S24.
Model | Percepatan 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 |