LiteRT CompiledModel API, C++ dilinde kullanılabilir. Bu sayede geliştiriciler, bellek ayırma ve düşük düzeyli geliştirme üzerinde ayrıntılı kontrol sahibi olabilir. Örneğin, Image segmentation C++ App'e (Resim segmentasyonu C++ uygulaması) bakın.
Aşağıdaki kılavuzda, CompiledModel Kotlin API'nin temel CPU çıkarımı gösterilmektedir. Gelişmiş hızlandırma özellikleri için GPU hızlandırma ve NPU hızlandırma ile ilgili kılavuza bakın.
Derleme bağımlılığı ekleme
Projenize uygun yolu seçin:
Önceden oluşturulmuş kitaplığı kullanma (platformlar arası): Anında kurulum için LiteRT önceden oluşturulmuş kitaplığını kullanın. Android'de LiteRT Maven paketindeki önceden oluşturulmuş C++ kitaplığını nasıl kullanacağınızı öğrenin veya Android, iOS, macOS, Linux ve Windows'da önceden oluşturulmuş C++ ikilisini indirip entegre edin.
Kaynaktan oluşturma (platformlar arası): Tam kontrol ve çoklu platform desteği (Android, iOS, macOS, Linux, Windows) için CMake ile kaynaktan oluşturma. Ayrıntılar için bu kılavuza bakın.
Temel çıkarım
Bu bölümde, temel çıkarımın nasıl yapıldığı gösterilmektedir.
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({}));
CompiledModel oluşturun
LiteRT modeli edindikten veya bir modeli .tflite biçimine dönüştürdükten sonra, CompiledModel API'sini kullanarak çalışma zamanını model dosyasıyla 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ırmayla çalıştırın.
compiled_model.Run(input_buffers, output_buffers);
Çıkışları alma
Model çıkışını doğrudan bellekten okuyarak çıkışları alın.
std::vector<float> data(output_data_size);
output_buffers[0].Read<float>(absl::MakeSpan(data));
// ... process output data
Temel kavramlar ve bileşenler
LiteRT CompiledModel API'nin 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ı kendiniz manuel olarak 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 = CompiledModel::Create(env, "mymodel.tflite", HwAccelerators::kCpu); 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.
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 belirlenir. 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, bir giriş arabelleğinden nasıl okuma yapabileceğinizi ve bir çıkış arabelleğine nasıl yazabileceğinizi gösterir:
// 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 env, Environment::Create({}));
LITERT_ASSIGN_OR_RETURN(auto compiled_model, CompiledModel::Create(env, "mymodel.tflite",
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 CompiledModel 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 compiled_model1, CompiledModel::Create(env, "model1.tflite", 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 compiled_model2, CompiledModel::Create(env, "model2.tflite", 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);