Délégués TensorFlow Lite

Introduction

Les délégués activent l'accélération matérielle des modèles TensorFlow Lite en tirant parti des accélérateurs intégrés à l'appareil, tels que le GPU et le processeur de signal numérique (DSP) .

Par défaut, TensorFlow Lite utilise des noyaux de processeur optimisés pour le jeu d'instructions ARM Neon . Cependant, le processeur est un processeur polyvalent qui n'est pas nécessairement optimisé pour l'arithmétique lourde que l'on trouve généralement dans les modèles d'apprentissage automatique (par exemple, les mathématiques matricielles impliquées dans la convolution et les couches denses).

D’un autre côté, la plupart des téléphones mobiles modernes contiennent des puces qui sont plus à même de gérer ces opérations lourdes. Leur utilisation pour les opérations de réseau neuronal offre d’énormes avantages en termes de latence et d’efficacité énergétique. Par exemple, les GPU peuvent fournir une latence jusqu'à 5 fois plus rapide , tandis que le DSP Qualcomm® Hexagon a montré qu'il réduisait la consommation d'énergie jusqu'à 75 % lors de nos expériences.

Chacun de ces accélérateurs est associé à des API qui permettent des calculs personnalisés, comme OpenCL ou OpenGL ES pour GPU mobile et le SDK Qualcomm® Hexagon pour DSP. En règle générale, vous devrez écrire beaucoup de code personnalisé pour exécuter un réseau neuronal via ces interfaces. Les choses deviennent encore plus compliquées si l'on considère que chaque accélérateur a ses avantages et ses inconvénients et ne peut pas exécuter toutes les opérations dans un réseau neuronal. L'API Delegate de TensorFlow Lite résout ce problème en agissant comme un pont entre le runtime TFLite et ces API de niveau inférieur.

exécution avec des délégués

Choisir un délégué

TensorFlow Lite prend en charge plusieurs délégués, chacun étant optimisé pour certaines plates-formes et types de modèles particuliers. Habituellement, il y aura plusieurs délégués applicables à votre cas d'utilisation, en fonction de deux critères majeurs : la plate-forme (Android ou iOS ?) que vous ciblez et le type de modèle (à virgule flottante ou quantifié ?) que vous essayez d'accélérer. .

Délégués par plateforme

Multiplateforme (Android et iOS)

  • Délégué GPU - Le délégué GPU peut être utilisé sur Android et iOS. Il est optimisé pour exécuter des modèles flottants 32 bits et 16 bits lorsqu'un GPU est disponible. Il prend également en charge les modèles quantifiés 8 bits et offre des performances GPU comparables à celles de leurs versions float. Pour plus de détails sur le délégué GPU, consultez TensorFlow Lite sur GPU . Pour obtenir des didacticiels étape par étape sur l'utilisation du délégué GPU avec Android et iOS, consultez Tutoriel de délégué GPU TensorFlow Lite .

Android

  • Délégué NNAPI pour les appareils Android plus récents - Le délégué NNAPI peut être utilisé pour accélérer les modèles sur les appareils Android avec GPU, DSP et/ou NPU disponibles. Il est disponible sous Android 8.1 (API 27+) ou supérieur. Pour obtenir une présentation du délégué NNAPI, des instructions étape par étape et des bonnes pratiques, consultez Délégué NNAPI TensorFlow Lite .
  • Délégué Hexagon pour les anciens appareils Android - Le délégué Hexagon peut être utilisé pour accélérer les modèles sur les appareils Android avec Qualcomm Hexagon DSP. Il peut être utilisé sur les appareils exécutant d’anciennes versions d’Android qui ne prennent pas en charge NNAPI. Consultez le délégué TensorFlow Lite Hexagon pour plus de détails.

IOS

  • Délégué Core ML pour les iPhones et iPads plus récents - Pour les iPhones et iPads plus récents sur lesquels Neural Engine est disponible, vous pouvez utiliser le délégué Core ML pour accélérer l'inférence pour les modèles à virgule flottante 32 bits ou 16 bits. Neural Engine est disponible sur les appareils mobiles Apple équipés d'un SoC A12 ou supérieur. Pour obtenir une présentation du délégué Core ML et des instructions étape par étape, consultez Délégué TensorFlow Lite Core ML .

