Rejoignez TensorFlow à Google I/O, du 11 au 12 mai. Inscrivez-vous maintenant

Délégué GPU TensorFlow Lite

Tensorflow Lite prend en charge plusieurs accélérateurs matériels. Ce document explique comment utiliser le backend GPU à l'aide des API déléguées TensorFlow Lite sur Android et iOS.

Les GPU sont conçus pour offrir un débit élevé pour les charges de travail massivement parallélisables. Ainsi, ils sont bien adaptés aux réseaux de neurones profonds, qui se composent d'un grand nombre d'opérateurs, chacun travaillant sur un ou plusieurs tenseurs d'entrée qui peuvent être facilement divisés en charges de travail plus petites et exécutés en parallèle, ce qui entraîne généralement une latence plus faible. Dans le meilleur des cas, l'inférence sur le GPU peut désormais s'exécuter assez rapidement pour les applications en temps réel qui n'étaient pas disponibles auparavant.

Contrairement aux CPU, les GPU calculent avec des nombres à virgule flottante 16 bits ou 32 bits et ne nécessitent pas de quantification pour des performances optimales. Le délégué accepte les modèles quantifiés 8 bits, mais le calcul sera effectué en nombres à virgule flottante. Reportez - vous à la documentation avancée pour plus de détails.

Un autre avantage de l'inférence GPU est son efficacité énergétique. Les GPU effectuent les calculs de manière très efficace et optimisée, de sorte qu'ils consomment moins d'énergie et génèrent moins de chaleur que lorsque la même tâche est exécutée sur des CPU.

Tutoriels d'application de démonstration

Le moyen le plus simple d'essayer le délégué GPU est de suivre les didacticiels ci-dessous, qui décrivent la création de nos applications de démonstration de classification avec la prise en charge du GPU. Le code GPU n'est pour l'instant que binaire ; il sera bientôt open-source. Une fois que vous avez compris comment faire fonctionner nos démos, vous pouvez les essayer sur vos propres modèles personnalisés.

Android (avec Android Studio)

Pour un tutoriel étape par étape, regarder le délégué GPU pour Android vidéo.

Étape 1. Clonez le code source de TensorFlow et ouvrez-le dans Android Studio

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

Étape 2. Modifier app/build.gradle utiliser l'AAR GPU nuit

Ajouter la tensorflow-lite-gpu package existant à côté de la tensorflow-lite paquet dans l'existant dependencies bloc.

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

Étape 3. Construire et exécuter

Exécuter → Exécuter « application ». Lorsque vous exécutez l'application, vous verrez un bouton pour activer le GPU. Passez d'un modèle quantifié à un modèle flottant, puis cliquez sur GPU pour l'exécuter sur le GPU.

exécuter une démo gpu android et passer à gpu

iOS (avec XCode)

Pour un tutoriel étape par étape, regarder le délégué GPU pour iOS vidéo.

Étape 1. Obtenez le code source de la démo et assurez-vous qu'il compile.

Suivez notre application de démonstration iOS tutoriel . Cela vous amènera à un point où la démo de l'appareil photo iOS non modifié fonctionne sur votre téléphone.

Étape 2. Modifier le fichier Podfile pour utiliser le CocoaPod GPU TensorFlow Lite

À partir de la version 2.3.0, par défaut, le délégué GPU est exclu du pod pour réduire la taille binaire. Vous pouvez les inclure en spécifiant une sous-spéc. Pour TensorFlowLiteSwift pod:

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

OU

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

Vous pouvez faire de même pour TensorFlowLiteObjC ou TensorFlowLitC si vous souhaitez utiliser l'Objective-C (de 2.4.0 version) ou API C.

Avant la version 2.3.0

Jusqu'à TensorFlow Lite 2.0.0

Nous avons construit un CocoaPod binaire qui inclut le délégué GPU. Pour changer le projet pour l'utiliser, modifiez le fichier `tensorflow/tensorflow/lite/examples/ios/camera/Podfile` pour utiliser le pod `TensorFlowLiteGpuExperimental` au lieu de `TensorFlowLite`.


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

Jusqu'à TensorFlow Lite 2.2.0

De TensorFlow Lite 2.1.0 à 2.2.0, le délégué GPU est inclus dans le pod "TensorFlowLiteC". Vous pouvez choisir entre `TensorFlowLiteC` et `TensorFlowLiteSwift` selon la langue.

Étape 3. Activer le délégué GPU

Pour activer le code qui utilisera le délégué du GPU, vous devrez changer TFLITE_USE_GPU_DELEGATE de 0 à 1 à CameraExampleViewController.h .

#define TFLITE_USE_GPU_DELEGATE 1

Étape 4. Créez et exécutez l'application de démonstration

Après avoir suivi l'étape précédente, vous devriez pouvoir exécuter l'application.

Étape 5. Mode de libération

Alors qu'à l'étape 4, vous avez exécuté en mode débogage, pour obtenir de meilleures performances, vous devez passer à une version de version avec les paramètres Metal optimaux appropriés. En particulier, Pour modifier ces paramètres vont au Product > Scheme > Edit Scheme... le Product > Scheme > Edit Scheme... . Sélectionnez Run . Sur l' Info onglet, le changement de Build Configuration , de Debug à Release , désactivez l' option Debug executable de Debug executable .

