LiteRT Next की मदद से जीपीयू पर तेज़ी से काम करना

सीपीयू की तुलना में, ग्राफ़िक्स प्रोसेसिंग यूनिट (जीपीयू) में एक साथ कई काम करने की सुविधा होती है. इसलिए, डीप लर्निंग को तेज़ करने के लिए आम तौर पर जीपीयू का इस्तेमाल किया जाता है. LiteRT Next, GPU ऐक्सेलरेशन का इस्तेमाल करने की प्रोसेस को आसान बनाता है. इसके लिए, यह उपयोगकर्ताओं को संकलित मॉडल (CompiledModel) बनाते समय, हार्डवेयर ऐक्सेलरेशन को पैरामीटर के तौर पर तय करने की सुविधा देता है. LiteRT Next, GPU ऐक्सेलरेशन को लागू करने के लिए एक नए और बेहतर तरीके का भी इस्तेमाल करता है. यह तरीका, LiteRT में उपलब्ध नहीं है.

LiteRT Next के जीपीयू ऐक्सेलरेशन की मदद से, जीपीयू के हिसाब से इनपुट और आउटपुट बफ़र बनाए जा सकते हैं. साथ ही, जीपीयू मेमोरी में अपने डेटा के साथ जीरो-कॉपी हासिल की जा सकती है. साथ ही, पैरलल प्रोसेसिंग को बढ़ाने के लिए, टास्क को अलग-अलग क्रम में चलाया जा सकता है.

जीपीयू के साथ LiteRT Next को लागू करने के उदाहरण के लिए, यहां दिए गए डेमो ऐप्लिकेशन देखें:

जीपीयू डिपेंडेंसी जोड़ना

अपने Kotlin या C++ ऐप्लिकेशन में GPU डिपेंडेंसी जोड़ने के लिए, यह तरीका अपनाएं.

Kotlin

Kotlin इस्तेमाल करने वाले लोगों के लिए, जीपीयू ऐक्सेलरेटर पहले से मौजूद होता है. इसके लिए, शुरू करें गाइड के अलावा कोई और चरण पूरा करने की ज़रूरत नहीं होती.

C++

C++ उपयोगकर्ताओं के लिए, आपको LiteRT GPU ऐक्सेलरेशन की मदद से ऐप्लिकेशन की डिपेंडेंसी बनानी होंगी. 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 डिपेंडेंसी gles_deps() शामिल होती हैं. साथ ही, linkopts में आम तौर पर gles_linkopts() शामिल होता है. दोनों, GPU एक्सेलरेशन के लिए काफ़ी काम के हैं, क्योंकि अक्सर LiteRT, Android पर OpenGLES का इस्तेमाल करता है.
  • मॉडल फ़ाइलें और अन्य ऐसेट: इन्हें 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 का इस्तेमाल किया जा सकता है.

अपनी प्रोफ़ाइल बनाना शुरू करें

जीपीयू ऐक्सेलरेटर का इस्तेमाल शुरू करने के लिए, संकलित मॉडल (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 GPU Accelerator

नया जीपीयू ऐक्सेलरेटर, सिर्फ़ LiteRT Next के साथ उपलब्ध है. इसे एआई के ज़्यादा से ज़्यादा वर्कलोड को मैनेज करने के लिए ऑप्टिमाइज़ किया गया है. जैसे, एलएलएम के लिए बड़ी मैट्रिक्स का गुणा और केवी कैश मेमोरी. यह पिछले वर्शन के मुकाबले ज़्यादा बेहतर तरीके से काम करता है. LiteRT Next जीपीयू ऐक्सेलरेटर में, LiteRT वर्शन के मुकाबले ये मुख्य सुधार किए गए हैं:

  • बड़े ऑपरेटर कवरेज: बड़े और ज़्यादा जटिल न्यूरल नेटवर्क को हैंडल करें.
  • बफ़र के साथ बेहतर इंटरऑपरेबिलिटी: कैमरा फ़्रेम, 2D टेक्सचर या एलएलएम के बड़े स्टेटस के लिए, जीपीयू बफ़र का सीधे तौर पर इस्तेमाल करने की सुविधा चालू करें.
  • असिंक्रोनस तरीके से लागू करने की सुविधा: जीपीयू के अनुमान लगाने की प्रोसेस के साथ सीपीयू की प्री-प्रोसेसिंग को ओवरलैप करें.

जीपीयू ऐक्सेलरेशन की मदद से, डेटा को कॉपी किए बिना इस्तेमाल करना

जीपीयू, जीपीयू मेमोरी में डेटा को सीधे ऐक्सेस कर सकता है. इसके लिए, सीपीयू को डेटा को कॉपी करने की ज़रूरत नहीं होती. सीपीयू मेमोरी में डेटा को कॉपी किए बिना, ज़ीरो-कॉपी की सुविधा से एंड-टू-एंड इंतज़ार का समय काफ़ी कम हो सकता है.

यहां दिया गया कोड, 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());

एसिंक्रोनस तरीके से लागू करना

RunAsync() जैसे LiteRT के असाइनोक्रोनस तरीके, आपको सीपीयू या एनपीयू का इस्तेमाल करके अन्य टास्क जारी रखते हुए, जीपीयू इंफ़रेंस शेड्यूल करने की सुविधा देते हैं. जटिल पाइपलाइन में, सीपीयू या एनपीयू के साथ अक्सर जीपीयू का इस्तेमाल असाइन्क्रोनस तरीके से किया जाता है.

नीचे दिया गया कोड स्निपेट, जीपीयू के ज़रिए ज़ीरो-कॉपी में तेज़ी के उदाहरण में दिए गए कोड पर आधारित है. यह कोड, सीपीयू और जीपीयू, दोनों का एक साथ इस्तेमाल करता है. साथ ही, इनपुट बफ़र में LiteRT Event अटैच करता है. LiteRT Event अलग-अलग तरह के सिंक्रोनाइज़ेशन प्राइमिटिव को मैनेज करने के लिए ज़िम्मेदार है. साथ ही, यहां दिया गया कोड, LiteRtEventTypeEglSyncFence टाइप का मैनेज किया गया LiteRT इवेंट ऑब्जेक्ट बनाता है. यह Event ऑब्जेक्ट पक्का करता है कि जब तक GPU काम करता है, तब तक हम इनपुट बफ़र से न पढ़ें. यह सब सीपीयू के बिना किया जाता है.

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 डिवाइस पर किए गए टेस्ट के आधार पर हैं.

मॉडल LiteRT जीपीयू ऐक्सेलरेशन LiteRT GPU (मिलीसेकंड)
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_deepspeech पूरी तरह से अधिकार दिए गए 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