LiteRT Compiled Model API'leri C++'ta kullanılabilir. Bu sayede Android geliştiriciler, bellek ayırma ve düşük düzeyli geliştirme üzerinde ayrıntılı kontrol sahibi olabilir.
C++ dilinde bir LiteRT uygulaması örneği için C++ ile Asenkron Segmentasyon Demosu'na bakın.
Başlayın
LiteRT Compiled Model API'yi Android uygulamanıza eklemek için aşağıdaki adımları uygulayın.
Derleme yapılandırmasını güncelleme
Bazel kullanarak GPU, NPU ve CPU hızlandırması için LiteRT ile C++ uygulaması oluşturmak, gerekli tüm bileşenlerin derlenmesini, bağlanmasını ve paketlenmesini sağlamak için bir cc_binary kuralı tanımlamayı içerir. Aşağıdaki örnek kurulum, uygulamanızın GPU, NPU ve CPU hızlandırıcılarını dinamik olarak seçmesine veya kullanmasına olanak tanır.
Bazel derleme yapılandırmanızdaki temel bileşenler şunlardır:
cc_binaryKural: Bu, C++ yürütülebilir hedefinizin (ör.name = "your_application_name").srcsÖzellik: Uygulamanızın C++ kaynak dosyalarını (ör.main.ccve diğer.ccveya.hdosyaları).dataÖzellik (Çalışma Zamanı Bağımlılıkları): Bu, uygulamanızın çalışma zamanında yüklediği paylaşılan kitaplıkları ve öğeleri paketlemek için çok önemlidir.- LiteRT Core Runtime: Ana LiteRT C API paylaşılan kitaplığı (ör.
//litert/c:litert_runtime_c_api_shared_lib). - Dispatch Libraries: LiteRT'nin donanım sürücüleriyle (ör.
//litert/vendors/qualcomm/dispatch:dispatch_api_so). - GPU Arka Uç Kitaplıkları: GPU hızlandırma için paylaşılan kitaplıklar
(ör.
"@litert_gpu//:jni/arm64-v8a/libLiteRtGpuAccelerator.so). - NPU Arka Uç Kitaplıkları: Qualcomm'un QNN HTP kitaplıkları (ör.
@qairt//:lib/aarch64-android/libQnnHtp.so,@qairt//:lib/hexagon-v79/unsigned/libQnnHtpV79Skel.so). - Model Dosyaları ve Öğeler: Eğitilmiş model dosyalarınız, test resimleriniz, gölgelendiricileriniz veya çalışma zamanında gereken diğer veriler (ör.
:model_files,:shader_files).
- LiteRT Core Runtime: Ana LiteRT C API paylaşılan kitaplığı (ör.
depsÖzellik (Derleme Zamanı Bağımlılıkları): Bu, kodunuzun derlenmesi için gereken kitaplıkları listeler.- LiteRT API'leri ve yardımcı programları: Tensor arabellekleri gibi LiteRT bileşenleri için başlıklar ve statik kitaplıklar (ör.
//litert/cc:litert_tensor_buffer). - Grafik Kitaplıkları (GPU için): GPU hızlandırıcı bunları kullanıyorsa grafik API'leriyle ilgili bağımlılıklar (ör.
gles_deps()).
- LiteRT API'leri ve yardımcı programları: Tensor arabellekleri gibi LiteRT bileşenleri için başlıklar ve statik kitaplıklar (ör.
linkoptsAttribute: Specifies options passed to the linker, which can include linking against system libraries (e.g.,-landroid(Androidgles_linkopts()derlemeleri veyagles_linkopts()ile GLES kitaplıkları).
Aşağıda bir cc_binary kuralı örneği 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",
# NPU accelerator shared library
"//litert/vendors/qualcomm/dispatch:dispatch_api_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
)
Modeli yükleme
LiteRT modeli edindikten veya bir modeli .tflite biçimine dönüştürdükten sonra Model nesnesi oluşturarak modeli yükleyin.
LITERT_ASSIGN_OR_RETURN(auto model, Model::CreateFromFile("mymodel.tflite"));
Ortamı oluşturma
Environment nesnesi, derleyici eklentisinin yolu ve GPU bağlamları gibi bileşenleri içeren bir çalışma zamanı ortamı sağlar. Environment, CompiledModel ve TensorBuffer oluşturulurken gereklidir. Aşağıdaki kod, seçenek içermeyen CPU ve GPU yürütmesi için bir Environment oluşturur:
LITERT_ASSIGN_OR_RETURN(auto env, Environment::Create({}));
Derlenmiş Modeli Oluşturma
CompiledModel API'yi kullanarak çalışma zamanını yeni oluşturulan Model nesnesiyle başlatın. Bu noktada donanım hızlandırmayı belirtebilirsiniz
(kLiteRtHwAcceleratorCpu veya kLiteRtHwAcceleratorGpu):
LITERT_ASSIGN_OR_RETURN(auto compiled_model,
CompiledModel::Create(env, model, kLiteRtHwAcceleratorCpu));
Giriş ve Çıkış Arabellekleri Oluşturma
Çıkarım için modele besleyeceğiniz giriş verilerini ve modelin çıkarım çalıştırdıktan sonra ürettiği çıkış verilerini tutmak üzere gerekli veri yapılarını (arabellekler) oluşturun.
LITERT_ASSIGN_OR_RETURN(auto input_buffers, compiled_model.CreateInputBuffers());
LITERT_ASSIGN_OR_RETURN(auto output_buffers, compiled_model.CreateOutputBuffers());
CPU belleği kullanıyorsanız girişleri doğrudan ilk giriş arabelleğine veri yazarak doldurun.
input_buffers[0].Write<float>(absl::MakeConstSpan(input_data, input_size));
Modeli çağırma
Giriş ve çıkış arabelleklerini sağlayarak Derlenmiş Modeli önceki adımlarda belirtilen model ve donanım hızlandırmasıyla çalıştırın.
compiled_model.Run(input_buffers, output_buffers);
Çıkışları alma
Model çıkışını doğrudan bellekten okuyarak çıkışları alma.
std::vector<float> data(output_data_size);
output_buffers[0].Read<float>(absl::MakeSpan(data));
// ... process output data
Temel kavramlar ve bileşenler
LiteRT Compiled Model API'lerinin temel kavramları ve bileşenleri hakkında bilgi edinmek için aşağıdaki bölümlere bakın.
Hata İşleme
LiteRT, litert::Expected veya std::expected ile benzer şekilde değer döndürmek ya da hataları yaymak için litert::Expected kullanır.absl::StatusOr Hatayı manuel olarak kendiniz kontrol edebilirsiniz.
LiteRT, kolaylık sağlamak için aşağıdaki makroları sunar:
LITERT_ASSIGN_OR_RETURN(lhs, expr),exprsonucunulhsdeğişkenine atar.exprhata üretmezse sonucu, aksi takdirde hatayı döndürür.Aşağıdaki snippet'e benzer şekilde genişler.
auto maybe_model = Model::CreateFromFile("mymodel.tflite"); if (!maybe_model) { return maybe_model.Error(); } auto model = std::move(maybe_model.Value());LITERT_ASSIGN_OR_ABORT(lhs, expr),LITERT_ASSIGN_OR_RETURNile aynı işi yapar ancak hata durumunda programı durdurur.Değerlendirmesi hata verirse
LITERT_RETURN_IF_ERROR(expr)değerini döndürür.exprLITERT_ABORT_IF_ERROR(expr),LITERT_RETURN_IF_ERRORile aynı işlevi görür ancak hata durumunda programı durdurur.
LiteRT makroları hakkında daha fazla bilgi için litert_macros.h sayfasına bakın.
Derlenmiş Model (CompiledModel)
Derlenmiş Model API'si (CompiledModel) bir modeli yüklemek, donanım hızlandırmayı uygulamak, çalışma zamanını başlatmak, giriş ve çıkış arabellekleri oluşturmak ve çıkarım çalıştırmaktan sorumludur.
Aşağıdaki basitleştirilmiş kod snippet'i, Compiled Model API'nin bir LiteRT modeli (.tflite) ve hedef donanım hızlandırıcıyı (GPU) nasıl aldığını ve çıkarım çalıştırmaya hazır derlenmiş bir model oluşturduğunu gösterir.
// Load model and initialize runtime
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, kLiteRtHwAcceleratorCpu));
Aşağıdaki basitleştirilmiş kod snippet'inde, Compiled Model API'nin nasıl giriş ve çıkış arabelleği aldığı ve derlenmiş modelle çıkarımlar yaptığı gösterilmektedir.
// Preallocate input/output buffers
LITERT_ASSIGN_OR_RETURN(auto input_buffers, compiled_model.CreateInputBuffers());
LITERT_ASSIGN_OR_RETURN(auto output_buffers, compiled_model.CreateOutputBuffers());
// Fill the first input
float input_values[] = { /* your data */ };
LITERT_RETURN_IF_ERROR(
input_buffers[0].Write<float>(absl::MakeConstSpan(input_values, /*size*/)));
// Invoke
LITERT_RETURN_IF_ERROR(compiled_model.Run(input_buffers, output_buffers));
// Read the output
std::vector<float> data(output_data_size);
LITERT_RETURN_IF_ERROR(
output_buffers[0].Read<float>(absl::MakeSpan(data)));
CompiledModel API'nin nasıl uygulandığına dair daha kapsamlı bir görünüm için litert_compiled_model.h kaynak koduna bakın.
Tensor arabelleği (TensorBuffer)
LiteRT, derlenmiş modele veri akışını yönetmek için Tensor Buffer API'yi (TensorBuffer) kullanarak G/Ç arabellek birlikte çalışabilirliği için yerleşik destek sağlar. Tensor Buffer API, yazma (Write<T>()), okuma (Read<T>()) ve CPU belleğini kilitleme olanağı sağlar.
TensorBuffer API'nin nasıl uygulandığına dair daha kapsamlı bir görünüm için litert_tensor_buffer.h kaynak koduna bakın.
Sorgu modeli giriş/çıkış şartları
Tensor arabelleği (TensorBuffer) ayırma koşulları genellikle donanım hızlandırıcı tarafından belirtilir. Giriş ve çıkış arabellekleri; hizalama, arabellek adımları ve bellek türüyle ilgili gereksinimlere sahip olabilir. Bu koşulları otomatik olarak işlemek için CreateInputBuffers gibi yardımcı işlevleri kullanabilirsiniz.
Aşağıdaki basitleştirilmiş kod snippet'inde, giriş verileri için arabellek gereksinimlerinin nasıl alınabileceği gösterilmektedir:
LITERT_ASSIGN_OR_RETURN(auto reqs, compiled_model.GetInputBufferRequirements(signature_index, input_index));
TensorBufferRequirements API'nin nasıl uygulandığına dair daha kapsamlı bir görünüm için litert_tensor_buffer_requirements.h kaynak koduna bakın.
Yönetilen Tensor Arabellekleri (TensorBuffer'lar) oluşturma
Aşağıdaki basitleştirilmiş kod snippet'inde, TensorBuffer API'sinin ilgili arabellekleri ayırdığı, yönetilen tensör arabelleklerinin nasıl oluşturulacağı gösterilmektedir:
LITERT_ASSIGN_OR_RETURN(auto tensor_buffer_cpu,
TensorBuffer::CreateManaged(env, /*buffer_type=*/kLiteRtTensorBufferTypeHostMemory,
ranked_tensor_type, buffer_size));
LITERT_ASSIGN_OR_RETURN(auto tensor_buffer_gl, TensorBuffer::CreateManaged(env,
/*buffer_type=*/kLiteRtTensorBufferTypeGlBuffer, ranked_tensor_type, buffer_size));
LITERT_ASSIGN_OR_RETURN(auto tensor_buffer_ahwb, TensorBuffer::CreateManaged(env,
/*buffer_type=*/kLiteRtTensorBufferTypeAhwb, ranked_tensor_type, buffer_size));
Sıfır kopyalama ile Tensor Buffer'lar oluşturma
Mevcut bir arabelleği Tensor Buffer olarak sarmak için (sıfır kopya) aşağıdaki kod snippet'ini kullanın:
// Create a TensorBuffer from host memory
LITERT_ASSIGN_OR_RETURN(auto tensor_buffer_from_host,
TensorBuffer::CreateFromHostMemory(env, ranked_tensor_type,
ptr_to_host_memory, buffer_size));
// Create a TensorBuffer from GlBuffer
LITERT_ASSIGN_OR_RETURN(auto tensor_buffer_from_gl,
TensorBuffer::CreateFromGlBuffer(env, ranked_tensor_type, gl_target, gl_id,
size_bytes, offset));
// Create a TensorBuffer from AHardware Buffer
LITERT_ASSIGN_OR_RETURN(auto tensor_buffer_from_ahwb,
TensorBuffer::CreateFromAhwb(env, ranked_tensor_type, ahardware_buffer, offset));
Tensor arabelleğinden okuma ve yazma
Aşağıdaki snippet'te, giriş arabelleğinden nasıl okuma yapabileceğiniz ve çıkış arabelleğine nasıl yazabileceğiniz gösterilmektedir:
// Example of reading to input buffer:
std::vector<float> input_tensor_data = {1,2};
LITERT_ASSIGN_OR_RETURN(auto write_success,
input_tensor_buffer.Write<float>(absl::MakeConstSpan(input_tensor_data)));
if(write_success){
/* Continue after successful write... */
}
// Example of writing to output buffer:
std::vector<float> data(total_elements);
LITERT_ASSIGN_OR_RETURN(auto read_success,
output_tensor_buffer.Read<float>(absl::MakeSpan(data)));
if(read_success){
/* Continue after successful read */
}
Gelişmiş: Özel donanım arabellek türleri için sıfır kopyalı arabellek birlikte çalışabilirliği
AHardwareBuffer gibi belirli arabellek türleri, diğer arabellek türleriyle birlikte çalışmaya olanak tanır. Örneğin, sıfır kopyalama ile bir AHardwareBuffer öğesinden OpenGL arabelleği oluşturulabilir. Aşağıdaki kod snippet'inde bir örnek gösterilmektedir:
LITERT_ASSIGN_OR_RETURN(auto tensor_buffer_ahwb,
TensorBuffer::CreateManaged(env, kLiteRtTensorBufferTypeAhwb,
ranked_tensor_type, buffer_size));
// Buffer interop: Get OpenGL buffer from AHWB,
// internally creating an OpenGL buffer backed by AHWB memory.
LITERT_ASSIGN_OR_RETURN(auto gl_buffer, tensor_buffer_ahwb.GetGlBuffer());
OpenCL arabellekleri AHardwareBuffer kullanılarak da oluşturulabilir:
LITERT_ASSIGN_OR_RETURN(auto cl_buffer, tensor_buffer_ahwb.GetOpenClMemory());
OpenCL ve OpenGL arasında birlikte çalışabilirliği destekleyen mobil cihazlarda, CL arabellekleri GL arabelleklerinden oluşturulabilir:
LITERT_ASSIGN_OR_RETURN(auto tensor_buffer_from_gl,
TensorBuffer::CreateFromGlBuffer(env, ranked_tensor_type, gl_target, gl_id,
size_bytes, offset));
// Creates an OpenCL buffer from the OpenGL buffer, zero-copy.
LITERT_ASSIGN_OR_RETURN(auto cl_buffer, tensor_buffer_from_gl.GetOpenClMemory());
Örnek uygulamalar
C++'taki aşağıdaki LiteRT uygulamalarına bakın.
Temel çıkarım (CPU)
Aşağıda, Başlarken bölümündeki kod snippet'lerinin kısaltılmış bir sürümü yer almaktadır. LiteRT ile çıkarımın en basit uygulamasıdır.
// Load model and initialize runtime
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,
kLiteRtHwAcceleratorCpu));
// Preallocate input/output buffers
LITERT_ASSIGN_OR_RETURN(auto input_buffers, compiled_model.CreateInputBuffers());
LITERT_ASSIGN_OR_RETURN(auto output_buffers, compiled_model.CreateOutputBuffers());
// Fill the first input
float input_values[] = { /* your data */ };
input_buffers[0].Write<float>(absl::MakeConstSpan(input_values, /*size*/));
// Invoke
compiled_model.Run(input_buffers, output_buffers);
// Read the output
std::vector<float> data(output_data_size);
output_buffers[0].Read<float>(absl::MakeSpan(data));
Ana makine belleğiyle sıfır kopyalama
LiteRT Compiled Model API, özellikle birden fazla donanım arka ucu ve sıfır kopyalı akışlarla çalışırken çıkarım işlem hatlarındaki sürtünmeyi azaltır. Aşağıdaki kod snippet'inde, giriş arabelleği oluşturulurken CreateFromHostMemory yöntemi kullanılmaktadır. Bu yöntem, ana makine belleğiyle sıfır kopyalama kullanır.
// Define an LiteRT environment to use existing EGL display and context.
const std::vector<Environment::Option> environment_options = {
{OptionTag::EglDisplay, user_egl_display},
{OptionTag::EglContext, user_egl_context}};
LITERT_ASSIGN_OR_RETURN(auto env,
Environment::Create(absl::MakeConstSpan(environment_options)));
// Load model1 and initialize runtime.
LITERT_ASSIGN_OR_RETURN(auto model1, Model::CreateFromFile("model1.tflite"));
LITERT_ASSIGN_OR_RETURN(auto compiled_model1, CompiledModel::Create(env, model1, kLiteRtHwAcceleratorGpu));
// Prepare I/O buffers. opengl_buffer is given outside from the producer.
LITERT_ASSIGN_OR_RETURN(auto tensor_type, model.GetInputTensorType("input_name0"));
// Create an input TensorBuffer based on tensor_type that wraps the given OpenGL Buffer.
LITERT_ASSIGN_OR_RETURN(auto tensor_buffer_from_opengl,
litert::TensorBuffer::CreateFromGlBuffer(env, tensor_type, opengl_buffer));
// Create an input event and attach it to the input buffer. Internally, it creates
// and inserts a fence sync object into the current EGL command queue.
LITERT_ASSIGN_OR_RETURN(auto input_event, Event::CreateManaged(env, LiteRtEventTypeEglSyncFence));
tensor_buffer_from_opengl.SetEvent(std::move(input_event));
std::vector<TensorBuffer> input_buffers;
input_buffers.push_back(std::move(tensor_buffer_from_opengl));
// Create an output TensorBuffer of the model1. It's also used as an input of the model2.
LITERT_ASSIGN_OR_RETURN(auto intermedidate_buffers, compiled_model1.CreateOutputBuffers());
// Load model2 and initialize runtime.
LITERT_ASSIGN_OR_RETURN(auto model2, Model::CreateFromFile("model2.tflite"));
LITERT_ASSIGN_OR_RETURN(auto compiled_model2, CompiledModel::Create(env, model2, kLiteRtHwAcceleratorGpu));
LITERT_ASSIGN_OR_RETURN(auto output_buffers, compiled_model2.CreateOutputBuffers());
compiled_model1.RunAsync(input_buffers, intermedidate_buffers);
compiled_model2.RunAsync(intermedidate_buffers, output_buffers);