TensorFlow Lite GPU temsilcisi

TensorFlow Lite , birkaç donanım hızlandırıcısını destekler. Bu belge, Android ve iOS'ta TensorFlow Lite temsilci API'lerini kullanarak GPU arka ucunun nasıl kullanılacağını açıklar.

GPU'lar, büyük ölçüde paralelleştirilebilir iş yükleri için yüksek aktarım hızına sahip olacak şekilde tasarlanmıştır. Bu nedenle, her biri daha küçük iş yüklerine kolayca bölünebilen ve paralel olarak yürütülebilen, tipik olarak daha düşük gecikme ile sonuçlanan bazı girdi tensörleri üzerinde çalışan çok sayıda operatörden oluşan derin sinir ağları için çok uygundurlar. En iyi senaryoda, GPU üzerindeki çıkarım, daha önce mevcut olmayan gerçek zamanlı uygulamalar için artık yeterince hızlı çalışabilir.

CPU'lardan farklı olarak, GPU'lar 16 bit veya 32 bit kayan nokta sayılarıyla hesaplama yapar ve optimum performans için niceleme gerektirmez. Temsilci 8 bitlik nicelleştirilmiş modelleri kabul eder, ancak hesaplama kayan noktalı sayılarla yapılacaktır. Ayrıntılar için gelişmiş belgelere bakın.

GPU çıkarımının bir başka avantajı da güç verimliliğidir. GPU'lar, hesaplamaları çok verimli ve optimize bir şekilde gerçekleştirir, böylece aynı görev CPU'larda çalıştırıldığından daha az güç tüketir ve daha az ısı üretir.

Demo uygulama eğitimleri

GPU temsilcisini denemenin en kolay yolu, GPU desteği ile sınıflandırma demo uygulamalarımızı oluşturan aşağıdaki öğreticileri takip etmektir. GPU kodu şimdilik sadece ikili; yakında açık kaynaklı olacak. Demolarımızı nasıl çalıştıracağınızı anladıktan sonra, bunu kendi özel modellerinizde deneyebilirsiniz.

Android (Android Studio ile)

Adım adım öğretici için Android için GPU Delegesi videosunu izleyin.

Adım 1. TensorFlow kaynak kodunu klonlayın ve Android Studio'da açın

git clone https://github.com/tensorflow/tensorflow

Adım 2. app/build.gradle gece GPU app/build.gradle kullanmak için app/build.gradle düzenleyin

Mevcut dependencies bloğundaki mevcut tensorflow-lite paketinin yanına tensorflow-lite-gpu paketini tensorflow-lite .

dependencies {
    ...
    implementation 'org.tensorflow:tensorflow-lite:2.3.0'
    implementation 'org.tensorflow:tensorflow-lite-gpu:2.3.0'
}

Adım 3. Oluşturun ve çalıştırın

Çalıştır → 'Uygulamayı' çalıştır. Uygulamayı çalıştırdığınızda, GPU'yu etkinleştirmek için bir düğme göreceksiniz. Kuantize modelden kayan modele geçin ve ardından GPU'da çalıştırmak için GPU'ya tıklayın.

android gpu demosunu çalıştırma ve gpu'ya geçme

iOS (XCode ile)

Adım adım eğitim için iOS için GPU Delegesi videosunu izleyin.

Adım 1. Demo kaynak kodunu alın ve derlendiğinden emin olun.

iOS Demo Uygulaması eğitimimizi takip edin. Bu sizi, telefonunuzda değiştirilmemiş iOS kamera demosunun çalıştığı bir noktaya götürecektir.

Adım 2. TensorFlow Lite GPU CocoaPod'u kullanmak için Pod dosyasını değiştirin

2.3.0 sürümünden itibaren, ikili dosya boyutunu küçültmek için varsayılan olarak GPU temsilcisi bölmeden çıkarılır. Alt belirtim belirterek bunları dahil edebilirsiniz. TensorFlowLiteSwift bölmesi için:

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

