iOS के लिए जीपीयू ऐक्सेलरेशन

अपने मशीन लर्निंग (एमएल) मॉडल को चलाने के लिए ग्राफ़िक प्रोसेसिंग यूनिट (जीपीयू) का इस्तेमाल करने से, मॉडल की परफ़ॉर्मेंस और मशीन लर्निंग की सुविधा वाले ऐप्लिकेशन का उपयोगकर्ता अनुभव आकर्षक रूप से बेहतर हो सकता है. iOS डिवाइसों पर, डेलीगेट का इस्तेमाल करके, अपने मॉडल को जीपीयू की मदद से तेज़ी से एक्ज़ीक्यूशन करने की सुविधा चालू की जा सकती है. प्रतिनिधि, TensorFlow Lite के लिए हार्डवेयर ड्राइवर के तौर पर काम करते हैं. इससे आपको जीपीयू प्रोसेसर पर अपने मॉडल का कोड चलाने की सुविधा मिलती है.

इस पेज पर बताया गया है कि iOS ऐप्लिकेशन में TensorFlow Lite मॉडल के लिए, जीपीयू से तेज़ी लाने की सुविधा कैसे चालू की जाती है. TensorFlow Lite के लिए जीपीयू डेलिगेट का इस्तेमाल करने के बारे में ज़्यादा जानने के लिए, जीपीयू डेलिगेट पेज देखें. इसमें सबसे सही तरीके और बेहतर तकनीकों के बारे में भी बताया गया है.

अनुवादक एपीआई के साथ जीपीयू का इस्तेमाल करें

TensorFlow Lite अनुवादक एपीआई मशीन लर्निंग ऐप्लिकेशन बनाने के लिए, सामान्य मकसद वाले एपीआई का सेट उपलब्ध कराता है. किसी iOS ऐप्लिकेशन में जीपीयू से जुड़ी सहायता जोड़ने के लिए, यहां दिए गए निर्देशों का पालन करें. इस गाइड में बताया गया है कि आपके पास पहले से ही ऐसा iOS ऐप्लिकेशन है जिसमें TensorFlow Lite की मदद से मशीन लर्निंग मॉडल को चलाया जा सकता है.

जीपीयू से जुड़ी सुविधा को शामिल करने के लिए, Podfile में बदलाव करें

TensorFlow Lite 2.3.0 रिलीज़ के बाद, बाइनरी साइज़ को कम करने के लिए जीपीयू डेलिगेट को पॉड से बाहर रखा गया है. TensorFlowLiteSwift पॉड के लिए एक सब-स्पेस तय करके, इन्हें शामिल किया जा सकता है:

pod 'TensorFlowLiteSwift/Metal', '~> 0.0.1-nightly',

OR

pod 'TensorFlowLiteSwift', '~> 0.0.1-nightly', :subspecs => ['Metal']

अगर आपको ऑब्जेक्टिव-सी का इस्तेमाल करना है, तो TensorFlowLiteObjC या TensorFlowLiteC का भी इस्तेमाल किया जा सकता है. ऑब्जेक्टिव-सी, 2.4.0 और इसके बाद के वर्शन या C API के लिए उपलब्ध है.

जीपीयू डेलिगेट शुरू करें और उसका इस्तेमाल करें

आपके पास TensorFlow Lite अनुवादक एपीआई के साथ, जीपीयू डेलिगेट का इस्तेमाल करने का विकल्प होता है. इसे कई प्रोग्रामिंग भाषाओं में इस्तेमाल किया जा सकता है. Swift और Objective-C का सुझाव दिया जाता है, लेकिन आप C++ और C का भी इस्तेमाल कर सकते हैं. अगर TensorFlow Lite के 2.4 से पहले के वर्शन का इस्तेमाल किया जा रहा है, तो C का इस्तेमाल करना ज़रूरी है. यहां दिए गए कोड के उदाहरणों में बताया गया है कि इनमें से हर भाषा में प्रतिनिधि को कैसे इस्तेमाल किया जाता है.

Swift

import TensorFlowLite

// Load model ...

// Initialize TensorFlow Lite interpreter with the GPU delegate.
let delegate = MetalDelegate()
if let interpreter = try Interpreter(modelPath: modelPath,
                                      delegates: [delegate]) {
  // Run inference ...
}
      

Objective-C

// Import module when using CocoaPods with module support
@import TFLTensorFlowLite;

// Or import following headers manually
#import "tensorflow/lite/objc/apis/TFLMetalDelegate.h"
#import "tensorflow/lite/objc/apis/TFLTensorFlowLite.h"