Délégués par type de modèle

Chaque accélérateur est conçu en tenant compte d’une certaine largeur de bits de données. Si vous fournissez un modèle à virgule flottante à un délégué qui ne prend en charge que les opérations quantifiées sur 8 bits (comme le délégué Hexagon ), il rejettera toutes ses opérations et le modèle s'exécutera entièrement sur le processeur. Pour éviter de telles surprises, le tableau ci-dessous donne un aperçu de la prise en charge des délégués en fonction du type de modèle :

Type de modèle GPU NNAPI Hexagone CoreML
Virgule flottante (32 bits) Oui Oui Non Oui
Quantification float16 post-entraînement Oui Non Non Oui
Quantification de la plage dynamique post-entraînement Oui Oui Non Non
Quantification entière post-formation Oui Oui Oui Non
Formation prenant en compte la quantification Oui Oui Oui Non

Validation des performances

Les informations contenues dans cette section servent de lignes directrices approximatives pour présélectionner les délégués qui pourraient améliorer votre candidature. Cependant, il est important de noter que chaque délégué prend en charge un ensemble prédéfini d'opérations et peut s'exécuter différemment selon le modèle et l'appareil ; par exemple, le délégué NNAPI peut choisir d'utiliser Edge-TPU de Google sur un téléphone Pixel tout en utilisant un DSP sur un autre appareil. Par conséquent, il est généralement recommandé d’effectuer une analyse comparative pour évaluer l’utilité d’un délégué par rapport à vos besoins. Cela permet également de justifier l'augmentation de la taille binaire associée à l'attachement d'un délégué au runtime TensorFlow Lite.

TensorFlow Lite dispose d'outils complets d'évaluation des performances et de la précision qui peuvent permettre aux développeurs d'utiliser en toute confiance des délégués dans leur application. Ces outils sont abordés dans la section suivante.

Outils d'évaluation

Latence et empreinte mémoire

L'outil d'évaluation de TensorFlow Lite peut être utilisé avec des paramètres appropriés pour estimer les performances du modèle, notamment la latence moyenne d'inférence, la surcharge d'initialisation, l'empreinte mémoire, etc. Cet outil prend en charge plusieurs indicateurs pour déterminer la meilleure configuration de délégué pour votre modèle. Par exemple, --gpu_backend=gl peut être spécifié avec --use_gpu pour mesurer l'exécution du GPU avec OpenGL. La liste complète des paramètres délégués pris en charge est définie dans la documentation détaillée .

Voici un exemple d'exécution pour un modèle quantifié avec GPU via adb :

adb shell /data/local/tmp/benchmark_model \
  --graph=/data/local/tmp/mobilenet_v1_224_quant.tflite \
  --use_gpu=true

Vous pouvez télécharger la version prédéfinie de cet outil pour Android, architecture ARM 64 bits ici ( plus de détails ).

Exactitude et exactitude

Les délégués effectuent généralement des calculs avec une précision différente de celle de leurs homologues CPU. En conséquence, il existe un compromis (généralement mineur) en matière de précision associé à l’utilisation d’un délégué pour l’accélération matérielle. Notez que ce n'est pas toujours vrai ; par exemple, étant donné que le GPU utilise une précision en virgule flottante pour exécuter des modèles quantifiés, il pourrait y avoir une légère amélioration de la précision (par exemple, <1 % d'amélioration Top-5 dans la classification des images ILSVRC).

TensorFlow Lite dispose de deux types d'outils pour mesurer avec quelle précision un délégué se comporte pour un modèle donné : basé sur les tâches et indépendant des tâches . Tous les outils décrits dans cette section prennent en charge les paramètres de délégation avancés utilisés par l'outil d'analyse comparative de la section précédente. Notez que les sous-sections ci-dessous se concentrent sur l'évaluation du délégué (le délégué effectue-t-il la même chose que le processeur ?) plutôt que sur l'évaluation du modèle (le modèle lui-même est-il bon pour la tâche ?).