VEYA

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

Objective-C'yi (2.4.0 sürümünden itibaren) veya C API'sini kullanmak istiyorsanız, TensorFlowLiteObjC veya TensorFlowLitC için benzer şekilde yapabilirsiniz.

2.3.0 sürümünden önce

TensorFlow Lite 2.0.0'a kadar

GPU temsilcisini içeren bir ikili CocoaPod oluşturduk. Projeyi kullanmak üzere değiştirmek için, 'tensorflow/tensorflow/lite/examples/ios/camera/Podfile' dosyasını 'TensorFlowLite' yerine 'TensorFlowLiteGpuExperimental' bölmesini kullanacak şekilde değiştirin.


    target 'YourProjectName'
      # pod 'TensorFlowLite', '1.12.0'
      pod 'TensorFlowLiteGpuExperimental'
    

TensorFlow Lite 2.2.0'a kadar

TensorFlow Lite 2.1.0'dan 2.2.0'a kadar, GPU temsilcisi "TensorFlowLiteC" bölmesine dahil edilmiştir. Dile bağlı olarak `TensorFlowLiteC` ve `TensorFlowLiteSwift` arasında seçim yapabilirsiniz.

Adım 3. GPU temsilcisini etkinleştirin

GPU temsilcisini kullanacak kodu etkinleştirmek için CameraExampleViewController.h içinde TFLITE_USE_GPU_DELEGATE 0'dan 1'e değiştirmeniz gerekir.

#define TFLITE_USE_GPU_DELEGATE 1

Adım 4. Demo uygulamasını oluşturun ve çalıştırın

Önceki adımı uyguladıktan sonra uygulamayı çalıştırabilmeniz gerekir.

Adım 5. Serbest bırakma modu

4. Adımda hata ayıklama modunda çalışırken, daha iyi performans elde etmek için uygun optimum Metal ayarlarına sahip bir sürüm yapısına geçmelisiniz. Özellikle, bu ayarları düzenlemek için Product > Scheme > Edit Scheme... seçeneğine gidin. Run seçin. Info sekmesinde, Build Configuration Debug Release , Debug executable işaretini kaldırın.

sürüm kurma

Ardından Options sekmesine tıklayın ve GPU Frame Capture Disabled ve Metal API Validation Disabled .

metal seçenekleri ayarlama

Son olarak, 64 bit mimaride yalnızca sürüme dayalı derlemeleri seçtiğinizden emin olun. Project navigator -> tflite_camera_example -> PROJECT -> tflite_camera_example -> Build Settings Build Active Architecture Only > Release seçeneğini Evet olarak ayarlayın.

sürüm seçeneklerini ayarlama

GPU temsilcisini kendi modelinizde denemek

Android

Android Studio ML Model Binding veya TensorFlow Lite Interpreter kullanmanıza bağlı olarak model hızlandırmayı çağırmanın iki yolu vardır.

TensorFlow Lite Yorumlayıcı

Temsilciyi nasıl ekleyeceğinizi görmek için demoya bakın. Uygulamanızda, org.tensorflow.lite.gpu.GpuDelegate yukarıdaki gibi ekleyin, org.tensorflow.lite.gpu.GpuDelegate modülünü içe org.tensorflow.lite.gpu.GpuDelegate ve GPU temsilcisini yorumlayıcıya kaydetmek için addDelegate işlevini kullanın:

Kotlin

    import org.tensorflow.lite.Interpreter
    import org.tensorflow.lite.gpu.CompatibilityList
    import org.tensorflow.lite.gpu.GpuDelegate

    val compatList = CompatibilityList()

    val options = Interpreter.Options().apply{
        if(compatList.isDelegateSupportedOnThisDevice){
            // if the device has a supported GPU, add the GPU delegate
            val delegateOptions = compatList.bestOptionsForThisDevice
            this.addDelegate(GpuDelegate(delegateOptions))
        } else {
            // if the GPU is not supported, run on 4 threads
            this.setNumThreads(4)
        }
    }

    val interpreter = Interpreter(model, options)

    // Run inference
    writeToInput(input)
    interpreter.run(input, output)
    readFromOutput(output)
      

