Le Blog Amazon Web Services

Amazon Elastic Inference – Accélération de l’inférence pour le Deep Learning assisté par GPU

L’une des raisons des récents progrès de l’intelligence artificielle et de l’apprentissage profond (Deep Learning) est la formidable capacité de calcul des processeurs graphiques (GPU). Il y a une dizaine d’années, les chercheurs ont appris à exploiter leur parallélisme matériel massif pour le Machine Learning et le High Performance Computing : les esprits les plus curieux apprécieront l’article fondateur (PDF) publié en 2009 par l’Université de Stanford.

Aujourd’hui, les GPU aident les développeurs et les data scientists à entraîner des modèles complexes sur des ensembles de données massifs pour l’analyse d’images médicales ou les vehicules autonomes. Par exemple, la famille d’instance Amazon EC2 P3 permet d’utiliser jusqu’à huit GPU NVIDIA Tesla V100 dans une même instance (jusqu’à huit GPU Tensor Core NVIDIA A100 pour les instances de la famille Amazon EC2 P4), pour des performances de précision mixte allant jusqu’à 1 PetaFLOP. Pouvez-vous croire qu’il y a 10 ans, ces performances étaient celles du supercalculateur le plus rapide du monde ?

Bien entendu, entraîner un modèle ne correspond qu’à la moitié du processus, et nous devons également nous préoccuper de l’inférence, c’est-à-dire de déployer le modèle et de prédire les résultats pour de nouveaux échantillons de données. Malheureusement, les développeurs sont souvent bloqués lorsque vient le temps de choisir un type et une taille d’instance pour déployer leurs modèles. En effet, pour les modèles de grande taille, la latence d’inférence des CPU peut ne pas répondre aux besoins des applications en temps réel, alors que le coût d’utilisation des GPU n’est pas toujours justifiable pour le projet. En outre, les ressources telles que la RAM et le CPU du serveur peuvent être plus importantes pour la performance globale de votre application que la vitesse d’inférence.

Par exemple, disons que votre application demande beaucoup de puissance et nécessite une instance c5.9xlarge : un seul appel d’inférence avec un modèle SSD prend près de 400 millisecondes, ce qui est certainement trop lent pour une interaction en temps réel. En déplaçant votre application vers une instance p2.xlarge, vous obtiendrez une performance d’inférence de 180 millisecondes : là encore, cela aurait un impact sur la performance de l’application car p2.xlarge dispose de moins de vCPU et de moins de RAM que l’instance c5.9xlarge.

Cet article a pour but de vous présenter Amazon Elastic Inference (EI), un service qui vous permet d’attacher la bonne quantité d’accélération d’inférence alimentée par des GPU à n’importe quelle instance Amazon EC2. Ce service est également disponible pour les instances de blocs-notes et les points de terminaison (endpoint) Amazon SageMaker, ce qui permet d’accélérer les algorithmes intégrés et les environnements d’apprentissage profond (deep learning).

Avec Amazon Elastic Inference, vous pouvez choisir le meilleur type d’instance basé sur le CPU pour votre application, attacher à cela la bonne quantité d’accélération GPU et obtenir le meilleur des deux mondes. De plus, vous pouvez utiliser Amazon EC2 Auto Scaling pour ajouter ou supprimer des instances accélérées à tout moment.

Introduction à Amazon Elastic Inference

Amazon Elastic Inference prend en charge des frameworks de Machine Learning populaires, tels que TensorFlow, Apache MXNet, PyTorch et ONNX (appliqué via MXNet). Les modifications à faire dans votre code existant sont minimes, mais vous devrez utiliser les versions optimisées pour AWS de ces frameworks et qui sont capables de détecter automatiquement les accélérateurs attachés aux instances, de garantir que seul les accès autorisés sont acceptés et de répartir le calcul entre les ressources CPU locales et l’accélérateur attaché. Ces versions sont disponibles dans les AWS Deep Learning AMIs, sur Amazon S3 afin que vous puissiez les intégrer dans votre propre image ou conteneur, et sont fournis automatiquement lorsque vous utilisez Amazon SageMaker.

