شتاب GPU با LiteRT Next

واحدهای پردازش گرافیکی (GPU) به دلیل توان عملیاتی موازی عظیمشان در مقایسه با CPU، معمولاً برای شتاب یادگیری عمیق استفاده می شوند. LiteRT Next فرآیند استفاده از شتاب GPU را با اجازه دادن به کاربران برای تعیین شتاب سخت افزاری به عنوان پارامتر هنگام ایجاد یک مدل کامپایل شده ( CompiledModel ) ساده می کند. LiteRT Next همچنین از یک پیاده سازی جدید و بهبود یافته شتاب GPU استفاده می کند که توسط LiteRT ارائه نشده است.

با شتاب GPU LiteRT Next، می‌توانید بافرهای ورودی و خروجی سازگار با GPU ایجاد کنید، با داده‌های خود در حافظه GPU به صفر کپی بردارید، و وظایف را به صورت ناهمزمان اجرا کنید تا موازی‌سازی را به حداکثر برسانید.

برای مثال اجرای LiteRT Next با پشتیبانی از GPU، به برنامه های آزمایشی زیر مراجعه کنید:

افزودن وابستگی به GPU

از مراحل زیر برای افزودن وابستگی GPU به برنامه Kotlin یا C++ خود استفاده کنید.

کاتلین

برای کاربران Kotlin، شتاب دهنده GPU داخلی است و نیازی به مراحل اضافی فراتر از راهنمای Get Started ندارد.

C++

برای کاربران ++C، باید وابستگی های برنامه را با شتاب GPU LiteRT ایجاد کنید. قانون cc_binary که منطق برنامه اصلی را بسته بندی می کند (مثلا main.cc ) به اجزای زمان اجرا زیر نیاز دارد:

  • کتابخانه اشتراکی LiteRT C API : ویژگی data باید شامل کتابخانه مشترک LiteRT C API ( //litert/c:litert_runtime_c_api_shared_lib ) و اجزای خاص GPU ( @litert_gpu//:jni/arm64-v8a/libLiteRtGpuAccelerator.so ) باشد.
  • وابستگی‌های ویژگی : ویژگی deps معمولاً شامل وابستگی‌های GLES gles_deps() و linkopts معمولاً شامل gles_linkopts() می‌شود. هر دو برای شتاب GPU بسیار مرتبط هستند، زیرا 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
)

این تنظیمات به باینری کامپایل شده شما اجازه می دهد تا به صورت پویا بارگیری و از GPU برای استنتاج یادگیری ماشینی شتاب گرفته استفاده کند.

شروع کنید

برای شروع استفاده از شتاب دهنده GPU، هنگام ایجاد مدل Compiled ( CompiledModel ) پارامتر GPU را ارسال کنید. قطعه کد زیر یک پیاده سازی اساسی از کل فرآیند را نشان می دهد:

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

کاتلین

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

برای اطلاعات بیشتر، به راهنمای Get Started with C++ یا Get Started with Kotlin مراجعه کنید.

LiteRT Next GPU Accelerator

شتاب دهنده GPU جدید، که فقط با LiteRT Next در دسترس است، برای مدیریت بارهای کاری هوش مصنوعی، مانند ضرب ماتریس های بزرگ و حافظه نهان KV برای LLM ها، بهینه شده است، که کارآمدتر از نسخه های قبلی است. LiteRT Next GPU Accelerator بهبودهای کلیدی زیر را نسبت به نسخه LiteRT دارد:

  • پوشش گسترده اپراتور: شبکه های عصبی بزرگتر و پیچیده تر را مدیریت کنید.
  • قابلیت همکاری بهتر بافر: استفاده مستقیم از بافرهای GPU را برای فریم‌های دوربین، بافت‌های دوبعدی یا حالت‌های بزرگ LLM فعال کنید.
  • پشتیبانی از اجرای Async: پیش پردازش CPU با استنتاج GPU همپوشانی دارد.

کپی صفر با شتاب GPU

استفاده از کپی صفر، یک GPU را قادر می‌سازد تا مستقیماً به داده‌ها در حافظه خود دسترسی داشته باشد بدون اینکه نیازی به کپی کردن صریح آن داده توسط CPU باشد. با کپی نکردن داده ها از حافظه CPU و از آن، کپی صفر می تواند تأخیر انتها به انتها را به میزان قابل توجهی کاهش دهد.

کد زیر نمونه ای از پیاده سازی Zero-Copy GPU با OpenGL است، یک API برای رندر کردن گرافیک های برداری. کد تصاویر را در قالب بافر 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 را برنامه‌ریزی کنید در حالی که کارهای دیگر را با استفاده از CPU یا NPU ادامه می‌دهید. در خطوط لوله پیچیده، GPU اغلب به صورت ناهمزمان در کنار CPU یا NPU استفاده می شود.

