Inférence de machine learning à l'aide de AWS Inferentia - Amazon EKS

Inférence de machine learning à l'aide de AWS Inferentia

Cette rubrique décrit comment créer un cluster Amazon EKS avec des nœuds de travail exécutant des instances Amazon EC2 Inf1 et (éventuellement) déployer un exemple d'application. Les instances Amazon EC2 Inf1 sont alimentées par des puces AWS Inferentia qui sont conçues sur mesure par AWS pour fournir des performances élevées et des inférences de coûts les plus bas dans le cloud. Les modèles de machine learning sont déployés sur des conteneurs à l'aide de AWS Neuron, un kit de développement logiciel (SDK) spécialisé composé d'un compilateur, d'un moteur d'exécution et d'outils de profilage qui optimisent les performances d'inférence de machine learning des puces Inferentia. AWS Neuron prend en charge les cadres de machine learning populaires tels que TensorFlow, PyTorch et MXNet.

Note

Les ID logiques de l'appareil Neuron doivent être contigus. Si un Pod demandant plusieurs appareils Neuron est programmé sur un inf1.6xlarge ou un type d'instance inf1.24xlarge (qui a plusieurs appareils Neuron), ce Pod ne démarrera pas si le planificateur Kubernetes sélectionne des ID d'appareil non contigus. Pour de plus amples informations, veuillez consulter Les ID logiques d'appareils doivent être contigus sur GitHub.

Prérequis

Créer un cluster

Pour créer un cluster avec des nœuds d'instances Amazon EC2 Inf1
  1. Créez un cluster avec des nœuds d'instances Amazon EC2 Inf1. Vous pouvez remplacer inf1.2xlarge par n'importe quel type d'instance Inf1. L'utilitaire eksctl détecte que vous lancez un groupe de nœuds avec un type d’instance Inf1 et démarre vos nœuds à l'aide de l'une des AMI Amazon Linux optimisées et accélérées.

    Note

    Vous ne pouvez pas utiliser les rôles IAM pour les comptes de service avec TensorFlow Serving.

    eksctl create cluster \ --name inferentia \ --region region-code \ --nodegroup-name ng-inf1 \ --node-type inf1.2xlarge \ --nodes 2 \ --nodes-min 1 \ --nodes-max 4 \ --ssh-access \ --ssh-public-key your-key \ --with-oidc
    Note

    Notez la valeur de la ligne suivante de la sortie. Elle est utilisée lors d'une étape ultérieure (facultative).

    [9] adding identity "arn:aws:iam::111122223333:role/eksctl-inferentia-nodegroup-ng-in-NodeInstanceRole-FI7HIYS3BS09" to auth ConfigMap

    Lors du lancement d'un groupe de nœuds avec des instances Inf1, eksctl installe automatiquement le plugin d'appareil AWS Neuron de Kubernetes. Ce plugin annonce les appareils Neuron comme une ressource système au planificateur Kubernetes, qui peut être demandée par un conteneur. Outre les stratégies IAM de nœud Amazon EKS par défaut, la stratégie d'accès en lecture seule Amazon S3 est ajoutée afin que l'exemple d'application, traité dans une étape ultérieure, puisse charger un modèle formé à partir d'Amazon S3.

  2. Assurez-vous que tous les Pods ont démarré correctement.

    kubectl get pods -n kube-system

    Sortie abrégée :

    NAME READY STATUS RESTARTS AGE [...] neuron-device-plugin-daemonset-6djhp 1/1 Running 0 5m neuron-device-plugin-daemonset-hwjsj 1/1 Running 0 5m

(Facultatif) Déployer une image d'application TensorFlow Serving

Un modèle formé doit être compilé sur une cible Inferentia avant de pouvoir être déployé sur des instances Inferentia. Pour continuer, vous aurez besoin d'un modèle TensorFlow optimisé pour Neuron enregistré dans Amazon S3. Si vous n'avez pas encore de SavedModel, veuillez suivre le didacticiel pour la création d'un modèle Resnet50 compatible Neuron et téléchargez le SavedModel résultant dans S3. ResNet-50 est un modèle de machine learning populaire utilisé pour les tâches de reconnaissance d'images. Pour plus d'informations sur la compilation de modèles Neuron, consultez La puce AWS Inferentia avec DLAMI dans le Guide du développeur AWS Deep Learning AMI.

L'exemple de manifeste de déploiement gère un conteneur de service d'inférence préconstruit pour TensorFlow fourni par les AWS Deep Learning Containers. À l'intérieur du conteneur se trouve le moteur d'exécution AWS Neuron et l'application TensorFlow Serving. Une liste complète des conteneurs Deep Learning préconstruits optimisés pour Neuron est conservée sur GitHub sous Images disponibles. Au démarrage, le DLC récupère votre modèle d'Amazon S3, lance Neuron TensorFlow Serving avec le modèle enregistré et attend les demandes de prédiction.