mise en place de la version

Cliquez ensuite sur le Options de l' onglet et le changement GPU Frame Capture de Disabled Metal API Validation Disabled GPU Frame Capture à Disabled et Metal API Validation à Disabled .

configuration des options de métal

Enfin, assurez-vous de sélectionner les versions de version uniquement sur une architecture 64 bits. Sous Project navigator -> tflite_camera_example -> PROJECT -> tflite_camera_example -> Build Settings de Build Active Architecture Only > Release Project navigator -> tflite_camera_example -> PROJECT -> tflite_camera_example -> Build Settings définir Build Active Architecture Only > Release Oui.

configuration des options de publication

Essayer le délégué GPU sur votre propre modèle

Android

Il y a deux façons d'invoquer l' accélération modèle en fonction de si vous utilisez Android ML Model Studio de liaison ou tensorflow Lite interprète.

Interprète TensorFlow Lite

Regardez la démo pour voir comment ajouter le délégué. Dans votre application, ajoutez le AAR comme ci - dessus, l' importation org.tensorflow.lite.gpu.GpuDelegate module et utiliser la addDelegate fonction pour enregistrer le délégué du GPU à l'interprète:

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

Rapide

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

Objectif 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 (jusqu'au 2.3.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);
          

## Supported Models and Ops

With the release of the GPU delegate, we included a handful of models that can
be run on the backend:

*   [MobileNet v1 (224x224) image classification](https://ai.googleblog.com/2017/06/mobilenets-open-source-models-for.html) [[download]](https://storage.googleapis.com/download.tensorflow.org/models/tflite/gpu/mobilenet_v1_1.0_224.tflite)
    <br /><i>(image classification model designed for mobile and embedded based vision applications)</i>
*   [DeepLab segmentation (257x257)](https://ai.googleblog.com/2018/03/semantic-image-segmentation-with.html) [[download]](https://storage.googleapis.com/download.tensorflow.org/models/tflite/gpu/deeplabv3_257_mv_gpu.tflite)
    <br /><i>(image segmentation model that assigns semantic labels (e.g., dog, cat, car) to every pixel in the input image)</i>
*   [MobileNet SSD object detection](https://ai.googleblog.com/2018/07/accelerated-training-and-inference-with.html) [[download]](https://storage.googleapis.com/download.tensorflow.org/models/tflite/gpu/mobile_ssd_v2_float_coco.tflite)
    <br /><i>(image classification model that detects multiple objects with bounding boxes)</i>
*   [PoseNet for pose estimation](https://github.com/tensorflow/tfjs-models/tree/master/posenet) [[download]](https://storage.googleapis.com/download.tensorflow.org/models/tflite/gpu/multi_person_mobilenet_v1_075_float.tflite)
    <br /><i>(vision model that estimates the poses of a person(s) in image or video)</i>

To see a full list of supported ops, please see the
[advanced documentation](gpu_advanced).

## Non-supported models and ops

If some of the ops are not supported by the GPU delegate, the framework will
only run a part of the graph on the GPU and the remaining part on the CPU. Due
to the high cost of CPU/GPU synchronization, a split execution mode like this
will often result in slower performance than when the whole network is run on
the CPU alone. In this case, the user will get a warning like:

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

Nous n'avons pas fourni de rappel pour cet échec, car il ne s'agit pas d'un véritable échec d'exécution, mais de quelque chose que le développeur peut observer tout en essayant de faire fonctionner le réseau sur le délégué.

Conseils pour l'optimisation

Optimisation pour les appareils mobiles

Certaines opérations triviales sur le CPU peuvent avoir un coût élevé pour le GPU sur les appareils mobiles. Opérations Reshape sont particulièrement coûteux à gérer, y compris BATCH_TO_SPACE , SPACE_TO_BATCH , SPACE_TO_DEPTH , et ainsi de suite. Vous devez examiner de près l'utilisation des opérations de remodelage et considérer qu'elles peuvent n'avoir été appliquées que pour l'exploration des données ou pour les premières itérations de votre modèle. Les supprimer peut améliorer considérablement les performances.

Sur GPU, les données de tenseur sont découpées en 4 canaux. Ainsi, un calcul sur un tenseur de forme [B,H,W,5] se produira peu près la même sur un tenseur de forme [B,H,W,8] , mais nettement moins bonne que [B,H,W,4] . En ce sens, si le matériel de la caméra prend en charge les images en RVBA, l'alimentation de cette entrée à 4 canaux est nettement plus rapide car une copie mémoire (de RVB à 3 canaux à RVBX à 4 canaux) peut être évitée.

Pour de meilleures performances, vous devez envisager de recycler le classificateur avec une architecture de réseau optimisée pour les mobiles. L'optimisation de l'inférence sur l'appareil peut réduire considérablement la latence et la consommation d'énergie en tirant parti des fonctionnalités du matériel mobile.

Réduction du temps d'initialisation grâce à la sérialisation

La fonction de délégué GPU vous permet de charger à partir du code du noyau précompilé et des données de modèle sérialisées et enregistrées sur le disque à partir des exécutions précédentes. Cette approche évite la recompilation et réduit le temps de démarrage jusqu'à 90 %. Pour obtenir des instructions sur la façon d'appliquer sérialisation à votre projet, voir GPU délégué sérialisation .