// Initialize GPU delegate
TFLMetalDelegate* metalDelegate = [[TFLMetalDelegate alloc] init];

// Initialize interpreter with model path and GPU delegate
TFLInterpreterOptions* options = [[TFLInterpreterOptions alloc] init];
NSError* error = nil;
TFLInterpreter* interpreter = [[TFLInterpreter alloc]
                                initWithModelPath:modelPath
                                          options:options
                                        delegates:@[ metalDelegate ]
                                            error:&error];
if (error != nil) { /* Error handling... */ }

if (![interpreter allocateTensorsWithError:&error]) { /* Error handling... */ }
if (error != nil) { /* Error handling... */ }

// Run inference ...
      

C++

// Set up interpreter.
auto model = FlatBufferModel::BuildFromFile(model_path);
if (!model) return false;
tflite::ops::builtin::BuiltinOpResolver op_resolver;
std::unique_ptr<Interpreter> interpreter;
InterpreterBuilder(*model, op_resolver)(&interpreter);

// Prepare GPU delegate.
auto* delegate = TFLGpuDelegateCreate(/*default options=*/nullptr);
if (interpreter->ModifyGraphWithDelegate(delegate) != kTfLiteOk) return false;

// Run inference.
WriteToInputTensor(interpreter->typed_input_tensor<float>(0));
if (interpreter->Invoke() != kTfLiteOk) return false;
ReadFromOutputTensor(interpreter->typed_output_tensor<float>(0));

// Clean up.
TFLGpuDelegateDelete(delegate);
      

C (2.4.0 से पहले)

#include "tensorflow/lite/c/c_api.h"
#include "tensorflow/lite/delegates/gpu/metal_delegate.h"

// Initialize model
TfLiteModel* model = TfLiteModelCreateFromFile(model_path);

// Initialize interpreter with GPU delegate
TfLiteInterpreterOptions* options = TfLiteInterpreterOptionsCreate();
TfLiteDelegate* delegate = TFLGPUDelegateCreate(nil);  // default config
TfLiteInterpreterOptionsAddDelegate(options, metal_delegate);
TfLiteInterpreter* interpreter = TfLiteInterpreterCreate(model, options);
TfLiteInterpreterOptionsDelete(options);

TfLiteInterpreterAllocateTensors(interpreter);

NSMutableData *input_data = [NSMutableData dataWithLength:input_size * sizeof(float)];
NSMutableData *output_data = [NSMutableData dataWithLength:output_size * sizeof(float)];
TfLiteTensor* input = TfLiteInterpreterGetInputTensor(interpreter, 0);
const TfLiteTensor* output = TfLiteInterpreterGetOutputTensor(interpreter, 0);

// Run inference
TfLiteTensorCopyFromBuffer(input, inputData.bytes, inputData.length);
TfLiteInterpreterInvoke(interpreter);
TfLiteTensorCopyToBuffer(output, outputData.mutableBytes, outputData.length);

// Clean up
TfLiteInterpreterDelete(interpreter);
TFLGpuDelegateDelete(metal_delegate);
TfLiteModelDelete(model);
      

जीपीयू एपीआई भाषा के इस्तेमाल से जुड़े नोट

  • TensorFlow Lite के 2.4.0 से पहले के वर्शन में, सिर्फ़ Objective-C के लिए C API का इस्तेमाल किया जा सकता है.
  • C++ API का इस्तेमाल सिर्फ़ तब किया जा सकता है, जब bazel का इस्तेमाल किया जा रहा हो या खुद TensorFlow Lite बनाया जा रहा हो. CocoaPods के साथ C++ एपीआई का इस्तेमाल नहीं किया जा सकता.
  • C++ के साथ जीपीयू डेलिगेट के साथ TensorFlow Lite का इस्तेमाल करने पर, TFLGpuDelegateCreate() फ़ंक्शन के ज़रिए जीपीयू का ऐक्सेस पाएं. इसके बाद, Interpreter::AllocateTensors() को कॉल करने के बजाय Interpreter::ModifyGraphWithDelegate() को दें.

रिलीज़ मोड की मदद से बनाएं और टेस्ट करें

बेहतर परफ़ॉर्मेंस और फ़ाइनल टेस्टिंग के लिए, सही मेटल एपीआई ऐक्सेलरेटर सेटिंग के साथ रिलीज़ बिल्ड बदलें. इस सेक्शन में बताया गया है कि रिलीज़ बनाने की सुविधा कैसे चालू करें और धातु से तेज़ी लाने के लिए, सेटिंग कैसे कॉन्फ़िगर करें.

