Ce tutoriel explique comment mesurer les performances du système d'inférence TensorFlow que vous avez créé dans la partie 2 de cette série et comment appliquer des réglages afin d'améliorer le débit du système. Il ne vise pas à fournir les données sur les performances d'un système particulier. Au lieu de cela, il offre des conseils généraux sur le processus de mesure des performances.
Le nombre réel de métriques de performance, telles que "Nombre total de requêtes par seconde (RPS)" et "Temps de réponse", diffèrent selon le modèle entraîné, les versions logicielles et les configurations matérielles.
Objectifs
- Définissez l'objectif de performances et les statistiques.
- Mesurez les performances de référence.
- Effectuer une optimisation du graphique.
- Mesurez la conversion FP16.
- Mesurez la quantification INT8.
- Ajuster le nombre d'instances.
Coûts
En plus d'utiliser le GPU NVIDIA T4, ce tutoriel utilise les composants facturables suivants de Google Cloud :
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. Pour en savoir plus, consultez la section Effectuer un nettoyage.
Avant de commencer
Avant de commencer ce tutoriel, vous devez finir de créer le système d'inférence en suivant la partie 2 de cette série. Pour ce tutoriel, vous devez utiliser les interfaces suivantes :
- Un terminal SSH de l'instance de travail que vous avez préparée dans la section Créer un environnement de travail
- Un tableau de bord Grafana que vous avez préparé à la section Déployer des serveurs de surveillance avec Prometheus et Grafana
- Une console Locust que vous avez préparée dans la section Déployer un outil de test de charge
Dans le terminal SSH, définissez le répertoire actuel sur le sous-répertoire client
:
cd $HOME/gke-tensorflow-inference-system-tutorial/client
Dans ce tutoriel, vous allez exécuter toutes les commandes à partir de ce répertoire.
Définir l'objectif de performances
Lorsque vous mesurez les performances des systèmes d'inférence, vous devez définir l'objectif de performances et les métriques de performances appropriées en fonction du cas d'utilisation du système. Par souci de simplicité, ce tutoriel suppose les objectifs de performances suivants :
- 95% des requêtes reçoivent des réponses dans un délai de 100 ms.
- Le débit total (requêtes par seconde) s'améliore sans dépasser l'objectif précédent.
En utilisant ces hypothèses, vous mesurez le débit des modèles ResNet-50 suivants avec différentes optimisations. Lorsqu'un client envoie des requêtes d'inférence, il spécifie le modèle en utilisant le nom du modèle figurant dans cette table. Vous appliquez également un réglage des paramètres pour améliorer le débit du modèle.
Nom du modèle | Optimisation |
---|---|
original |
Modèle d'origine (sans optimisation avec TF-TRT) |
tftrt_fp32 |
Optimisation du graphique (taille du lot: 64, groupes d'instances: 1) |
tftrt_fp16 |
Conversion en FP16 en plus de l'optimisation du graphique (taille du lot: 64, groupes d'instances: 1) |
tftrt_int8 |
Quantification avec INT8 en plus de l'optimisation du graphique (taille du lot: 64, groupes d'instances: 1) |
tftrt_int8_bs16_count4 |
Quantification avec INT8 en plus de l'optimisation du graphique (taille du lot: 16, groupes d'instances: 4) |
Mesurer les performances de référence
Vous allez commencer par utiliser TF-TRT comme base pour mesurer les performances du modèle d'origine non optimisé. Vous comparez les performances des autres modèles avec celles des modèles d'origine afin d'évaluer quantitativement l'amélioration des performances. Lorsque vous avez déployé Locust, il était déjà configuré pour envoyer des requêtes pour le modèle d'origine.
- Ouvrez la console Locust et vérifiez que le nombre de clients (appelés esclaves) est 10. Si le nombre est inférieur à 10, les clients démarrent toujours. Dans ce cas, attendez quelques minutes jusqu'à ce qu'il passe à 10.
- Définissez Nombre d'utilisateurs à simuler sur
3000
et Taux d'apparition sur5
. Augmentez le nombre d'utilisations simulées de 5 par seconde jusqu'à 3 000 en cliquant sur Start swarming (Démarrer le travail en essaim).
Cliquez sur Graphiques pour afficher les graphiques suivants.
Notez que si la valeur Total Requests per Second (Nombre total de requêtes par seconde) augmente de manière linéaire, la valeur Response Times (ms) (temps de réponse en ms) augmente de la même façon.
Lorsque la valeur de 95% du temps de réponse dépasse 100 ms, cliquez sur Stop pour arrêter la simulation. Si vous déplacez le pointeur de la souris sur le graphique, vous pouvez vérifier le nombre de requêtes par seconde correspondant aux cas où la valeur de 95% des centiles de réponses a dépassé 100 ms.
Dans la capture d'écran suivante, le nombre de requêtes par seconde est de 253,1.
Nous vous recommandons de répéter cette mesure plusieurs fois et de prendre en compte une moyenne pour tenir compte de la fluctuation.
Redémarrez Locust :
kubectl delete -f deployment_master.yaml -n locust kubectl delete -f deployment_slave.yaml -n locust kubectl apply -f deployment_master.yaml -n locust kubectl apply -f deployment_slave.yaml -n locust
Revenez à l'étape 1 pour répéter la mesure.
Optimiser les graphiques
Dans cette section, vous allez évaluer les performances du modèle tftrt_fp32
optimisé à l'aide du module TF-TRT pour l'optimisation du graphe. Il s'agit d'une optimisation courante qui est compatible avec la plupart des cartes de GPU NVIDIA.
Redémarrez l'outil de test de charge. Utilisez la ressource
configmap
pour spécifier le modèle en tant quetftrt_fp32
.kubectl delete configmap locust-config -n locust kubectl create configmap locust-config \ --from-literal model=tftrt_fp32 \ --from-literal saddr=${TRITON_IP} \ --from-literal rps=10 -n locust kubectl delete -f deployment_master.yaml -n locust kubectl delete -f deployment_slave.yaml -n locust kubectl apply -f deployment_master.yaml -n locust kubectl apply -f deployment_slave.yaml -n locust
Redémarrez le serveur Triton :
kubectl scale deployment/inference-server --replicas=0 kubectl scale deployment/inference-server --replicas=1
Attendez quelques minutes jusqu'à ce que les processus du serveur soient prêts.
Répétez la mesure des performances réalisée dans la section précédente.
Dans les captures d'écran suivantes, le nombre de requêtes par seconde est de 381.
Ces images montrent l'amélioration des performances de l'optimisation du graphique TF-TRT.
Conversion au format FP16
Dans cette section, vous allez évaluer les performances du modèle tftrt_fp16
, qui est optimisé avec TF-TRT pour l'optimisation du graphique et la conversion FP16. Il s'agit d'une optimisation disponible pour NVIDIA Tesla T4.
Redémarrez l'outil de test de charge. Utilisez la ressource
configmap
pour spécifier le modèle en tant quetftrt_fp16
.kubectl delete configmap locust-config -n locust kubectl create configmap locust-config \ --from-literal model=tftrt_fp16 \ --from-literal saddr=${TRITON_IP} \ --from-literal rps=10 -n locust kubectl delete -f deployment_master.yaml -n locust kubectl delete -f deployment_slave.yaml -n locust kubectl apply -f deployment_master.yaml -n locust kubectl apply -f deployment_slave.yaml -n locust
Redémarrez le serveur Triton :
kubectl scale deployment/inference-server --replicas=0 kubectl scale deployment/inference-server --replicas=1
Attendez quelques minutes jusqu'à ce que les processus du serveur soient prêts.
Répétez la mesure des performances réalisée dans la section précédente. Dans l'exemple suivant, le nombre de requêtes par seconde est de 1072,5.
Ces images montrent l'amélioration des performances de la conversion FP16 en plus de l'optimisation du graphique TF-TRT.
Quantification avec INT8
Dans cette section, vous allez évaluer les performances du modèle tftrt_int8
, qui est optimisé avec TF-TRT pour l'optimisation du graphe et la quantification INT8. Cette optimisation est disponible pour NVIDIA Tesla T4.
Redémarrez l'outil de test de charge. Utilisez la ressource
configmap
pour spécifier le modèle en tant quetftrt_int8
.kubectl delete configmap locust-config -n locust kubectl create configmap locust-config \ --from-literal model=tftrt_int8 \ --from-literal saddr=${TRITON_IP} \ --from-literal rps=10 -n locust kubectl delete -f deployment_master.yaml -n locust kubectl delete -f deployment_slave.yaml -n locust kubectl apply -f deployment_master.yaml -n locust kubectl apply -f deployment_slave.yaml -n locust
Redémarrez le serveur Triton :
kubectl scale deployment/inference-server --replicas=0 kubectl scale deployment/inference-server --replicas=1
Attendez quelques minutes jusqu'à ce que les processus du serveur soient prêts.
Répétez la mesure des performances réalisée dans la section précédente.
Dans les captures d'écran suivantes, le nombre de requêtes par seconde est de 1085,4.
Ce résultat est pratiquement identique à la conversion FP16. Le fait d'utiliser la quantification INT8 n'entraîne pas un avantage. En théorie, le GPU NVIDIA Tesla T4 peut gérer les modèles de quantification INT8 plus rapidement que les modèles de conversion FP16. Dans ce cas, le goulot d'étranglement peut être différent des performances des GPU. Vous pouvez le vérifier à partir des données d'utilisation du GPU suivantes dans le tableau de bord Grafana. Notez que l'utilisation est inférieure à 40%, ce qui signifie que le modèle ne peut pas utiliser pleinement les performances du GPU.
Comme le montre la section suivante, vous pourrez peut-être faciliter ce goulot d'étranglement en augmentant le nombre de groupes d'instances. Par exemple, augmentez le nombre de groupes d'instances de 1 à 4, puis réduisez la taille de lot de 64 à 16. Cette approche conserve le nombre total de requêtes traitées sur un seul GPU à 64.
Ajuster le nombre d'instances
Dans cette section, vous allez mesurer les performances du modèle tftrt_int8_bs16_count4
. Ce modèle possède la même structure que tftrt_int8
, mais vous modifiez la taille de lot et le nombre de groupes d'instances, comme décrit à la fin de la section précédente.
Redémarrez Locust. Utilisez la ressource
configmap
pour spécifier le modèle en tant quetftrt_int8_bs16_count4
. Dans le même temps, augmentez le nombre de pods clients Locust pour générer suffisamment de charges de travail afin de mesurer la limitation des performances du modèle.kubectl delete configmap locust-config -n locust kubectl create configmap locust-config \ --from-literal model=tftrt_int8_bs16_count4 \ --from-literal saddr=${TRITON_IP} \ --from-literal rps=10 -n locust kubectl delete -f deployment_master.yaml -n locust kubectl delete -f deployment_slave.yaml -n locust kubectl apply -f deployment_master.yaml -n locust kubectl apply -f deployment_slave.yaml -n locust kubectl scale deployment/locust-slave --replicas=20 -n locust
Redémarrez le serveur Triton :
kubectl scale deployment/inference-server --replicas=0 kubectl scale deployment/inference-server --replicas=1
Attendez quelques minutes jusqu'à ce que les processus du serveur soient prêts.
Répétez la mesure des performances réalisée dans la section précédente. Toutefois, dans le cas présent, définissez Taux d'apparition sur
15
car le temps nécessaire pour atteindre la limite de performance est long si vous définissezTaux d'apparition sur5
. Dans l'exemple suivant, le nombre de requêtes par seconde est de 2236,6.En ajustant le nombre d'instances, vous exécutez presque deux requêtes par seconde. Notez que l'utilisation du GPU a atteint environ 75% sur le tableau de bord Grafana.
Procéder au scaling avec plusieurs nœuds
Lorsque vous effectuez un scaling avec plusieurs nœuds, vous mesurez les performances d'un pod unique. Étant donné que les processus d'inférence sont exécutés indépendamment sur différents pods de manière "sans partage", vous pouvez supposer que le débit total évoluera de manière linéaire avec le nombre de pods. Cette hypothèse s'applique tant qu'il n'existe pas de goulots d'étranglement, tels que la bande passante réseau entre les clients et les serveurs d'inférence.
Toutefois, il est important de comprendre comment les requêtes d'inférence sont équilibrées entre plusieurs serveurs d'inférence. Triton utilise le protocole gRPC pour établir une connexion TCP entre un client et un serveur. Étant donné que Triton réutilise la connexion établie pour envoyer plusieurs requêtes d'inférence, les requêtes d'un même client sont toujours envoyées au même serveur. Pour distribuer les requêtes sur plusieurs serveurs, vous devez utiliser plusieurs clients.
Nettoyer
Supprimer le projet
- Dans la 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
- Apprenez-en plus sur la réduction de la latence de diffusion des prédictions en temps réel dans le machine learning.
- Découvrez des architectures de référence, des schémas, des tutoriels et des bonnes pratiques concernant Google Cloud. Consultez notre Centre d'architecture cloud.