iOS için GPU hızlandırma temsilcisi

Makine öğrenimi (ML) modellerinizi çalıştırmak için grafik işlem birimlerini (GPU'lar) kullanmak, modelinizin performansını ve ML özellikli uygulamalarınızın kullanıcı deneyimini önemli ölçüde artırabilir. iOS cihazlarda, bir temsilci kullanarak modellerinizin GPU hızlandırmalı yürütülmesinin kullanımını etkinleştirebilirsiniz. Temsilciler, TensorFlow Lite için donanım sürücüleri görevi görerek modelinizin kodunu GPU işlemcilerde çalıştırmanıza olanak tanır.

Bu sayfada iOS uygulamalarında TensorFlow Lite modelleri için GPU hızlandırmanın nasıl etkinleştirileceği açıklanmaktadır. En iyi uygulamalar ve gelişmiş teknikler de dahil olmak üzere TensorFlow Lite için GPU temsilcisini kullanma hakkında daha fazla bilgi için GPU temsilcileri sayfasına bakın.

Tercüman API'si ile GPU'yu kullanın

TensorFlow Lite Interpreter API, makine öğrenimi uygulamaları oluşturmak için bir dizi genel amaçlı API sağlar. Aşağıdaki talimatlar, bir iOS uygulamasına GPU desteği ekleme konusunda size yol gösterir. Bu kılavuz, TensorFlow Lite ile bir ML modelini başarıyla yürütebilecek bir iOS uygulamanızın zaten olduğunu varsayar.

Pod dosyasını GPU desteğini içerecek şekilde değiştirin

TensorFlow Lite 2.3.0 sürümünden başlayarak, ikili boyutu azaltmak için GPU temsilcisi bölmeden çıkarılır. TensorFlowLiteSwift bölmesi için bir alt özellik belirterek bunları dahil edebilirsiniz:

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

VEYA

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

2.4.0 ve üzeri sürümler için mevcut olan Objective-C'yi veya C API'yi kullanmak istiyorsanız TensorFlowLiteObjC veya TensorFlowLiteC de kullanabilirsiniz.

GPU temsilcisini başlat ve kullan

GPU temsilcisini TensorFlow Lite Interpreter API ile çeşitli programlama dillerinde kullanabilirsiniz. Swift ve Objective-C önerilir ancak C++ ve C de kullanabilirsiniz. TensorFlow Lite'ın 2.4'ten önceki bir sürümünü kullanıyorsanız C kullanmanız gerekir. Aşağıdaki kod örnekleri, temsilcinin bu dillerin her birinde nasıl kullanılacağını özetlemektedir.

Süratli

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 ...
}
      

Amaç-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'dan önce)

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

GPU API dili kullanım notları

  • 2.4.0'dan önceki TensorFlow Lite sürümleri yalnızca Objective-C için C API'yi kullanabilir.
  • C++ API yalnızca bazel kullandığınızda veya TensorFlow Lite'ı kendiniz oluşturduğunuzda kullanılabilir. C++ API, CocoaPod'larla kullanılamaz.
  • TensorFlow Lite'ı C++ ile GPU temsilcisiyle kullanırken, GPU temsilcisini TFLGpuDelegateCreate() işlevi aracılığıyla alın ve ardından bunu Interpreter::ModifyGraphWithDelegate() çağırmak yerine Interpreter::AllocateTensors() öğesine iletin.

Yayın moduyla derleyin ve test edin

Daha iyi performans elde etmek ve son testler için uygun Metal API hızlandırıcı ayarlarına sahip bir sürüm yapısına geçin. Bu bölümde, bir sürüm oluşturmanın nasıl etkinleştirileceği ve Metal hızlandırma ayarının nasıl yapılandırılacağı açıklanmaktadır.

Bir sürüm yapısına geçmek için:

  1. Ürün > Şema > Şemayı Düzenle...'yi ve ardından Çalıştır'ı seçerek derleme ayarlarını düzenleyin.
  2. Bilgi sekmesinde Yapı Yapılandırmasını Serbest Bırak olarak değiştirin ve Yürütülebilir Hata Ayıklama seçeneğinin işaretini kaldırın.sürüm kurulumu
  3. Seçenekler sekmesine tıklayın ve GPU Çerçeve Yakalamayı Devre Dışı olarak ve Metal API Doğrulamasını Devre Dışı olarak değiştirin.
    metal seçeneklerini ayarlama
  4. 64 bit mimaride yalnızca sürüm sürümleri seçeneğini seçtiğinizden emin olun. Proje gezgini > tflite_camera_example > PROJECT > projenizin_adı > Yapı Ayarları altında Yalnızca Etkin Mimari Oluştur > Serbest Bırak seçeneğini Evet olarak ayarlayın. sürüm seçeneklerini ayarlama

