تُستخدَم وحدات معالجة الرسومات (GPU) عادةً لتسريع التعلم العميق
بسبب معدل نقل البيانات المتوازي الهائل مقارنةً بوحدات المعالجة المركزية. تعمل أداة LiteRT
Next على تبسيط عملية استخدام ميزة تسريع وحدة معالجة الرسومات من خلال السماح للمستخدمين بتحديد ميزة تسريع الأجهزة كمَعلمة عند إنشاء نموذج مجمَّع
(CompiledModel
). وتستخدم أداة LiteRT Next أيضًا عملية جديدة ومحسّنة لتنفيذ ميزة تسريع وحدة معالجة الرسومات، وهي ميزة لا تقدّمها أداة LiteRT.
باستخدام ميزة تسريع وحدة معالجة الرسومات في LiteRT Next، يمكنك إنشاء مخازن ذاكرة مؤقتة للدخل والخرج متوافقة مع وحدة معالجة الرسومات، وتحقيق ميزة "عدم إجراء أي نسخ" لبياناتك في ذاكرة وحدة معالجة الرسومات، وتنفيذ tasks بشكل غير متزامن لزيادة التوازي إلى أقصى حد.
للحصول على أمثلة على عمليات تنفيذ LiteRT Next مع ميزة دعم وحدة معالجة الرسومات، يُرجى الرجوع إلى التطبيقات التجريبية التالية:
إضافة الاعتماد على وحدة معالجة الرسومات
اتّبِع الخطوات التالية لإضافة الاعتماد على وحدة معالجة الرسومات إلى تطبيقك المكتوب بلغة Kotlin أو C++.
Kotlin
بالنسبة إلى مستخدمي Kotlin، يكون مسرع وحدة معالجة الرسومات مضمّنًا ولا يتطلّب سوى خطوات إضافية خارج دليل البدء.
C++
بالنسبة إلى مستخدمي C++، يجب إنشاء ملفات الاعتماد للتطبيق باستخدام LiteRT
تسريع وحدة معالجة الرسومات. قاعدة cc_binary
التي تحزِّم منطق التطبيق الأساسي
(مثلاً، main.cc
) تتطلّب مكونات وقت التشغيل التالية:
- مكتبة LiteRT C API المشتركة: يجب أن تتضمّن السمة
data
مكتبة LiteRT C API المشتركة (//litert/c:litert_runtime_c_api_shared_lib
) والمكونات الخاصة بوحدة معالجة الرسومات (@litert_gpu//:jni/arm64-v8a/libLiteRtGpuAccelerator.so
). - التبعيات للسمات: تتضمّن سمة
deps
عادةً تبعياتgles_deps()
لـ GLES، وتتضمّن سمةlinkopts
عادةًgles_linkopts()
. يرتبط كلاهما بشكل كبير بتسريع وحدة معالجة الرسومات، لأنّه غالبًا ما يستخدم LiteRT OpenGLES على Android. - ملفات النماذج ومواد العرض الأخرى: يتم تضمينها من خلال السمة
data
.
في ما يلي مثال على قاعدة 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
)
يتيح هذا الإعداد لملفك الثنائي المجمّع التحميل الديناميكي واستخدام وحدة معالجة الرسومات للقيام بعملية معالجة سريعة لنتائج تعلُّم الآلة.
البدء
لبدء استخدام مسرع وحدة معالجة الرسومات، عليك تمرير مَعلمة وحدة معالجة الرسومات عند إنشاء
النموذج المجمّع (CompiledModel
). يعرض مقتطف الرمز التالي تنفيذًا أساسيًا
للعملية بأكملها:
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()
لمزيد من المعلومات، يُرجى الاطّلاع على دليلَي البدء في استخدام C++ أو البدء في استخدام Kotlin.
مسرّع LiteRT Next لوحدة معالجة الرسومات
تم تحسين أداة تسريع وحدة معالجة الرسومات الجديدة، المتوفّرة فقط مع LiteRT Next، للتعامل مع مهام الذكاء الاصطناعي بكفاءة أكبر من الإصدارات السابقة، مثل عمليات ضرب المصفوفات الكبيرة وذاكرة التخزين المؤقت KV للنماذج اللغوية الكبيرة. يقدّم مسرِّع وحدة معالجة الرسومات LiteRT Next التحسينات التالية مقارنةً بإصدار LiteRT:
- تغطية موسّعة لمشغّلي الشبكات: يمكنك التعامل مع الشبكات العصبية الأكبر والأكثر تعقيدًا.
- إمكانية التشغيل التفاعلي الأفضل للذاكرة المؤقتة: يمكنك تفعيل الاستخدام المباشر لذاكرات التخزين المؤقت لوحدة معالجة الرسومات لمعالجة لقطات الكاميرا أو مواد النسيج ثنائية الأبعاد أو حالات LLM الكبيرة.
- إتاحة التنفيذ غير المتزامن: يمكنك تداخل المعالجة المُسبقة باستخدام وحدة المعالجة المركزية مع الاستنتاج باستخدام وحدة معالجة الرسومات.
ميزة "النسخ بدون نقل البيانات" مع تسريع وحدة معالجة الرسومات
من خلال استخدام تقنية "النسخ بدون نقل البيانات"، يمكن لوحدة معالجة الرسومات الوصول إلى البيانات مباشرةً في ذاكرتها الخاصة بدون الحاجة إلى أن تنسخ وحدة المعالجة المركزية هذه البيانات صراحةً. من خلال عدم نسخ البيانات إلى ذاكرة وحدة المعالجة المركزية وإزالتها منها، يمكن أن تقلل تقنية "النسخ بدون نقل البيانات" بشكل كبير من وقت الاستجابة من البداية إلى النهاية.
الرمز البرمجي التالي هو مثال على تنفيذ ميزة "وحدة معالجة الرسومات بدون نسخ" باستخدام OpenGL، وهي واجهة برمجة تطبيقات لعرض الرسومات المتجهة. تُرسِل العبارة البرمجية الصور بتنسيق مخزن OpenGL مباشرةً إلى 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());
التنفيذ غير المتزامن
تتيح لك الطرق غير المتزامنة في LiteRT، مثل RunAsync()
، جدولة الاستنتاج باستخدام وحدة معالجة الرسومات
أثناء مواصلة المهام الأخرى باستخدام وحدة المعالجة المركزية أو وحدة المعالجة العصبية. في مسارات المعالجة المعقدة، غالبًا ما يتم استخدام وحدة معالجة الرسومات
بشكل غير متزامن إلى جانب وحدة المعالجة المركزية أو وحدات المعالجة العصبية.
يستند مقتطف التعليمات البرمجية التالي إلى الرمز المقدَّم في مثال تسريع GPU
بتقنية "النسخ بدون نقل البيانات". يستخدم الرمز البرمجي كلّ من وحدة المعالجة المركزية ووحدة معالجة الرسومات
بشكل غير متزامن ويُرفِق Event
LiteRT بوحدة تخزين مؤقت للدخل. LiteRT Event
هي المسؤولة عن إدارة أنواع مختلفة من العناصر الأساسية للتزامن، وينشئ الرمز البرمجي التالي عنصر حدث LiteRT مُدارًا من النوع
LiteRtEventTypeEglSyncFence
. يضمن عنصر Event
هذا عدم قراءة
من مخزن الدخل إلى أن تنتهي وحدة معالجة الرسومات. ويتم تنفيذ كل ذلك بدون إشراك
وحدة المعالجة المركزية.
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));
النماذج المتوافقة
يتوافق LiteRT Next مع ميزة تسريع وحدة معالجة الرسومات في الطُرز التالية. تستند نتائج قياس الأداء إلى الاختبارات التي تم إجراؤها على جهاز Samsung Galaxy S24.