Serveur d'impression

Amazon ECS prend désormais en charge les instances EC2 Inf1: idk.dev – Serveur d’impression

Le 18 août 2020 - 10 minutes de lecture

[bzkshopping keyword= »Minecraft » count= »8″ template= »grid »]

À mesure que les modèles d'apprentissage automatique et d'apprentissage en profondeur deviennent plus sophistiqués, une accélération matérielle est de plus en plus nécessaire pour fournir des prédictions rapides à haut débit. Aujourd'hui, nous sommes très heureux d'annoncer que les clients AWS peuvent désormais utiliser les instances Amazon EC2 Inf1 sur Amazon ECS, pour des performances élevées et le coût de prédiction le plus bas dans le cloud. Depuis quelques semaines maintenant, ces instances sont également disponibles sur Amazon Elastic Kubernetes Service.

Présentation des instances EC2 Inf1
Les instances Inf1 ont été lancées à AWS re: Invent 2019. Elles sont alimentées par AWS Inferentia, une puce personnalisée conçue à partir de zéro par AWS pour accélérer les charges de travail d'inférence de machine learning.

Les instances Inf1 sont disponibles en plusieurs tailles, avec 1, 4 ou 16 puces AWS Inferentia, avec une bande passante réseau jusqu'à 100 Gbit / s et une bande passante EBS jusqu'à 19 Gbit / s. Une puce AWS Inferentia contient quatre NeuronCores. Chacun implémente un moteur de multiplication matricielle systolique haute performance, qui accélère massivement les opérations typiques d'apprentissage en profondeur telles que la convolution et les transformateurs. Les NeuronCores sont également équipés d'un grand cache sur puce, ce qui permet de réduire les accès à la mémoire externe, économisant ainsi du temps d'E / S dans le processus. Lorsque plusieurs puces AWS Inferentia sont disponibles sur une instance Inf1, vous pouvez partitionner un modèle entre elles et le stocker entièrement dans la mémoire cache. Alternativement, pour diffuser des prédictions multi-modèles à partir d'une seule instance Inf1, vous pouvez partitionner les NeuronCores d'une puce AWS Inferentia sur plusieurs modèles.

Compilation de modèles pour les instances EC2 Inf1
Pour exécuter des modèles de machine learning sur des instances Inf1, vous devez les compiler en une représentation optimisée pour le matériel à l'aide du kit SDK AWS Neuron. Tous les outils sont facilement disponibles sur l'AMI AWS Deep Learning et vous pouvez également les installer sur vos propres instances. Vous trouverez des instructions dans la documentation AMI Deep Learning, ainsi que des didacticiels pour TensorFlow, PyTorch et Apache MXNet dans le référentiel AWS Neuron SDK.

Dans la démo ci-dessous, je vais vous montrer comment déployer un modèle optimisé pour Neuron sur un cluster ECS d'instances Inf1 et comment servir des prédictions avec TensorFlow Serving. Le modèle en question est BERT, un modèle de pointe pour les tâches de traitement du langage naturel. C'est un modèle énorme avec des centaines de millions de paramètres, ce qui en fait un excellent candidat pour l'accélération matérielle.

Création d'un cluster Amazon ECS
Créer un cluster est la chose la plus simple: il suffit d'un appel au CreateCluster API.

$ aws ecs create-cluster - nom-cluster ecs-inf1-demo

Immédiatement, je vois le nouveau cluster dans la console.

Nouveau cluster

Plusieurs prérequis sont nécessaires avant de pouvoir ajouter des instances à ce cluster:

  • Un rôle AWS Identity and Access Management (IAM) pour les instances ECS: si vous n'en avez pas déjà, vous pouvez trouver des instructions dans la documentation. Ici, mon rôle est nommé ecsInstanceRole.
  • Une Amazon Machine Image (AMI) contenant l'agent ECS et prenant en charge les instances Inf1. Vous pouvez créer la vôtre ou utiliser l'AMI optimisée pour ECS pour Inferentia. Dans la région us-east-1, son identifiant est ami-04450f16e0cd20356.
  • Un groupe de sécurité, ouvrant des ports réseau pour TensorFlow Serving (8500 pour gRPC, 8501 pour HTTP). L'identifiant du mien est sg-0994f5c7ebbb48270.
  • Si vous souhaitez avoir un accès ssh, votre groupe de sécurité doit également ouvrir le port 22 et vous devez transmettre le nom d'une paire de clés SSH. Le mien s'appelle admin.

Nous devons également créer un petit fichier de données utilisateur afin de permettre aux instances de rejoindre notre cluster. Ceci est réalisé en stockant le nom du cluster dans une variable d'environnement, elle-même écrite dans le fichier de configuration de l'agent ECS.

#! / bin / bash
echo ECS_CLUSTER = ecs-inf1-demo >> /etc/ecs/ecs.config

Nous sommes tous prêts. Ajoutons quelques instances Inf1 avec le RunInstances API. Pour minimiser les coûts, nous demanderons des instances Spot.

