LiteRT ile GPU hızlandırma

Grafik işleme birimleri (GPU'lar), CPU'lara kıyasla büyük paralel işleme kapasiteleri nedeniyle derin öğrenme hızlandırması için yaygın olarak kullanılır. LiteRT, derlenmiş bir model (CompiledModel) oluştururken kullanıcıların donanım hızlandırmayı parametre olarak belirtmesine olanak tanıyarak GPU hızlandırmayı kullanma sürecini basitleştirir.

LiteRT'nin GPU hızlandırmasıyla GPU dostu giriş ve çıkış arabellekleri oluşturabilir, GPU belleğindeki verilerinizle sıfır kopya elde edebilir ve paralelliği en üst düzeye çıkarmak için görevleri eşzamansız olarak yürütebilirsiniz.

Başlayın

GPU bağımlılığı ekleme

Kotlin veya C++ uygulamanıza GPU bağımlılığı eklemek için aşağıdaki adımları uygulayın.

Kotlin

Kotlin kullanıcıları için GPU hızlandırıcı yerleşiktir ve Başlangıç kılavuzunda belirtilenler dışında ek adım gerektirmez.

C++

C++ kullanıcıları için uygulamanın bağımlılıklarını LiteRT GPU hızlandırmasıyla oluşturmanız gerekir. Temel uygulama mantığını paketleyen cc_binary kuralı (ör. main.cc) için aşağıdaki çalışma zamanı bileşenleri gerekir:

  • LiteRT C API paylaşılan kitaplığı: data özelliği, LiteRT C API paylaşılan kitaplığını (//litert/c:litert_runtime_c_api_shared_lib) ve GPU'ya özel bileşenleri (litert_gpu_accelerator_prebuilts) içermelidir.
  • Özellik bağımlılıkları: deps özelliği genellikle GLES bağımlılıklarını gles_deps(), linkopts özelliği ise genellikle gles_linkopts() bağımlılıklarını içerir. LiteRT genellikle Android'de OpenGLES kullandığından her ikisi de GPU hızlandırma için son derece önemlidir.
  • Model dosyaları ve diğer öğeler: data özelliği aracılığıyla eklenir.

Aşağıda bir cc_binary kuralı örneği verilmiştir:

load("//litert/build_common:special_rule.bzl", "litert_gpu_accelerator_prebuilts")

cc_binary(
    name = "your_application",
    srcs = [
        "main.cc",
    ],
    data = [
        ...
        # litert c api shared library
        "//litert/c:litert_runtime_c_api_shared_lib",
    ] + litert_gpu_accelerator_prebuilts(),
    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
)

Bu kurulum, derlenmiş ikilinizin hızlandırılmış makine öğrenimi çıkarımı için GPU'yu dinamik olarak yüklemesine ve kullanmasına olanak tanır.

Önceden Oluşturulmuş GPU Hızlandırıcılar

Yeni LiteRT GPU hızlandırıcı henüz açık kaynaklı değildir. Ancak hazır bilgisayarlar mevcuttur. Kotlin kullanıcıları için LiteRT Maven paketi zaten GPU Hızlandırıcıları içerir. C++ SDK kullanıcılarının, buradan ayrı olarak indirmesi gerekir.

Bazel'de, hedefinize bağımlılık eklemek için aşağıdaki kuralı kullanabilirsiniz. cpp load("//litert/build_common:special_rule.bzl", "litert_gpu_accelerator_prebuilts")

CompiledModel API ile GPU kullanma

GPU hızlandırıcıyı kullanmaya başlamak için Derlenmiş Model'i (CompiledModel) oluştururken GPU parametresini iletin. Aşağıdaki kod snippet'inde tüm sürecin temel bir uygulaması gösterilmektedir:

C++

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

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

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

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

// 5. 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()

Daha fazla bilgi için C++ ile Başlarken veya Kotlin ile Başlarken kılavuzlarına bakın.

GPU hızlandırmasıyla sıfır kopyalama

Sıfır kopyalama, GPU'nun verileri kendi belleğinde doğrudan erişmesini sağlar. Bu durumda CPU'nun verileri açıkça kopyalaması gerekmez. Verileri CPU belleğine ve CPU belleğinden kopyalamayarak sıfır kopyalama, uçtan uca gecikmeyi önemli ölçüde azaltabilir.

Aşağıdaki kod, vektör grafiklerin oluşturulması için kullanılan bir API olan OpenGL ile Sıfır Kopyalı GPU'nun örnek bir uygulamasıdır. Kod, OpenGL arabellek biçimindeki görüntüleri doğrudan LiteRT'ye iletir:

// 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 env, Environment::Create({}));
LITERT_ASSIGN_OR_RETURN(auto compiled_model,
    CompiledModel::Create(env, "mymodel.tflite", 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());

Eşzamansız yürütme

LiteRT'nin RunAsync() gibi eşzamansız yöntemleri, CPU veya NPU kullanarak diğer görevlere devam ederken GPU çıkarımı planlamanıza olanak tanır. Karmaşık işlem hatlarında GPU, genellikle CPU veya NPU'larla birlikte eşzamansız olarak kullanılır.

Aşağıdaki kod snippet'i, Zero-copy GPU acceleration örneğinde verilen kodu temel alır. Kod, hem CPU hem de GPU'yu eşzamansız olarak kullanır ve giriş arabelleğine bir LiteRT Event ekler. LiteRT Event farklı senkronizasyon temel öğelerini yönetmekten sorumludur ve aşağıdaki kod, LiteRtEventTypeEglSyncFence türünde yönetilen bir LiteRT Event nesnesi oluşturur. Bu Event nesnesi, GPU işlemi tamamlanana kadar giriş arabelleğinden okuma yapmamamızı sağlar. Tüm bu işlemler CPU kullanılmadan yapılır.

LITERT_ASSIGN_OR_RETURN(auto env, Environment::Create({}));
LITERT_ASSIGN_OR_RETURN(auto compiled_model,
    CompiledModel::Create(env, "mymodel.tflite", 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));

Desteklenen arka uç

LiteRT, her platform için aşağıdaki GPU arka ucunu destekler.

Platform Arka uç
Android OpenCL + OpenGL
Linux WebGPU (Vulkan)
macOS Metal
Windows WebGPU (Direct3D)
Android OpenCL + OpenGL

Desteklenen modeller

LiteRT, aşağıdaki modellerde GPU hızlandırmayı destekler. Karşılaştırma testi sonuçları, Samsung Galaxy S24 cihazda çalıştırılan testlere dayanmaktadır.

Model LiteRT GPU Hızlandırma LiteRT GPU (ms)
hf_mms_300m Tam yetki verilmiş 19,6
hf_mobilevit_small Tam yetki verilmiş 8.7
hf_mobilevit_small_e2e Tam yetki verilmiş 8.0
hf_wav2vec2_base_960h Tam yetki verilmiş 9.1
hf_wav2vec2_base_960h_dynamic Tam yetki verilmiş 9,8
isnet Tam yetki verilmiş 43,1
timm_efficientnet Tam yetki verilmiş 3.7
timm_nfnet Tam yetki verilmiş 9.7
timm_regnety_120 Tam yetki verilmiş 12.1
torchaudio_deepspeech Tam yetki verilmiş 4,6
torchaudio_wav2letter Tam yetki verilmiş 4.8
torchvision_alexnet Tam yetki verilmiş 3.3
torchvision_deeplabv3_mobilenet_v3_large Tam yetki verilmiş 5.7
torchvision_deeplabv3_resnet101 Tam yetki verilmiş 35.1
torchvision_deeplabv3_resnet50 Tam yetki verilmiş 24,5
torchvision_densenet121 Tam yetki verilmiş 13,9
torchvision_efficientnet_b0 Tam yetki verilmiş 3.6
torchvision_efficientnet_b1 Tam yetki verilmiş 4,7
torchvision_efficientnet_b2 Tam yetki verilmiş 5,0
torchvision_efficientnet_b3 Tam yetki verilmiş 6.1
torchvision_efficientnet_b4 Tam yetki verilmiş 7.6
torchvision_efficientnet_b5 Tam yetki verilmiş 8.6
torchvision_efficientnet_b6 Tam yetki verilmiş 11.2
torchvision_efficientnet_b7 Tam yetki verilmiş 14.7
torchvision_fcn_resnet50 Tam yetki verilmiş 19,9
torchvision_googlenet Tam yetki verilmiş 3,9
torchvision_inception_v3 Tam yetki verilmiş 8.6
torchvision_lraspp_mobilenet_v3_large Tam yetki verilmiş 3.3
torchvision_mnasnet0_5 Tam yetki verilmiş 2.4
torchvision_mobilenet_v2 Tam yetki verilmiş 2.8
torchvision_mobilenet_v3_large Tam yetki verilmiş 2.8
torchvision_mobilenet_v3_small Tam yetki verilmiş 2.3
torchvision_resnet152 Tam yetki verilmiş 15,0
torchvision_resnet18 Tam yetki verilmiş 4,3
torchvision_resnet50 Tam yetki verilmiş 6.9
torchvision_squeezenet1_0 Tam yetki verilmiş 2.9
torchvision_squeezenet1_1 Tam yetki verilmiş 2.5
torchvision_vgg16 Tam yetki verilmiş 13.4
torchvision_wide_resnet101_2 Tam yetki verilmiş 25,0
torchvision_wide_resnet50_2 Tam yetki verilmiş 13.4
u2net_full Tam yetki verilmiş 98,3
u2net_lite Tam yetki verilmiş 51,4
hf_distil_whisper_small_no_cache Kısmen devredildi 251,90 E£
hf_distilbert Kısmen devredildi 13.7
hf_tinyroberta_squad2 Kısmen devredildi 17.1
hf_tinyroberta_squad2_dynamic_batch Kısmen devredildi 52,1
snapml_StyleTransferNet Kısmen devredildi 40,9
timm_efficientformer_l1 Kısmen devredildi 17,6
timm_efficientformerv2_s0 Kısmen devredildi 16.1
timm_pvt_v2_b1 Kısmen devredildi 73,5
timm_pvt_v2_b3 Kısmen devredildi 246,70 E£
timm_resnest14d Kısmen devredildi 88,9
torchaudio_conformer Kısmen devredildi 21,5
torchvision_convnext_tiny Kısmen devredildi 8.2
torchvision_maxvit_t Kısmen devredildi 194,0
torchvision_shufflenet_v2 Kısmen devredildi 9.5
torchvision_swin_tiny Kısmen devredildi 164,4
torchvision_video_resnet2plus1d_18 Kısmen devredildi 6832,0
torchvision_video_swin3d_tiny Kısmen devredildi 2617,8
yolox_tiny Kısmen devredildi 11.2