使用 AWS Inferentia 的機器學習推論 - Amazon EKS

本文為英文版的機器翻譯版本,如內容有任何歧義或不一致之處,概以英文版為準。

使用 AWS Inferentia 的機器學習推論

本主題描述了如何建立 Amazon EKS 叢集,其中具有執行 Amazon EC2 Inf1 執行個體的節點,以及 (選用) 如何部署範例應用程式。Amazon EC2 Inf1 執行個體由AWS 推論晶片提供支援,這些晶片由 AWS 客製化建置,可在雲端中提供高效能和最低成本的推論。機器學習模型使用 AWS Neuron 部署到容器中,Neuron 是一種專門的軟體開發套件 (SDK),由編譯器、執行階段和剖析工具組成,可最佳化 Inferentia 晶片的機器學習推論效能。 AWS 神經元支持流行的機器學習框架,例如 TensorFlow PyTorch,和 MXNet。

注意

Neuron 裝置邏輯 ID 必須是連續的。如果請求多個 Neuron 裝置的 Pod 已排程在某個 inf1.6xlargeinf1.24xlarge 執行個體類型 (具有多個 Neuron 裝置) 上,倘若 Kubernetes 排程器選取非連續的裝置 ID,該 Pod 將無法啟動。如需詳細資訊,請參閱 GitHub 上的 Device logical IDs must be contiguous (裝置邏輯 ID 必須是連續的)。

必要條件

  • eksctl 安裝在您的電腦上。如果您尚未安裝,請參閱 eksctl 文件中的 Installation 一節。

  • kubectl 安裝在您的電腦上。如需詳細資訊,請參閱 安裝或更新 kubectl

  • (選用) 將 python3 安裝在您的電腦上。如果您尚未安裝,請參閱 Python 下載以取得安裝指示。

建立叢集

建立具有 Inf1 Amazon EC2 執行個體之節點的叢集
  1. 建立具有 Inf1 Amazon EC2 執行個體之節點的叢集。您可以使用任何 Inf1 執行個體類型取代 inf1.2xlargeeksctl 公用程式偵測到您正在啟動具有 Inf1 執行個體類型的節點群組,並將使用 Amazon EKS 最佳化加速 Amazon Linux AMI 之一來啟動您的節點。

    注意

    您無法透 TensorFlow 過「服務」將 IAM 角色用於服務帳戶

    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
    注意

    請注意下列輸出行的值。它將用於稍後的 (選用) 步驟。

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

    使用Inf1執行個體啟動節點群組時,eksctl會自動安裝 AWS Neuron 裝Kubernetes置外掛程式。這個外掛程式會將 Neuron 裝置做為系統資源公告給 Kubernetes 排程器,如此就能由容器請求。除了預設 Amazon EKS 節點 IAM 政策之外,還會新增 Amazon S3 唯讀存取政策,以便稍後步驟介紹的範例應用程式可以從 Amazon S3 載入訓練過的模型。

  2. 請確定所有的 Pods 都已正確啟動。

    kubectl get pods -n kube-system

    縮寫輸出:

    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

(選擇性) 部署 TensorFlow服務應用程式映像

經過訓練的模型必須編譯至 Inferentia 目標,才能部署到 Inferentia 執行個體上。若要繼續,您需要在 Amazon S3 中儲存一個神經元最佳化 TensorFlow模型。如果您還沒有 SavedModel,請按照教程創建 Neuron 兼容 ResNet 50 模型,並 SavedModel 將結果上傳到 S3。 ResNet-50 是一種流行的機器學習模型,用於圖像識別任務。如需有關編譯神經元模型的詳細資訊,請參閱開AWS 發人員指南中的含 DLAMI 的推論晶片。 AWS Deep Learning AMI

範例部署資訊清單會管理 AWS Deep Learning Containers 所 TensorFlow 提供的預先建置推論服務容器。容器內部是 AWS 神經元運行時和 TensorFlow 服務應用程序。針對 Neuron 最佳化的預建置 Deep Learning Containers 完整清單會在 GitHub 上進行維護,位於可用映像下。在啟動時,DLC 將從 Amazon S3 擷取您的模型、使用儲存的模型啟動神經元 TensorFlow 服務,然後等待預測請求。

分配給服務應用程式的 Nesuron 裝置數量可以進行調整,方法是變更部署 yaml 中的 aws.amazon.com/neuron 資源。請注意, TensorFlow 服務與 Neuron 執行階段之間的通訊會透過 GRPC 進行,因此需要將IPC_LOCK功能傳遞至容器。

  1. AmazonS3ReadOnlyAccess IAM 政策新增至步驟 1/建立叢集 中建立的節點執行個體角色。這是必要步驟,以便範例應用程式可以從 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. 使用下列內容建立名為 rn50_deployment.yaml 的檔案。更新區域碼和模型路徑以符合您想要的設定。當客戶端向 TensorFlow 服務器發出請求時,模型名稱用於識別目的。此範例使用模型名稱來比對範例 ResNet 50 用戶端指令碼,該指令碼將在稍後的步驟中用於傳送預測要求。

    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. 部署模型。

    kubectl apply -f rn50_deployment.yaml
  4. 使用下列內容建立名為 rn50_service.yaml 的檔案。HTTP 和 gRPC 連接埠會開啟以接受預測請求。

    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. 為您的 TensorFlow 模型 Kubernetes Service 應用程式建立服務。

    kubectl apply -f rn50_service.yaml

(可選)針對您的服 TensorFlow 務進行預測

  1. 若要在本機測試,請將 gRPC 連接埠轉送至 eks-neuron-test 服務。

    kubectl port-forward service/eks-neuron-test 8500:8500 &
  2. 建立一個叫做 tensorflow-model-server-infer.py 的 Python 指令碼,具有以下內容。此指令碼透過 gRPC (為一服務框架) 執行推斷。

    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. 執行指令碼,將預測提交至您的服務。

    python3 tensorflow-model-server-infer.py

    範例輸出如下。

    [[(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)]]