Ce tutoriel explique comment lancer une opération d'inférence à grande échelle en utilisant NVIDIA TensorRT 5 et des GPU T4. NVIDIA TensorRT™ est une plate-forme d'inférence haute performance pour le deep learning. Cette plate-forme inclut un optimiseur de processus d'inférence et un environnement d'exécution qui permettent de bénéficier d'un débit élevé et d'une faible latence pour les applications d'inférence liées au deep learning.
Dans le tutoriel, vous allez définir un cluster multizone afin d'exécuter une charge de travail d'inférence avec un groupe d'instances pour lesquelles l'autoscaling est activé. Le nombre d'instances utilisées dépendra de l'utilisation GPU.
Présentation
Ce tutoriel fournit les éléments suivants :
- Une architecture de référence pour la mise en œuvre d'un système d'inférence pour les opérations de machine learning sur Google Cloud, à la fois évolutif et adapté à un environnement de développement. Vos besoins en termes d'infrastructure et de sécurité pourraient ne pas correspondre à ce qui a été retenu pour ce tutoriel. Vous pouvez bien évidemment ajuster les configurations décrites dans ce document en conséquence.
- Un dépôt GitHub contenant les scripts que vous exécuterez dans le cadre de ce tutoriel pour installer le modèle TensorFlow et les autres composants requis.
- Des instructions pour la quantification du modèle TensorFlow à l'aide de TensorRT, pour le déploiement des scripts et pour le déploiement de l'architecture de référence.
- Des instructions relatives à la configuration de Cloud Load Balancing.
Lorsque vous aurez terminé ce tutoriel, vous disposerez d'un modèle pré-entraîné et quantifié qui sera hébergé dans Cloud Storage, de deux groupes d'instances Compute Engine déployés dans des zones différentes, ainsi que d'une solution Cloud Load Balancing frontale permettant d'équilibrer le trafic Web destiné aux instances. Cette architecture est illustrée dans le schéma suivant.
Objectifs
- Vous allez commencer avec un graphe pré-entraîné.
- Dans un second temps, vous optimiserez le modèle avec TensorRT et pourrez constater qu'il est possible de le rendre bien plus rapide en procédant à différentes optimisations.
- Une fois le modèle finalisé, vous créerez un cluster composé de VM Compute Engine dédiées au deep learning, sur lesquelles TensorFlow, TensorFlow Serving et TensorRT 5 sont préinstallés.
Coûts
Ce tutoriel utilise les composants facturables suivants de Google Cloud :
- Compute Engine
- Persistent Disk
- Cloud Storage
- Mise en réseau
- GPU NVIDIA T4
Obtenez une estimation des coûts en fonction de votre utilisation prévue à l'aide du simulateur de coût. Les nouveaux utilisateurs de Google Cloud peuvent bénéficier d'un essai gratuit.
Avant de commencer
-
Dans Google Cloud Console, accédez à la page de sélection du projet.
-
Sélectionnez ou créez un projet Google Cloud.
-
Assurez-vous que la facturation est activée pour votre projet Cloud. Découvrez comment vérifier que la facturation est activée pour votre projet.
- Activer les API Compute Engine and Cloud Logging.
- Assurez-vous que vous disposez d'un quota de GPU suffisant pour créer des machines virtuelles.
Une fois que vous avez terminé ce tutoriel, vous pouvez éviter de continuer à payer des frais en supprimant les ressources que vous avez créées. Consultez la page Effectuer un nettoyage pour en savoir plus.
Préparer l'environnement
Dans cette section, vous définissez des paramètres par défaut pour les valeurs utilisées tout au long du tutoriel, telles que la région et la zone. Dans ce tutoriel, la région par défaut est us-central1
, et la zone par défaut est us-central1-b
.
Vous devez également créer un fichier comprenant tous les paramètres, de façon à pouvoir charger les variables automatiquement si vous devez rouvrir Cloud Shell et réinitialiser les paramètres.
Ouvrez Cloud Shell.
Définissez la région et la zone par défaut :
gcloud compute project-info add-metadata \ --metadata google-compute-default-region=us-central1,google-compute-default-zone=us-central1-a
Réinitialisez l'interface système :
gcloud init --console-only
Appuyez sur
1
pour les trois premières questions, puis saisissez l'ID du projet pour la dernière question.
Optimiser le modèle avec TensorRT
Dans Cloud Shell, créez l'instance que vous allez utiliser pour la préparation du modèle :
export IMAGE_FAMILY="tf-latest-cu100" export INSTANCE_NAME="model-prep" gcloud compute instances create $INSTANCE_NAME \ --image-family=$IMAGE_FAMILY \ --machine-type=n1-standard-8 \ --image-project=deeplearning-platform-release \ --maintenance-policy=TERMINATE \ --accelerator="type=nvidia-tesla-t4,count=1" \ --metadata="install-nvidia-driver=True"
Le fait d'utiliser un seul GPU suffit amplement pour comparer différents modes d'optimisation TensorRT. En outre, cela permet de se faire une idée de la vitesse que peut atteindre un GPU unique.
Une fois l'instance de VM créée, utilisez
ssh
pour vous connecter à la machine virtuelle.Dans l'instance, téléchargez le modèle
resnetv2
depuis le dépôt officiel TensorFlow. Ce modèle va vous permettre de tester l'optimisation TensorRT :wget -q http://download.tensorflow.org/models/official/resnetv2_imagenet_frozen_graph.pb
TensorRT peut accroître la vitesse des charges de travail d'inférence, mais la quantification permet d'aller encore plus loin dans l'accélération du processus. La quantification de modèle linéaire consiste à convertir en nombres entiers les pondérations et activations exprimées sous forme de valeurs à virgule flottante. Par exemple, si les pondérations initiales du modèle sont de type FP32 (32 bits à virgule flottante), vous pouvez utiliser le type INT8 en réduisant la précision. Mais la quantification n'est pas sans incidence : en réduisant la représentation en mémoire, vous risquez de réduire fortement la justesse du modèle. En revanche, le passage du type FP32 au type FP16 n'a quasiment aucune incidence.
Comment choisir le bon compromis entre vitesse (précision des pondérations) et justesse ? Il existe un code qui fait cela. Il peut évaluer le degré de justesse atteignable en prenant en considération la vitesse ou d'autres métriques. Pour l'instant, ce code ne permet de tester que les modèles de reconnaissance d'image, mais il n'est pas très difficile de mettre en œuvre un test personnalisé en se basant sur ce code.
Dans Cloud Shell, téléchargez et mettez en œuvre un test personnalisé :
git clone https://github.com/tensorflow/models.git cd models git checkout f0e10716160cd048618ccdd4b6e18336223a172f touch research/__init__.py touch research/tensorrt/__init__.py cp research/tensorrt/labellist.json . cp research/tensorrt/image.jpg .
Préparez le test en vue de son exécution :
python -m research.tensorrt.tensorrt \ --frozen_graph=$HOME/resnetv2_imagenet_frozen_graph.pb \ --image_file=$HOME/models/image.jpg \ --native --fp32 --fp16 --int8 \ --output_dir=$HOME
Le test nécessite un graphe figé (le modèle resnetv2 que vous avez téléchargé précédemment) et des arguments pour les différents modes de quantification que vous souhaitez tester. Sachez que cette opération peut prendre un certain temps.
Le résultat renvoyé à la suite de l'exécution de la commande est une comparaison des résultats du processus d'inférence pour une version différente du graphe :
Les résultats, qui sont identiques pour FP32 et FP16, offrent le même degré de justesse. Si vous considérez que le résultat du test TensorRT est concluant, vous pouvez commencer à utiliser FP16 immédiatement. On peut également constater que les résultats pour INT8 sont légèrement moins précis.
Affichez les valeurs de justesse :
cat $HOME/log.txt
Cette commande produit le résultat suivant :
TensorRT 5 indique les résultats suivants, tous comparés aux valeurs natives :
- Pour FP32, le débit a été amélioré d'environ 34 %. Il est passé de 319,1 FPS à 428,2 FPS.
- Pour FP16, le débit a été amélioré d'environ 207 %. Il est passé de 319,1 FPS à 979,6 FPS.
- Pour INT8, le débit a été amélioré d'environ 376 %. Il est passé de 319,1 FPS à 1 519,5 FPS.
Ce que vous pouvez apprendre de ces résultats :
- Le passage du modèle natif au modèle optimisé par TensorRT a une incidence non négligeable sur l'incertitude. Toutefois, si vous acceptez une légère perte de précision, vous pouvez passer directement au type FP16.
- Le type INT8 est très rapide, mais le prix à payer en termes de perte de précision est sensiblement plus élevé.
La section suivante utilise le modèle INT8.
Convertir un modèle personnalisé en graphe TensorRT
Pour convertir un modèle en graphe TensorRT, vous avez besoin d'un SavedModel.
Dans Cloud Shell, téléchargez le SavedModel pré-entraîné suivant :
wget http://download.tensorflow.org/models/official/20181001_resnet/savedmodels/resnet_v2_fp32_savedmodel_NCHW.tar.gz tar -xzvf resnet_v2_fp32_savedmodel_NCHW.tar.gz
Créez un script Python permettant de convertir le modèle figé en graphe TensorRT :
cat <<EOF > convert_to_rt.py import tensorflow.contrib.tensorrt as trt import argparse parser = argparse.ArgumentParser(description="Converts TF SavedModel to the TensorRT enabled graph.") parser.add_argument("--input_model_dir", required=True) parser.add_argument("--output_model_dir", required=True) parser.add_argument("--batch_size", type=int, required=True) parser.add_argument("--precision_mode", choices=["FP32", "FP16", "INT8"], required=True) args = parser.parse_args() trt.create_inference_graph( None, None, max_batch_size=args.batch_size, input_saved_model_dir=args.input_model_dir, output_saved_model_dir=args.output_model_dir, precision_mode=args.precision_mode) EOF
Convertissez le modèle en graphe TensorRT :
python ./convert_to_rt.py \ --input_model_dir=$HOME/resnet_v2_fp32_savedmodel_NCHW/1538687196 \ --output_model_dir=$HOME/resnet_v2_int8_NCHW/00001 \ --batch_size=128 \ --precision_mode="INT8"
Désormais, le dossier
$HOME/resnet_v2_int8_NCHW/00001
contient un modèle INT8.Lancez un test d'inférence pour vous assurer que tout fonctionne correctement :
tensorflow_model_server --model_base_path=$HOME/resnet_v2_int8_NCHW/ --rest_api_port=8888
Pour vérifier que tout fonctionne, envoyez l'exemple d'entrée suivant :
curl -X POST localhost:8888/v1/models/default:predict -d '{"instances": [[[[1,1,1]]]]}'
Si vous voyez les résultats de cette commande
curl
s'afficher, arrêtez le test d'inférence en appuyant sur Ctrl+C.Pour utiliser le modèle optimisé depuis votre cluster, importez le modèle dans Cloud Storage. Pour cela, vous devez remplacer
[GCS_PATH]
par le nom de votre bucket Cloud Storage :tar -zcvf model.tar.gz ./resnet_v2_int8_NCHW/ export GCS_PATH=[GCS_PATH] gsutil cp model.tar.gz $GCS_PATH
La prochaine fois que vous souhaiterez utiliser ce modèle, vous n'aurez pas à répéter ce processus. Au lieu de cela, vous pourrez directement utiliser le graphe figé INT8 qui se trouve dans votre bucket Cloud Storage :
gs://solutions-public-assets/tensorrt-t4-gpu/model.tar.gz
Configurer un cluster
Maintenant que vous avez importé un modèle dans Cloud Storage, vous pouvez créer un cluster. La première étape consiste à créer un modèle de VM. Le cluster utilisera ensuite ce modèle de VM pour créer des instances de machine virtuelle.
Dans Cloud Shell, téléchargez le code dont vous avez besoin pour configurer le cluster :
git clone https://github.com/GoogleCloudPlatform/tensorflow-inference-tensorrt5-t4-gpu.git
Créez le modèle de VM en remplaçant
[PROJECT_NAME]
par le nom de votre projet :export PROJECT_NAME=[PROJECT_NAME] export INSTANCE_TEMPLATE_NAME="tf-inference-template" export IMAGE_FAMILY="tf-latest-cu100" gcloud beta compute --project=$PROJECT_NAME instance-templates create $INSTANCE_TEMPLATE_NAME \ --machine-type=n1-standard-16 \ --maintenance-policy=TERMINATE \ --accelerator=type=nvidia-tesla-t4,count=4 \ --min-cpu-platform=Intel\ Skylake \ --tags=http-server,https-server \ --image-family=$IMAGE_FAMILY \ --image-project=deeplearning-platform-release \ --boot-disk-size=100GB \ --boot-disk-type=pd-ssd \ --boot-disk-device-name=$INSTANCE_TEMPLATE_NAME \ --metadata startup-script-url=gs://solutions-public-assets/tensorrt-t4-gpu/start_agent_and_inf_server.sh
Le paramètre
metadata
fait référence à un script de démarrage qui sera installé sur chaque instance créée à partir du modèle de VM. Ce script effectue les procédures suivantes lors du démarrage de l'instance de VM :- Installation des pilotes NVIDIA
- Installation d'un agent chargé de surveiller l'utilisation du GPU
- Téléchargement du modèle
- Démarrage du service d'inférence
Lorsque le modèle est prêt, vous pouvez créer le groupe d'instances géré. Ce dernier ne sera pas utilisé en tant que groupe de scaling et aucune vérification de l'état ne sera effectuée sur les instances de VM. La création de ce groupe ne vous offre qu'une seule garantie : celle d'avoir deux instances en cours d'exécution dans des zones spécifiques.
Créez le groupe d'instances géré :
gcloud compute instance-groups managed create $INSTANCE_GROUP_NAME \ --template $INSTANCE_TEMPLATE_NAME \ --base-instance-name deeplearning-instances \ --size 2 \ --zones us-central1-a,us-central1-b
La valeur
INSTANCE_TEMPLATE_NAME
correspond au nom de l'instance que vous avez configurée précédemment. Choisissez des zones en fonction de la disponibilité des GPU (tous les GPU ne sont pas disponibles dans toutes les zones) et en fonction de vos quotas.La création du groupe prend un certain temps.
Exécutez la commande suivante pour surveiller la progression :
gcloud compute instance-groups managed list-instances $INSTANCE_GROUP_NAME --region us-central1
Le résultat ressemble à ceci :
Lorsque la création est terminée, vous obtenez quelque chose de semblable à ceci :
Ouvrez la page "Surveillance" dans Cloud Console.
Assurez-vous que vous êtes dans l'espace de travail associé à votre projet (cette information se trouve dans le coin supérieur gauche de la fenêtre). Si vous accédez à cette page pour la première fois, vous devez créer un espace de travail.
Sur la page Metrics Explorer (Explorateur de métriques), pour la valeur Resource type (Type de ressource), sélectionnez
GCE VM Instance
. Pour la valeur Metric (Métrique), sélectionnezcustom/gpu_utilization
:Si des données arrivent, vous voyez quelque chose de semblable à ceci :
Dans Cloud Shell, activez l'autoscaling pour votre groupe :
gcloud compute instance-groups managed set-autoscaling $INSTANCE_GROUP_NAME \ --custom-metric-utilization metric=custom.googleapis.com/gpu_utilization,utilization-target-type=GAUGE,utilization-target=85 \ --max-num-replicas 4 \ --cool-down-period 360 \ --region us-central1
La partie importante ici est le chemin d'utilisation (
custom.googleapis.com/gpu_utilization
), qui représente le chemin d'accès complet de votre métrique. Notez également que le niveau d'utilisation cible (utilization-target) est défini sur 85. Cela implique qu'une instance sera créée dans votre groupe à chaque fois que l'utilisation GPU atteint 85 %.
Tester l'autoscaling
Pour tester l'autoscaling, que vous avez configuré dans la section précédente, vous devez procéder comme suit :
- Utilisez SSH pour vous connecter à l'une des instances de deep learning basées sur des GPU.
- Faites grimper le taux d'utilisation de tous les GPU à 100 %.
- Observez comment votre groupe d'autoscaling se met à l'échelle automatiquement en créant une instance supplémentaire.
- Connectez-vous à l'instance via
ssh
. Faites grimper le taux d'utilisation du GPU à 100 % et maintenez-le à ce niveau pendant 600 secondes :
git clone https://github.com/GoogleCloudPlatform/tensorflow-inference-tensorrt5-t4-gpu.git cd tensorflow-inference-tensorrt5-t4-gpu git submodule update --init --recursive cd third_party/gpu-burn make ./gpu_burn 600 > /dev/null &
Dans Cloud Console, vous pouvez accéder à la page Metrics Explorer (Explorateur de métriques) pour constater et suivre l'activité de l'instance :
Créez la deuxième instance.
Accédez à la page GCE Compute (Calcul GCE) > Instance Groups (Groupes d'instances) > Monitoring (Surveillance) et observez l'activité :
À ce stade, l'autoscaler tente de démarrer autant d'instances que possible afin de réduire la charge (sans toutefois y parvenir). Et c'est bien ce que l'on constate à l'écran :
Arrêtez le démarrage de nouvelles instances et observez la réduction de l'activité.
Observons les éléments dont vous disposez désormais :
- Un modèle entraîné, optimisé à l'aide de TensorRT 5 (INT8)
- Un groupe d'instances de deep learning géré
- Un autoscaling basé sur l'utilisation GPU
Créer un équilibreur de charge
La dernière étape consiste à créer un équilibreur de charge devant les instances.
Dans Cloud Shell, créez des points de "vérification de l'état" afin de déterminer si un hôte particulier de votre backend peut diffuser le trafic :
gcloud compute health-checks create http $HEALTH_CHECK_NAME \ --request-path /v1/models/default \ --port 8888
Configurez les ports nommés du groupe d'instances pour que l'équilibreur de charge puisse transférer les requêtes d'inférence arrivant sur le port 80 au service d'inférence, lequel est desservi via le port 8888 :
gcloud compute instance-groups set-named-ports $INSTANCE_GROUP_NAME \ --named-ports http:8888 \ --region us-central1
Créez un service de backend :
export WEB_BACKED_SERVICE_NAME="tensorflow-backend" gcloud compute backend-services create $WEB_BACKED_SERVICE_NAME \ --protocol HTTP \ --health-checks $HEALTH_CHECK_NAME \ --global
Comme vous pouvez le remarquer, un service de backend est un groupe d'instances avec vérification de l'état (Health Check).
Ajoutez votre groupe d'instances au service de backend nouvellement créé :
gcloud compute backend-services add-backend $WEB_BACKED_SERVICE_NAME \ --balancing-mode UTILIZATION \ --max-utilization 0.8 \ --capacity-scaler 1 \ --instance-group $INSTANCE_GROUP_NAME \ --instance-group-region us-central1 \ --global
Indiquez à l'équilibreur de charge quelle est l'URL à transférer au service de backend :
export WEB_MAP_NAME="map-all" gcloud compute url-maps create $WEB_MAP_NAME \ --default-service $WEB_BACKED_SERVICE_NAME
Créez l'équilibreur de charge :
export LB_NAME="tf-lb" gcloud compute target-http-proxies create $LB_NAME \ --url-map $WEB_MAP_NAME
Créez une adresse IP externe pour votre équilibreur de charge :
export IP4_NAME="lb-ip4" gcloud compute addresses create $IP4_NAME \ --ip-version=IPV4 \ --global
Contrôlez que l'adresse IP a été attribuée :
gcloud compute addresses list
Vérifiez la règle de transfert utilisée par Google Cloud pour rediriger toutes les requêtes arrivant au niveau de l'adresse IP publique vers l'équilibreur de charge :
export IP=$(gcloud compute addresses list | grep ${IP4_NAME} | awk '{print $2}') export FORWARDING_RULE="lb-fwd-rule" gcloud compute forwarding-rules create $FORWARDING_RULE \ --address $IP \ --global \ --target-http-proxy $LB_NAME \ --ports 80
Une fois les règles de transfert globales créées, la propagation de votre configuration peut prendre plusieurs minutes.
Pour vous connecter à des instances externes, activez le pare-feu pour le projet :
gcloud compute firewall-rules create www-firewall-80 \ --target-tags http-server --allow tcp:80 gcloud compute firewall-rules create www-firewall-8888 \ --target-tags http-server --allow tcp:8888
Convertissez l'image dans un format d'entrée accepté par le serveur :
cat <<EOF > load_and_convert_image.py from PIL import Image import numpy as np import json import codecs img = Image.open("image.jpg").resize((240, 240)) img_array=np.array(img) result = { "instances":[img_array.tolist()] } file_path="/tmp/out.json" print(json.dump(result, codecs.open(file_path, 'w', encoding='utf-8'), separators=(',', ':'), sort_keys=True, indent=4)) EOF
Lancez une opération d'inférence :
wget https://pixnio.com/free-images/2017/10/31/2017-10-31-10-43-58-1032x825.jpg -O image.jpg python load_and_convert_image.py curl -X POST $IP/v1/models/default:predict -d @/tmp/out.json
Si l'inférence fonctionne correctement, le résultat renvoyé doit ressembler à ceci :
Effectuer un nettoyage
Une fois ce tutoriel terminé, vous pouvez nettoyer les ressources que vous avez créées dans Google Cloud afin qu'elles ne soient pas prises en compte et qu'elles ne vous soient plus facturées. Dans les sections suivantes, nous allons voir comment supprimer ou désactiver ces ressources.
- Dans Cloud Console, accédez à la page Gérer les ressources.
- Dans la liste des projets, sélectionnez le projet que vous souhaitez supprimer, puis cliquez sur Supprimer.
- Dans la boîte de dialogue, saisissez l'ID du projet, puis cliquez sur Arrêter pour supprimer le projet.
Étape suivante
- Pour en savoir plus sur TensorRT, consultez la documentation.
- Consultez la documentation relative aux GPU NVIDIA T4.
- Découvrez comment créer des métriques personnalisées et utiliser des métriques personnalisées.
- Apprenez-en davantage sur les instances intégrées à un groupe d'autoscaling.
- Testez d'autres fonctionnalités de Google Cloud. Découvrez nos tutoriels.