Akselerasi GPU dengan LiteRT Next

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 GLES gles_deps(), dan linkopts biasanya menyertakan gles_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