Gelişmiş GPU desteği

Bu bölüm, iOS için GPU temsilcisinin, temsilci seçenekleri, giriş ve çıkış arabellekleri ve nicelenmiş modellerin kullanımı da dahil olmak üzere gelişmiş kullanımlarını kapsar.

iOS için Delege Seçenekleri

GPU temsilcisinin yapıcısı Swift API , Objective-C API ve C API'deki seçeneklerin struct kabul eder. Başlatıcıya nullptr (C API) veya hiçbir şeyin (Objective-C ve Swift API) iletilmesi, varsayılan seçenekleri ayarlar (bunlar yukarıdaki Temel Kullanım örneğinde açıklanmıştır).

Süratli

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

Amaç-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 kullanan Giriş/Çıkış arabellekleri

GPU üzerindeki hesaplama, verilerin GPU tarafından kullanılabilir olmasını gerektirir. Bu gereksinim genellikle bir bellek kopyalaması yapmanız gerektiği anlamına gelir. Mümkünse verilerinizin CPU/GPU bellek sınırını aşmasından kaçınmalısınız çünkü bu işlem çok fazla zaman alabilir. Genellikle böyle bir geçiş kaçınılmazdır ancak bazı özel durumlarda biri veya diğeri ihmal edilebilir.

Ağın girişi GPU belleğine önceden yüklenmiş bir görüntüyse (örneğin, kamera beslemesini içeren bir GPU dokusu), CPU belleğine girmeden GPU belleğinde kalabilir. Benzer şekilde, eğer ağın çıktısı görüntü stili aktarım işlemi gibi işlenebilen bir görüntü biçimindeyse, sonucu doğrudan ekranda görüntüleyebilirsiniz.

En iyi performansı elde etmek için TensorFlow Lite, kullanıcıların TensorFlow donanım arabelleğinden doğrudan okuma ve yazma yapmasını ve önlenebilir bellek kopyalarını atlamasını mümkün kılar.

Görüntü girişinin GPU belleğinde olduğunu varsayarsak, önce bunu Metal için bir MTLBuffer nesnesine dönüştürmeniz gerekir. Bir TfLiteTensor TFLGpuDelegateBindMetalBufferToTensor() işleviyle kullanıcı tarafından hazırlanan bir MTLBuffer ile ilişkilendirebilirsiniz. Bu işlevin Interpreter::ModifyGraphWithDelegate() öğesinden sonra çağrılması gerektiğini unutmayın. Ek olarak çıkarım çıkışı varsayılan olarak GPU belleğinden CPU belleğine kopyalanır. Başlatma sırasında Interpreter::SetAllowBufferHandleOutput(true) çağırarak bu davranışı kapatabilirsiniz.

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;
      

Varsayılan davranış kapatıldığında, çıkarım çıktısının GPU belleğinden CPU belleğine kopyalanması, her çıkış tensörü için Interpreter::EnsureTensorDataIsReadable() işlevine açık bir çağrı yapılmasını gerektirir. Bu yaklaşım aynı zamanda nicelenmiş modeller için de işe yarar, ancak yine de float32 verileriyle birlikte float32 boyutlu bir arabellek kullanmanız gerekir, çünkü arabellek dahili kuantumsuzlaştırılmış arabelleğe bağlıdır.

Nicelenmiş modeller

iOS GPU temsilci kitaplıkları varsayılan olarak nicelenmiş modelleri destekler . Nicelenmiş modelleri GPU temsilcisiyle kullanmak için herhangi bir kod değişikliği yapmanıza gerek yoktur. Aşağıdaki bölümde, test veya deneysel amaçlarla nicelenmiş desteğin nasıl devre dışı bırakılacağı açıklanmaktadır.

Nicelenmiş model desteğini devre dışı bırakın

Aşağıdaki kod, nicelenmiş modeller için desteğin nasıl devre dışı bırakılacağını gösterir.

Süratli

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

Amaç-C

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

C

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

    TfLiteDelegate* delegate = TFLGpuDelegateCreate(options);
      

Nicelenmiş modelleri GPU hızlandırmayla çalıştırma hakkında daha fazla bilgi için bkz. GPU temsilcisine genel bakış.