Java

    import org.tensorflow.lite.Interpreter;
    import org.tensorflow.lite.gpu.CompatibilityList;
    import org.tensorflow.lite.gpu.GpuDelegate;

    // Initialize interpreter with GPU delegate
    Interpreter.Options options = new Interpreter.Options();
    CompatibilityList compatList = CompatibilityList();

    if(compatList.isDelegateSupportedOnThisDevice()){
        // if the device has a supported GPU, add the GPU delegate
        GpuDelegate.Options delegateOptions = compatList.getBestOptionsForThisDevice();
        GpuDelegate gpuDelegate = new GpuDelegate(delegateOptions);
        options.addDelegate(gpuDelegate);
    } else {
        // if the GPU is not supported, run on 4 threads
        options.setNumThreads(4);
    }

    Interpreter interpreter = new Interpreter(model, options);

    // Run inference
    writeToInput(input);
    interpreter.run(input, output);
    readFromOutput(output);
      

iOS

hızlı

    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 (2.3.0'a kadar)

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

Desteklenen Modeller ve İşlemler

GPU temsilcisinin piyasaya sürülmesiyle, arka uçta çalıştırılabilen birkaç model ekledik:

Desteklenen işlemlerin tam listesini görmek için lütfen gelişmiş belgelere bakın .

Desteklenmeyen modeller ve işlemler

İşlemlerden bazıları GPU delegesi tarafından desteklenmiyorsa, çerçeve grafiğin yalnızca bir kısmını GPU'da ve kalan kısmı CPU'da çalıştırır. CPU/GPU senkronizasyonunun yüksek maliyeti nedeniyle, bunun gibi bir bölünmüş yürütme modu, genellikle tüm ağın yalnızca CPU üzerinde çalıştırıldığından daha yavaş performansa neden olur. Bu durumda kullanıcı şöyle bir uyarı alır:

WARNING: op code #42 cannot be handled by this delegate.

Bu gerçek bir çalışma zamanı hatası değil, geliştiricinin ağı temsilci üzerinde çalıştırmaya çalışırken gözlemleyebileceği bir şey olduğundan, bu hata için bir geri arama sağlamadık.

Optimizasyon için ipuçları

CPU üzerinde önemsiz olan bazı işlemler GPU için yüksek maliyetli olabilir. Bu tür bir işlemin bir sınıfı, BATCH_TO_SPACE , SPACE_TO_BATCH , SPACE_TO_DEPTH vb. dahil olmak üzere çeşitli yeniden şekillendirme işlemleri biçimleridir. Bu işlemler, yalnızca ağ mimarının mantıksal düşüncesi için ağa eklenirse, performans için bunları kaldırmaya değer.

GPU'da tensör verileri 4 kanala bölünür. Bu nedenle, [B,H,W,5] şeklindeki bir tensör üzerinde bir hesaplama, [B,H,W,8] şeklindeki bir tensör üzerinde yaklaşık olarak aynı performansı gösterecek [B,H,W,8] ancak [B,H,W,4] ten önemli ölçüde daha kötü olacaktır .

Bu anlamda, kamera donanımı RGBA'da görüntü çerçevelerini destekliyorsa, bir bellek kopyası (3 kanallı RGB'den 4 kanallı RGBX'e) önlenebileceğinden, bu 4 kanallı girişin beslenmesi önemli ölçüde daha hızlıdır.

En iyi performans için, sınıflandırıcınızı mobil cihazlar için optimize edilmiş bir ağ mimarisiyle yeniden eğitmekten çekinmeyin. Bu, cihaz üzerinde çıkarım için optimizasyonun önemli bir parçasıdır.