Amazon Elastic Inference propose actuellement 2 familles d’accélérateurs Elastic Inference comprenant 3 types chacune. EIA2 est notre type d’accélérateur doté de deux fois plus de mémoire de GPU que des accélérateurs EIA1 équivalents. Pour vérifier la disponibilité régionale des 2 familles d’accélérateurs, veuillez vous référer à la page de tarification d’Amazon Elastic Inference.

Les différents types d’accélérateurs vous permettent de choisir le meilleur rapport qualité/prix pour votre application. Par exemple, une instance c5.large configurée avec l’accélération eia1.medium vous coûtera, à cette date, 0,236 USD par heure (en UE Irlande). Cette combinaison n’est que 10 à 15 % plus lente qu’une instance p2.xlarge, qui héberge un GPU NVIDIA K80 dédié et coûte, à cette date, 0,972 USD par heure (en UE Irlande). Résultat : vous bénéficiez d’une réduction de 75 % du coût pour des performances GPU équivalentes, tout en choisissant le type d’instance exact qui convient à votre application.

Dans la section suivante, nous allons examiner les exemples d’utilisation de d’Apache MXNet et de TensorFlow sur une instance Amazon EC2.

Mise en place d’Amazon Elastic Inference

Voici les étapes à suivre pour utiliser le service Amazon Elastic Inference avec une instance Amazon EC2:

  1. Créez un groupe de sécurité pour l’instance n’autorisant que le trafic SSH entrant,
  2. Créer un rôle IAM pour l’instance, lui permettant de se connecter au service Amazon Elastic Inference,
  3. Créer un point de terminaison VPC pour Amazon Elastic Inference dans le Amazon Virtual Private Cloud (Amazon VPC) où l’instance s’exécutera, en attachant un groupe de sécurité n’autorisant que le trafic HTTPS entrant de l’instance. Veuillez noter que vous n’aurez à le faire qu’une seule fois par Amazon VPC et que les frais pour le point de terminaison sont inclus dans le coût de l’accélérateur.

Création d’une instance accélérée

Maintenant que le point de terminaison est disponible, nous allons utiliser l’AWS CLI pour lancer une instance c5.large avec l’AWS Deep Learning AMI.

aws ec2 run-instances --image-id $AMI_ID \
--key-name $KEYPAIR_NAME --security-group-ids $SG_ID \
--subnet-id $SUBNET_ID --instance-type c5.large \
--elastic-inference-accelerator Type=eia1.large
--iam-instance-profile Name="entrez le nom de votre profil d'accélérateur"

Voilà ! Vous n’avez pas besoin d’apprendre de nouvelles API pour utiliser Amazon Elastic Inference, il suffit de passer un paramètre supplémentaire décrivant le type d’accélérateur. Après quelques minutes, l’instance est en place et nous pouvons nous y connecter.

Accélération avec Apache MXNet

Dans cet exemple classique, nous allons utiliser l’instance précédemment lancée pour charger un grand réseau de neurones convolutif pré-entraînés sur un accélérateur Amazon Elastic Inference Accelerator (si vous n’êtes pas familier avec les modèles pré-entraînés, ce sujet est couvert dans cet article, en anglais). Plus précisément, nous utiliserons un réseau ResNet-152 entraîné sur l’ensemble de données ImageNet. Ensuite, nous allons simplement classer une image en utilisant l’accélérateur Amazon Elastic Inference.

import mxnet as mx
import numpy as np
from collections import namedtuple
Batch = namedtuple('Batch', ['data'])

# Télécharger le modèle (ResNet-152 entraîné sur ImageNet) et les catégories d'ImageNet
path='http://data.mxnet.io/models/imagenet/'
[mx.test_utils.download(path+'resnet/152-layers/resnet-152-0000.params'),
 mx.test_utils.download(path+'resnet/152-layers/resnet-152-symbol.json'),
 mx.test_utils.download(path+'synset.txt')]

# Définir le contexte de calcul comme accélérateur Elastic Inference
# ctx = mx.gpu(0) # Voici comment nous ferions des prédictions sur un GPU
ctx = mx.eia()    # Voici comment nous faisons des prédictions sur un accélérateur Elastic Inference