रिलीज़ बिल्ड में बदलने के लिए:

  1. बिल्ड सेटिंग में बदलाव करने के लिए, प्रॉडक्ट > स्कीम > स्कीम में बदलाव करें... चुनें. इसके बाद, चलाएं चुनें.
  2. जानकारी टैब पर, बिल्ड कॉन्फ़िगरेशन को रिलीज़ में बदलें और डीबग के एक्ज़ीक्यूटेबल से सही का निशान हटाएं. रिलीज़ सेट अप कर रही हूँ
  3. विकल्प टैब पर क्लिक करें और GPU फ़्रेम कैप्चर को बंद किया गया और मेटल एपीआई की पुष्टि करके को बंद किया गया में बदलें.
    मेटल के विकल्प
सेट अप करना
  4. पक्का करें कि आपने 64-बिट आर्किटेक्चर पर सिर्फ़ रिलीज़ किए जा सकने वाले बिल्ड चुने हों. प्रोजेक्ट नेविगेटर > tflite_camera_example > PROJECT > your_project_name > बिल्ड सेटिंग में जाकर, सिर्फ़ ऐक्टिव आर्किटेक्चर > रिलीज़ करें को हां पर सेट करें. रिलीज़ के विकल्प सेट अप
कर रहे हैं.

जीपीयू से जुड़ी बेहतर सुविधा

इस सेक्शन में iOS के लिए जीपीयू डेलिगेट के बेहतर इस्तेमाल के बारे में बताया गया है. इसमें डेलिगेट विकल्प, इनपुट और आउटपुट बफ़र, और संख्या वाले मॉडल के इस्तेमाल शामिल हैं.

iOS के लिए डेलिगेट के विकल्प

जीपीयू प्रतिनिधि का कंस्ट्रक्टर, Swift API, Objective-C API, और C API में struct विकल्पों को स्वीकार करता है. nullptr (C API) को या कुछ भी (Objective-C और Swift API) को शुरू करने वाले व्यक्ति को पास करने से, डिफ़ॉल्ट विकल्प सेट हो जाते हैं. इन विकल्पों के बारे में ऊपर दिए गए 'बुनियादी इस्तेमाल' वाले उदाहरण में बताया गया है.

Swift

// THIS:
var options = MetalDelegate.Options()
options.isPrecisionLossAllowed = false
options.waitType = .passive
options.isQuantizationEnabled = true
let delegate = MetalDelegate(options: options)

// IS THE SAME AS THIS:
let delegate = MetalDelegate()
      

Objective-C

// THIS:
TFLMetalDelegateOptions* options = [[TFLMetalDelegateOptions alloc] init];
options.precisionLossAllowed = false;
options.waitType = TFLMetalDelegateThreadWaitTypePassive;
options.quantizationEnabled = true;

TFLMetalDelegate* delegate = [[TFLMetalDelegate alloc] initWithOptions:options];

// IS THE SAME AS THIS:
TFLMetalDelegate* delegate = [[TFLMetalDelegate alloc] init];
      

C

// THIS:
const TFLGpuDelegateOptions options = {
  .allow_precision_loss = false,
  .wait_type = TFLGpuDelegateWaitType::TFLGpuDelegateWaitTypePassive,
  .enable_quantization = true,
};

TfLiteDelegate* delegate = TFLGpuDelegateCreate(options);

// IS THE SAME AS THIS:
TfLiteDelegate* delegate = TFLGpuDelegateCreate(nullptr);
      

C++ API का इस्तेमाल करके इनपुट/आउटपुट बफ़र

जीपीयू पर कंप्यूटेशन के लिए, जीपीयू के पास डेटा उपलब्ध होना ज़रूरी है. आम तौर पर, इस ज़रूरत का मतलब होता है कि आपको मेमोरी कॉपी करनी होगी. अगर मुमकिन हो, तो आपको अपने डेटा को सीपीयू/जीपीयू की मेमोरी की सीमा से पार जाने से बचना चाहिए, क्योंकि इसमें बहुत ज़्यादा समय लग सकता है. आम तौर पर, इस तरह के क्रॉसिंग ज़रूरी हैं, लेकिन कुछ खास मामलों में, इनमें से किसी एक को छोड़ा जा सकता है.

अगर नेटवर्क का इनपुट जीपीयू मेमोरी में पहले से लोड की गई कोई इमेज है (उदाहरण के लिए, कैमरा फ़ीड वाली जीपीयू टेक्सचर), तो वह सीपीयू मेमोरी डाले बिना ही जीपीयू मेमोरी में बनी रह सकती है. इसी तरह, अगर नेटवर्क का आउटपुट, रेंडर की जा सकने वाली किसी इमेज के तौर पर मिलता है, जैसे कि इमेज की स्टाइल को ट्रांसफ़र करने की कार्रवाई, तो नतीजे को सीधे स्क्रीन पर दिखाया जा सकता है.