Le nombre d'appareils Neuron alloués à votre application de service peut être ajusté en changeant la ressource aws.amazon.com/neuron dans le yaml de déploiement. Veuillez noter que la communication entre TensorFlow Serving et le moteur d'exécution Neuron se fait via GRPC, ce qui nécessite de transmettre la capacité IPC_LOCK au conteneur.

  1. Ajoutez la stratégie IAM AmazonS3ReadOnlyAccess au rôle d'instance de nœud créé à l'étape 1 de Créer un cluster . Ceci est nécessaire pour que l'application exemple puisse charger un modèle formé à partir de Amazon S3.

    aws iam attach-role-policy \ --policy-arn arn:aws:iam::aws:policy/AmazonS3ReadOnlyAccess \ --role-name eksctl-inferentia-nodegroup-ng-in-NodeInstanceRole-FI7HIYS3BS09
  2. Créez un fichier nommé rn50_deployment.yaml avec les contenus suivants. Mettez à jour le code régional et le chemin du modèle pour correspondre aux paramètres souhaités. Le nom du modèle est à des fins d'identification lorsqu'un client fait une demande au serveur TensorFlow. Cet exemple utilise un nom de modèle pour correspondre à un exemple de script client ResNet50 qui sera utilisé lors d'une étape ultérieure pour envoyer des demandes de prédiction.

    aws ecr list-images --repository-name neuron-rtd --registry-id 790709498068 --region us-west-2
    kind: Deployment apiVersion: apps/v1 metadata: name: eks-neuron-test labels: app: eks-neuron-test role: master spec: replicas: 2 selector: matchLabels: app: eks-neuron-test role: master template: metadata: labels: app: eks-neuron-test role: master spec: containers: - name: eks-neuron-test image: 763104351884.dkr.ecr.us-east-1.amazonaws.com/tensorflow-inference-neuron:1.15.4-neuron-py37-ubuntu18.04 command: - /usr/local/bin/entrypoint.sh args: - --port=8500 - --rest_api_port=9000 - --model_name=resnet50_neuron - --model_base_path=s3://your-bucket-of-models/resnet50_neuron/ ports: - containerPort: 8500 - containerPort: 9000 imagePullPolicy: IfNotPresent env: - name: AWS_REGION value: "us-east-1" - name: S3_USE_HTTPS value: "1" - name: S3_VERIFY_SSL value: "0" - name: S3_ENDPOINT value: s3.us-east-1.amazonaws.com - name: AWS_LOG_LEVEL value: "3" resources: limits: cpu: 4 memory: 4Gi aws.amazon.com/neuron: 1 requests: cpu: "1" memory: 1Gi securityContext: capabilities: add: - IPC_LOCK
  3. Déployez le modèle.

    kubectl apply -f rn50_deployment.yaml
  4. Créez un fichier nommé rn50_service.yaml avec les contenus suivants. Les ports HTTP et gRPC sont ouverts pour accepter les demandes de prédiction.

    kind: Service apiVersion: v1 metadata: name: eks-neuron-test labels: app: eks-neuron-test spec: type: ClusterIP ports: - name: http-tf-serving port: 8500 targetPort: 8500 - name: grpc-tf-serving port: 9000 targetPort: 9000 selector: app: eks-neuron-test role: master
  5. Créez un service Kubernetes pour votre application Serving modèle TensorFlow.

    kubectl apply -f rn50_service.yaml

(Facultatif) Faites des prévisions pour votre service TensorFlow Serving

  1. Pour tester localement, transférez le port gRPC au service eks-neuron-test.

    kubectl port-forward service/eks-neuron-test 8500:8500 &
  2. Créez un script Python appelé tensorflow-model-server-infer.py avec le contenu suivant. Ce script exécute l'inférence via gRPC, qui est une infrastructure de service.

    import numpy as np import grpc import tensorflow as tf from tensorflow.keras.preprocessing import image from tensorflow.keras.applications.resnet50 import preprocess_input from tensorflow_serving.apis import predict_pb2 from tensorflow_serving.apis import prediction_service_pb2_grpc from tensorflow.keras.applications.resnet50 import decode_predictions if __name__ == '__main__': channel = grpc.insecure_channel('localhost:8500') stub = prediction_service_pb2_grpc.PredictionServiceStub(channel) img_file = tf.keras.utils.get_file( "./kitten_small.jpg", "https://raw.githubusercontent.com/awslabs/mxnet-model-server/master/docs/images/kitten_small.jpg") img = image.load_img(img_file, target_size=(224, 224)) img_array = preprocess_input(image.img_to_array(img)[None, ...]) request = predict_pb2.PredictRequest() request.model_spec.name = 'resnet50_inf1' request.inputs['input'].CopyFrom( tf.make_tensor_proto(img_array, shape=img_array.shape)) result = stub.Predict(request) prediction = tf.make_ndarray(result.outputs['output']) print(decode_predictions(prediction))
  3. Exécutez le script pour soumettre des prédictions à votre service.

    python3 tensorflow-model-server-infer.py

    L'exemple qui suit illustre un résultat.

    [[(u'n02123045', u'tabby', 0.68817204), (u'n02127052', u'lynx', 0.12701613), (u'n02123159', u'tiger_cat', 0.08736559), (u'n02124075', u'Egyptian_cat', 0.063844085), (u'n02128757', u'snow_leopard', 0.009240591)]]