Instances d'exécution $ aws ec2
--image-id ami-04450f16e0cd20356
--compte 2
--instance-type inf1.xlarge
--instance-market-options '"MarketType": "spot"'
--tag-specs 'ResourceType = instance, Tags =[Key=Name,Value=ecs-inf1-demo]'
- nom-clé admin
--security-group-ids sg-0994f5c7ebbb48270
--iam-instance-profile Nom = ecsInstanceRole
- fichier de données utilisateur: // données-utilisateur.txt

Les deux instances apparaissent immédiatement dans la console EC2.

Instances Inf1

Quelques minutes plus tard, ils sont prêts à exécuter des tâches sur le cluster.

Instances Inf1

Notre infrastructure est prête. Maintenant, construisons un conteneur stockant notre modèle BERT.

Création d'un conteneur pour les instances Inf1
le Dockerfile est assez simple:

  • À partir d'une image Amazon Linux 2, nous ouvrons les ports 8500 et 8501 pour le service TensorFlow.
  • Ensuite, nous ajoutons le référentiel Neuron SDK à la liste des référentiels, et nous installons une version de TensorFlow Serving qui prend en charge AWS Inferentia.
  • Enfin, nous copions notre modèle BERT à l'intérieur du conteneur, et nous le chargeons au démarrage.

Voici le dossier complet.

DE AMAZONLINUX: 2
EXPOSE 8500 8501
RUN echo $ '[neuron] n
name = Dépôt Neuron YUM n
baseurl = https: //yum.repos.neuron.amazonaws.com n
enabled = 1 '> /etc/yum.repos.d/neuron.repo
RUN rpm - import https://yum.repos.neuron.amazonaws.com/GPG-PUB-KEY-AMAZON-AWS-NEURON.PUB
RUN yum install -y tensorflow-model-server-neuron
COPIER bert / bert
CMD ["/bin/sh", "-c", "/usr/local/bin/tensorflow_model_server_neuron --port=8500 --rest_api_port=8501 --model_name=bert --model_base_path=/bert/"]

Ensuite, je crée et pousse le conteneur vers un référentiel hébergé dans Amazon Elastic Container Registry. Affaires comme d'habitude.

$ docker build -t neuron-tensorflow-inference.

$ aws ecr create-repository - nom du référentiel ecs-inf1-demo

$ aws ecr get-login-password | connexion docker --username AWS --password-stdin 123456789012.dkr.ecr.us-east-1.amazonaws.com

$ balise docker neuron-tensorflow-inference 123456789012.dkr.ecr.us-east-1.amazonaws.com/ecs-inf1-demo:latest

$ docker push

Maintenant, nous devons créer une définition de tâche afin d'exécuter ce conteneur sur notre cluster.

Création d'une définition de tâche pour les instances Inf1
Si vous n'en avez pas déjà, vous devez d'abord créer un rôle d'exécution, c'est-à-dire un rôle permettant à l'agent ECS d'effectuer des appels d'API en votre nom. Vous pouvez trouver plus d'informations dans la documentation. Le mien s'appelle ecsTaskExecutionRole.

La définition complète de la tâche est visible ci-dessous. Comme vous pouvez le voir, il contient deux conteneurs:

  • Le conteneur BERT que j'ai construit,
  • Un conteneur side-car appelé neurone-rtd, qui permet au conteneur BERT d'accéder aux NeuronCores présents sur l'instance Inf1. le AWS_NEURON_VISIBLE_DEVICES La variable d'environnement vous permet de contrôler ceux qui peuvent être utilisés par le conteneur. Vous pouvez l'utiliser pour épingler un conteneur sur un ou plusieurs NeuronCores spécifiques.

  "famille": "ecs-neuron",
  "executionRoleArn": "arn: aws: iam :: 123456789012: role / ecsTaskExecutionRole",
  "containerDefinitions": [
    
      "entryPoint": [
        "sh",
        "-c"
      ],
      "portMappings": [
        
          "hostPort": 8500,
          "protocol": "tcp",
          "containerPort": 8500
        ,
        
          "hostPort": 8501,
          "protocol": "tcp",
          "containerPort": 8501
        ,
        
          "hostPort": 0,
          "protocol": "tcp",
          "containerPort": 80
        
      ],
      "commander": [
        "tensorflow_model_server_neuron --port=8500 --rest_api_port=8501 --model_name=bert --model_base_path=/bert"
      ],
      "cpu": 0,
      "environnement": [
        
          "name": "NEURON_RTD_ADDRESS",
          "value": "unix:/sock/neuron-rtd.sock"
        
      ],
      "mountPoints": [
        
          "containerPath": "/sock",
          "sourceVolume": "sock"
        
      ],
      "memoryReservation": 1 000,
      "image": "123456789012.dkr.ecr.us-east-1.amazonaws.com/ecs-inf1-demo:latest",
      "essentiel": vrai,
      "nom": "bert"
    ,
    
      "point d'accès": [
        "sh",
        "-c"
      ],
      "portMappings": [],
      "commander": [
        "neuron-rtd -g unix:/sock/neuron-rtd.sock"
      ],
      "cpu": 0,
      "environnement": [
        
          "name": "AWS_NEURON_VISIBLE_DEVICES",
          "value": "ALL"
        
      ],
      "mountPoints": [
        
          "containerPath": "/sock",
          "sourceVolume": "sock"
        
      ],
      "memoryReservation": 1 000,
      "image": "790709498068.dkr.ecr.us-east-1.amazonaws.com/neuron-rtd:latest",
      "essentiel": vrai,
      "linuxParameters": "capabilities": "add": ["SYS_ADMIN", "IPC_LOCK"] ,
      "nom": "neuron-rtd"
    
  ],
  "volumes": [
    
      "name": "sock",
      "host": 
        "sourcePath": "/tmp/sock"
      
    
  ]