قطعه کد زیر بر اساس کد ارائه شده در مثال شتاب GPU Zero-copy ساخته شده است. کد از CPU و GPU به صورت ناهمزمان استفاده می کند و یک Event LiteRT را به بافر ورودی متصل می کند. LiteRT Event مسئول مدیریت انواع مختلفی از همگام سازی های اولیه است و کد زیر یک شی رویداد LiteRT مدیریت شده از نوع LiteRtEventTypeEglSyncFence ایجاد می کند. این شئ Event تضمین می‌کند که تا زمانی که GPU تمام نشود، از بافر ورودی نمی‌خوانیم. همه اینها بدون دخالت CPU انجام می شود.

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 از شتاب GPU با مدل های زیر پشتیبانی می کند. نتایج بنچمارک بر اساس آزمایش‌هایی است که روی دستگاه گلکسی S24 سامسونگ انجام شده است.

مدل شتاب پردازنده گرافیکی LiteRT LiteRT GPU (ms)
hf_mms_300m کاملا تفویض شده 19.6
hf_mobilevit_small کاملا تفویض شده 8.7
hf_mobilevit_small_e2e کاملا تفویض شده 8.0
hf_wav2vec2_base_960h کاملا تفویض شده 9.1
hf_wav2vec2_base_960h_dynamic کاملا تفویض شده 9.8
isnet کاملا تفویض شده 43.1
timm_efficientnet کاملا تفویض شده 3.7
timm_nfnet کاملا تفویض شده 9.7
timm_regnety_120 کاملا تفویض شده 12.1
torchaudio_deeppeech کاملا تفویض شده 4.6
torchaudio_wav2letter کاملا تفویض شده 4.8
torchvision_alexnet کاملا تفویض شده 3.3
torchvision_deeplabv3_mobilenet_v3_large کاملا تفویض شده 5.7
torchvision_deeplabv3_resnet101 کاملا تفویض شده 35.1
torchvision_deeplabv3_resnet50 کاملا تفویض شده 24.5
torchvision_densenet121 کاملا تفویض شده 13.9
torchvision_efficientnet_b0 کاملا تفویض شده 3.6
torchvision_efficientnet_b1 کاملا تفویض شده 4.7
torchvision_efficientnet_b2 کاملا تفویض شده 5.0
torchvision_efficientnet_b3 کاملا تفویض شده 6.1
torchvision_efficientnet_b4 کاملا تفویض شده 7.6
torchvision_efficientnet_b5 کاملا تفویض شده 8.6
torchvision_efficientnet_b6 کاملا تفویض شده 11.2
torchvision_efficientnet_b7 کاملا تفویض شده 14.7
torchvision_fcn_resnet50 کاملا تفویض شده 19.9
torchvision_googlenet کاملا تفویض شده 3.9
torchvision_inception_v3 کاملا تفویض شده 8.6
torchvision_lraspp_mobilenet_v3_large کاملا تفویض شده 3.3
torchvision_mnasnet0_5 کاملا تفویض شده 2.4
torchvision_mobilenet_v2 کاملا تفویض شده 2.8
torchvision_mobilenet_v3_large کاملا تفویض شده 2.8
torchvision_mobilenet_v3_small کاملا تفویض شده 2.3
torchvision_resnet152 کاملا تفویض شده 15.0
torchvision_resnet18 کاملا تفویض شده 4.3
torchvision_resnet50 کاملا تفویض شده 6.9
torchvision_squeezenet1_0 کاملا تفویض شده 2.9
torchvision_squeezenet1_1 کاملا تفویض شده 2.5
torchvision_vgg16 کاملا تفویض شده 13.4
torchvision_wide_resnet101_2 کاملا تفویض شده 25.0
torchvision_wide_resnet50_2 کاملا تفویض شده 13.4
u2net_full کاملا تفویض شده 98.3
u2net_lite کاملا تفویض شده 51.4
hf_distil_whisper_small_no_cache تا حدی تفویض شده است 251.9
hf_distilbert تا حدی تفویض شده است 13.7
hf_tinyroberta_squad2 تا حدی تفویض شده است 17.1
hf_tinyroberta_squad2_dynamic_batch تا حدی تفویض شده است 52.1
snapml_StyleTransferNet تا حدی تفویض شده است 40.9
timm_efficientformer_l1 تا حدی تفویض شده است 17.6
timm_efficientformerv2_s0 تا حدی تفویض شده است 16.1
timm_pvt_v2_b1 تا حدی تفویض شده است 73.5
timm_pvt_v2_b3 تا حدی تفویض شده است 246.7
timm_resnest14d تا حدی تفویض شده است 88.9
torchaudio_conformer تا حدی تفویض شده است 21.5
torchvision_convnext_tiny تا حدی تفویض شده است 8.2
torchvision_maxvit_t تا حدی تفویض شده است 194.0
torchvision_shufflenet_v2 تا حدی تفویض شده است 9.5
torchvision_swin_tiny تا حدی تفویض شده است 164.4
torchvision_video_resnet2plus1d_18 تا حدی تفویض شده است 6832.0
torchvision_video_swin3d_tiny تا حدی تفویض شده است 2617.8
yolox_tiny تا حدی تفویض شده است 11.2