# Charger le modèle pré-entraîné
sym, arg_params, aux_params = mx.model.load_checkpoint('resnet-152', 0)
mod = mx.mod.Module(symbol=sym, context=ctx, label_names=None)
mod.bind(for_training=False, data_shapes=[('data', (1,3,224,224))],
         label_shapes=mod._label_shapes)
mod.set_params(arg_params, aux_params, allow_missing=True)

# Charger les étiquettes de catégories d'ImageNet
with open('synset.txt', 'r') as f:
    labels = [l.rstrip() for l in f]

# Télécharger et charger l'image de test
fname = mx.test_utils.download('https://github.com/dmlc/web-data/blob/master/mxnet/doc/tutorials/python/predict_image/dog.jpg?raw=true')
img = mx.image.imread(fname)

# Convertir et remodeler l'image vers (lot=1, canaux=3, largeur, hauteur)
img = mx.image.imresize(img, 224, 224) # Redimensionner en fonction des paramètres d'entraînement
img = img.transpose((2, 0, 1)) # Canaux 
img = img.expand_dims(axis=0)  # Taille du lot
# img = img.as_in_context(ctx) # Pas nécessaire : les données sont chargées automatiquement dans Amazon Elastic Inference

# Prédire l'image
mod.forward(Batch([img]))
prob = mod.get_outputs()[0].asnumpy()

# Afficher les 3 premières classes
prob = np.squeeze(prob)
a = np.argsort(prob)[::-1]
for i in a[0:3]:
    print('probability=%f, class=%s' %(prob[i], labels[i]))

Comme vous pouvez le constater, il n’y a que quelques différences entre le code utilisé pour un GPU et celui utilisé pour Amazon Elastic Inference :

  • Nous avons défini le contexte de calcul comme mx.eia(). Aucune notation numérique n’est nécessaire, car seulement un accélérateur Amazon Elastic Inference peut être attaché sur une instance Amazon EC2,
  • Nous n’avons pas explicitement chargé l’image sur l’accélérateur Amazon Elastic Inference, comme nous l’aurions fait avec un GPU. Cette opération est effectuée automatiquement lorsque nous utilisons Amazon Elastic Inference.

L’exécution de cet exemple produit le résultat suivant.

probability=0.979113, class=n02110958 pug, pug-dog
probability=0.003781, class=n02108422 bull mastiff
probability=0.003718, class=n02112706 Brabancon griffon

En termes de performances, nous constatons que sur notre instance c5.large, cette prédiction prend environ 0,23 seconde sur le CPU, et seulement 0,031 seconde sur l’accélérateur eia1.large. À titre de comparaison, la même prédiction prend environ 0,015 seconde sur une instance p3.2xlarge équipée d’un GPU NVIDIA V100 intégré. Si nous utilisons plutôt un accélérateur eia1.medium, cette prédiction prend 0,046 seconde, ce qui est tout aussi rapide qu’un p2.xlarge (0,042 seconde) mais avec une réduction de 75% en termes de coûts.

Accélération avec TensorFlow

Vous pouvez utiliser TensorFlow Serving pour servir des prédictions accélérées : c’est un serveur de modèles qui charge des modèles sauvegardés et fournit des prédictions hautes performances via API REST et gRPC.

Amazon Elastic Inference propose une version accélérée de TensorFlow Serving, que vous pouvez utiliser sur votre instance accélérée comme dans l’exemple suivant.

$ AmazonEI_TensorFlow_Serving_v1.11_v1 --model_name=resnet --model_base_path=$MODEL_PATH --port=9000
$ python resnet_client.py --server=localhost:9000

Disponibilité d’Amazon Elastic Inference

Nous espérons que cet article a été instructif. Vous pouvez commencer à construire vos applications en utilisant Amazon Elastic Inference dès aujourd’hui ! Pour obtenir la liste la plus récente des régions prenant en charge Amazon Elastic Inference, veuillez consulter le Tableau des régions AWS de toute l’infrastructure mondiale AWS.

Article original rédigé en anglais par Julien Simon, Artificial Intelligence et Machine Learning Evangelist pour AWS EMEA, et traduit par Bruno Medeiros de Barros, Solutions Architect dans l’équipe AWS France, LinkedIn.