Enfin, j'appelle le RegisterTaskDefinition API pour en informer le backend ECS.

$ aws ecs register-task-definition --cli-input-json file: //inf1-task-definition.json

Nous sommes maintenant prêts à exécuter notre conteneur et à prévoir avec lui.

Exécution d'un conteneur sur des instances Inf1
Étant donné qu'il s'agit d'un service de prédiction, je souhaite m'assurer qu'il est toujours disponible sur le cluster. Au lieu d'exécuter simplement une tâche, je crée un service ECS qui s'assurera que le nombre requis de copies de conteneurs est en cours d'exécution, en les relançant en cas de panne.

$ aws ecs create-service --cluster ecs-inf1-demo
--service-name bert-inf1
--task-definition ecs-neuron: 1
- nombre souhaité 1

Une minute plus tard, je vois que les deux conteneurs de tâches s'exécutent sur le cluster.

Conteneurs en cours d'exécution

Prédire avec BERT sur ECS et Inf1
Le fonctionnement interne de BERT dépasse le cadre de cet article. Ce modèle particulier attend une séquence de 128 jetons, codant les mots de deux phrases que nous aimerions comparer pour l’équivalence sémantique.

Ici, je ne suis intéressé que par la mesure de la latence de prédiction, donc les données factices conviennent. Je construis 100 requêtes de prédiction stockant une séquence de 128 zéros. En utilisant l'adresse IP du conteneur BERT, je les envoie au point de terminaison TensorFlow Serving via grpc, et je calcule le temps de prédiction moyen.

Voici le code complet.

importer numpy comme np
importer grpc
importer tensorflow en tant que tf
depuis tensorflow_serving.apis import predict_pb2
depuis tensorflow_serving.apis import prediction_service_pb2_grpc
temps d'importation

si __name__ == '__main__':
    canal = grpc.insecure_channel ('18 .234.61.31: 8500 ')
    stub = prediction_service_pb2_grpc.PredictionServiceStub (canal)
    request = predict_pb2.PredictRequest ()
    request.model_spec.name = 'bert'
    i = np.zeros ([1, 128], dtype = np.int32)
    request.inputs['input_ids'].CopyFrom (tf.contrib.util.make_tensor_proto (i, shape = i.shape))
    request.inputs['input_mask'].CopyFrom (tf.contrib.util.make_tensor_proto (i, shape = i.shape))
    request.inputs['segment_ids'].CopyFrom (tf.contrib.util.make_tensor_proto (i, shape = i.shape))

    latences = []
    pour i dans la plage (100):
        start = time.time ()
        result = stub.Predict (demande)
        latencies.append (time.time () - start)
        print ("Inférence réussie: ". format (i))
    print ("Ran  inférences réussies. Latence moyenne = ". format (len (latences), np.average (latences)))

Pour plus de commodité, j'exécute ce code sur une instance EC2 basée sur l'AMI Deep Learning. Il est livré pré-installé avec un environnement Conda pour TensorFlow et TensorFlow Serving, ce qui m'évite d'installer des dépendances.

$ source activate tensorflow_p36
$ python predict.py

En moyenne, la prédiction a pris 56,5 ms. En ce qui concerne BERT, c'est plutôt bien!

Ran 100 inférences avec succès. Latence moyenne = 0,05647835493087769

Commencer
Vous pouvez maintenant déployer Amazon Elastic Compute Cloud (EC2) Instances Inf1 sur Amazon ECS aujourd'hui dans le USA Est (Virginie du Nord) et USA Ouest (Oregon) Régions. Au fur et à mesure que le déploiement d'Inf1 progresse, vous pourrez les utiliser avec Amazon ECS dans plus de régions.

Essayez-le et envoyez-nous vos commentaires via vos contacts AWS Support habituels, sur le forum AWS pour Amazon ECS ou sur la feuille de route du conteneur sur Github.

– Julien

Commentaires

Laisser un commentaire

Votre commentaire sera révisé par les administrateurs si besoin.