LiteRT Next ile GPU hızlandırma

Grafik işleme birimleri (GPU'lar), CPU'lara kıyasla büyük paralel veri işleme hızları nedeniyle genellikle derin öğrenme hızlandırması için kullanılır. LiteRT Next, kullanıcıların derlenmiş model (CompiledModel) oluştururken donanım hızlandırmayı parametre olarak belirtmesine olanak tanıyarak GPU hızlandırmayı kullanma sürecini basitleştirir. LiteRT Next ayrıca LiteRT tarafından sunulmayan yeni ve geliştirilmiş bir GPU hızlandırma uygulaması kullanır.

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

GPU desteğiyle LiteRT Next'in örnek uygulamaları için aşağıdaki demo uygulamalarına bakı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şik olduğundan Başlayın kılavuzundaki adımlardan başka bir işlem gerekmez.

C++

C++ kullanıcıları, uygulamanın bağımlılıklarını LiteRT GPU hızlandırmasıyla derlemelidir. Temel uygulama mantığını paketleyen cc_binary kuralı (ör. main.cc) aşağıdaki çalışma zamanı bileşenlerini gerektirir:

  • 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 özgü bileşenleri (@litert_gpu//:jni/arm64-v8a/libLiteRtGpuAccelerator.so) içermelidir.
  • Özellik bağımlılıkları: deps özelliği genellikle GLES bağımlılıkları gles_deps() içerir ve linkopts genellikle gles_linkopts() içerir. LiteRT genellikle Android'de OpenGLES kullandığından her ikisi de GPU hızlandırması için son derece alakalı.
  • Model dosyaları ve diğer öğeler: data özelliği aracılığıyla dahil edilir.

Aşağıda, cc_binary kuralına örnek verilmiştir:

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
)

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

Başlayın

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

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()

Daha fazla bilgi için C++'yu Kullanmaya Başlama veya Kotlin'i Kullanmaya Başlama kılavuzlarına bakın.

LiteRT Next GPU Hızlandırıcı

Yalnızca LiteRT Next ile kullanılabilen yeni GPU hızlandırıcı, büyük matris çarpımları ve LLM'ler için KV önbelleği gibi yapay zeka iş yüklerini önceki sürümlere kıyasla daha verimli bir şekilde işlemek için optimize edilmiştir. LiteRT Next GPU hızlandırıcısı, LiteRT sürümüne kıyasla aşağıdaki önemli iyileştirmeleri içerir:

  • Genişletilmiş Operatör Kapsamı: Daha büyük ve daha karmaşık sinir ağlarını işleyin.
  • Daha iyi arabellek birlikte çalışabilirliği: Kamera kareleri, 2D dokular veya büyük LLM durumları için GPU arabelleklerinin doğrudan kullanımını etkinleştirin.
  • Asenkron yürütme desteği: CPU ön işleme ile GPU çıkarımlarını çakıştırır.

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

Sıfır kopyalama, GPU'nun CPU'nun bu verileri açıkça kopyalamasına gerek kalmadan verilere doğrudan kendi belleğinden erişmesine olanak tanır. Sıfır kopyalama, verileri CPU belleğine ve bellekten kopyalamaması nedeniyle uçtan uca gecikmeyi önemli ölçüde azaltabilir.

Aşağıdaki kod, vektör grafikleri oluşturmaya yönelik bir API olan OpenGL ile sıfır kopyalama GPU'nun örnek bir uygulamasıdır. Kod, OpenGL arabellek biçimindeki resimleri doğrudan LiteRT Next'e 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 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());

Eşzamansız yürütme

LiteRT'nin RunAsync() gibi asenkron yöntemleri, CPU veya NPU'yu kullanarak diğer görevlere devam ederken GPU çıkarımlarını planlamanıza olanak tanır. Karmaşık ardışık düzenlerde GPU, genellikle CPU veya NPUs ile birlikte eşzamansız olarak kullanılır.

Aşağıdaki kod snippet'i, Boş kopya GPU hızlandırması örneğinde sağlanan kodu temel alır. Kod hem CPU'yu hem de GPU'yu eşzamansız olarak kullanır ve giriş arabelleğine bir LiteRT Event ekler. LiteRT Event, farklı türde senkronizasyon primitiflerini yönetmekten sorumludur ve aşağıdaki kod, LiteRtEventTypeEglSyncFence türüne sahip yönetilen bir LiteRT etkinlik nesnesi oluşturur. Bu Event nesnesi, GPU işlemini tamamlayana kadar giriş arabelleğinden veri okumamızı engeller. Tüm bu işlemler CPU'yu kullanmadan yapılır.

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));

Desteklenen modeller

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

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