सबसे अच्छी परफ़ॉर्मेंस पाने के लिए, TensorFlow Lite की मदद से उपयोगकर्ता, TensorFlow के हार्डवेयर बफ़र में मौजूद डेटा को सीधे पढ़ सकते हैं और उसमें लिख सकते हैं. साथ ही, इससे बचने के लिए मेमोरी की कॉपी को बायपास भी कर सकते हैं.

यह मानते हुए कि इमेज इनपुट जीपीयू मेमोरी में है, आपको पहले इसे मेटल के लिए MTLBuffer ऑब्जेक्ट में बदलना होगा. TfLiteTensor को उपयोगकर्ता के तैयार किए गए MTLBuffer से TFLGpuDelegateBindMetalBufferToTensor() फ़ंक्शन से जोड़ा जा सकता है. ध्यान दें कि इस फ़ंक्शन को Interpreter::ModifyGraphWithDelegate() के बाद कॉल करना चाहिए. इसके अलावा, अनुमान आउटपुट, डिफ़ॉल्ट रूप से जीपीयू मेमोरी से सीपीयू मेमोरी में कॉपी किया जाता है. शुरू करने के दौरान, Interpreter::SetAllowBufferHandleOutput(true) को कॉल करके इस व्यवहार को बंद किया जा सकता है.

C++

#include "tensorflow/lite/delegates/gpu/metal_delegate.h"
#include "tensorflow/lite/delegates/gpu/metal_delegate_internal.h"

// ...

// Prepare GPU delegate.
auto* delegate = TFLGpuDelegateCreate(nullptr);

if (interpreter->ModifyGraphWithDelegate(delegate) != kTfLiteOk) return false;

interpreter->SetAllowBufferHandleOutput(true);  // disable default gpu->cpu copy
if (!TFLGpuDelegateBindMetalBufferToTensor(
        delegate, interpreter->inputs()[0], user_provided_input_buffer)) {
  return false;
}
if (!TFLGpuDelegateBindMetalBufferToTensor(
        delegate, interpreter->outputs()[0], user_provided_output_buffer)) {
  return false;
}

// Run inference.
if (interpreter->Invoke() != kTfLiteOk) return false;
      

डिफ़ॉल्ट व्यवहार बंद होने के बाद, अनुमानित आउटपुट आउटपुट को जीपीयू मेमोरी से सीपीयू मेमोरी में कॉपी करने के लिए, हर आउटपुट टेंसर के लिए Interpreter::EnsureTensorDataIsReadable() को साफ़ तौर पर कॉल करना ज़रूरी होता है. यह तरीका क्वांटाइज़्ड मॉडल के लिए भी काम करता है. हालांकि, आपको अब भी फ़्लोट 32 डेटा के साथ फ़्लोट32 साइज़ का बफ़र इस्तेमाल करना होगा, क्योंकि बफ़र इंटरनल डी-क्वांटाइज़्ड बफ़र से जुड़ा होता है.

क्वांटाइज़्ड मॉडल

iOS जीपीयू डेलिगेट की गई लाइब्रेरी, संख्या वाले मॉडल डिफ़ॉल्ट रूप से काम करती हैं. जीपीयू डेलिगेट के साथ संख्या वाले मॉडल इस्तेमाल करने के लिए, आपको किसी कोड में बदलाव करने की ज़रूरत नहीं है. नीचे दिए गए सेक्शन में, टेस्टिंग या प्रयोग के लिए, संख्या के आधार पर मिलने वाली सहायता को बंद करने का तरीका बताया गया है.

संख्या वाले मॉडल की सुविधा बंद करें

इस कोड में, संख्या वाले मॉडल के लिए सहायता बंद करने का तरीका बताया गया है.

Swift

    var options = MetalDelegate.Options()
    options.isQuantizationEnabled = false
    let delegate = MetalDelegate(options: options)
      

Objective-C

    TFLMetalDelegateOptions* options = [[TFLMetalDelegateOptions alloc] init];
    options.quantizationEnabled = false;
      

C

    TFLGpuDelegateOptions options = TFLGpuDelegateOptionsDefault();
    options.enable_quantization = false;

    TfLiteDelegate* delegate = TFLGpuDelegateCreate(options);
      

जीपीयू की रफ़्तार के साथ संख्या वाले मॉडल चलाने के बारे में ज़्यादा जानकारी के लिए, GPU प्रतिनिधि की खास जानकारी देखें.