Évaluation basée sur les tâches

TensorFlow Lite dispose d'outils pour évaluer l'exactitude de deux tâches basées sur des images :

Les binaires prédéfinis de ces outils (Android, architecture ARM 64 bits), ainsi que la documentation, sont disponibles ici :

L'exemple ci-dessous montre l'évaluation de la classification d'images avec NNAPI en utilisant Edge-TPU de Google sur un Pixel 4 :

adb shell /data/local/tmp/run_eval \
  --model_file=/data/local/tmp/mobilenet_quant_v1_224.tflite \
  --ground_truth_images_path=/data/local/tmp/ilsvrc_images \
  --ground_truth_labels=/data/local/tmp/ilsvrc_validation_labels.txt \
  --model_output_labels=/data/local/tmp/model_output_labels.txt \
  --output_file_path=/data/local/tmp/accuracy_output.txt \
  --num_images=0 # Run on all images. \
  --use_nnapi=true \
  --nnapi_accelerator_name=google-edgetpu

Le résultat attendu est une liste de métriques Top-K de 1 à 10 :

Top-1 Accuracy: 0.733333
Top-2 Accuracy: 0.826667
Top-3 Accuracy: 0.856667
Top-4 Accuracy: 0.87
Top-5 Accuracy: 0.89
Top-6 Accuracy: 0.903333
Top-7 Accuracy: 0.906667
Top-8 Accuracy: 0.913333
Top-9 Accuracy: 0.92
Top-10 Accuracy: 0.923333

Évaluation indépendante des tâches

Pour les tâches pour lesquelles il n'existe pas d'outil d'évaluation établi sur l'appareil, ou si vous expérimentez des modèles personnalisés, TensorFlow Lite dispose de l'outil Inference Diff . (Android, architecture binaire ARM 64 bits ici )

Inference Diff compare l'exécution de TensorFlow Lite (en termes de latence et d'écart de valeur de sortie) dans deux paramètres :

  • Inférence CPU monothread
  • Inférence définie par l'utilisateur - définie par ces paramètres

Pour ce faire, l'outil génère des données gaussiennes aléatoires et les transmet via deux interpréteurs TFLite : l'un exécutant des noyaux de processeur monothread et l'autre paramétré par les arguments de l'utilisateur.

Il mesure la latence des deux, ainsi que la différence absolue entre les tenseurs de sortie de chaque interpréteur, élément par élément.

Pour un modèle avec un seul tenseur de sortie, la sortie pourrait ressembler à ceci :

Num evaluation runs: 50
Reference run latency: avg=84364.2(us), std_dev=12525(us)
Test run latency: avg=7281.64(us), std_dev=2089(us)
OutputDiff[0]: avg_error=1.96277e-05, std_dev=6.95767e-06

Cela signifie que pour le tenseur de sortie à l'index 0 , les éléments de la sortie CPU diffèrent de la sortie du délégué d'une moyenne de 1.96e-05 .

Notez que l'interprétation de ces chiffres nécessite une connaissance plus approfondie du modèle et de la signification de chaque tenseur de sortie. S'il s'agit d'une simple régression qui détermine une sorte de score ou d'intégration, la différence devrait être faible (sinon c'est une erreur du délégué). Cependant, les sorties telles que celle de la « classe de détection » des modèles SSD sont un peu plus difficiles à interpréter. Par exemple, cela peut montrer une différence en utilisant cet outil, mais cela ne signifie peut-être pas vraiment quelque chose qui ne va pas avec le délégué : considérez deux (fausses) classes : "TV (ID : 10)", "Moniteur (ID : 20)" - Si un délégué s'écarte légèrement de la vérité dorée et affiche un moniteur au lieu de la télévision, la différence de sortie pour ce tenseur peut atteindre 20-10 = 10.