AWS Inferentia를 사용한 기계 학습 추론 - Amazon EKS

AWS Inferentia를 사용한 기계 학습 추론

이 주제에서는 Amazon EC2 Inf1 인스턴스를 실행하는 노드가 있는 Amazon EKS 클러스터를 생성하고 샘플 애플리케이션을 배포(선택 사항)하는 방법을 설명합니다. Amazon EC2 Inf1 인스턴스는 AWS Inferentia 칩으로 구동됩니다. 이 칩은 클라우드에서 고성능의 가장 저렴한 추론을 제공하기 위해 AWS에서 사용자 지정으로 구축됩니다. 기계 학습 모델은 Inferentia 칩의 기계 학습 추론 성능을 최적화하는 컴파일러, 런타임 및 프로파일링 도구로 구성된 특수 소프트웨어 개발 키트(SDK)인 AWS Neuron을 사용하여 컨테이너에 배포됩니다. AWS Neuron은 TensorFlow, PyTorch, MXNet과 같은 인기 있는 기계 학습 프레임워크를 지원합니다.

참고

Neuron 디바이스 논리적 ID는 연속적이어야 합니다. Neuron 디바이스를 여러 개 요청하는 Pod가 inf1.6xlarge 또는 inf1.24xlarge 인스턴스 유형(둘 이상의 Neuron 디바이스가 있음)에서 예약된 경우 Kubernetes 스케줄러가 불연속적인 디바이스 ID를 선택하면 해당 Pod가 시작되지 않습니다. 자세한 내용은 GitHub의 Device logical IDs must be contiguous를 참조하세요.

사전 조건

  • eksctl가 컴퓨터에 설치되어 있어야 합니다. 설치되지 않은 경우 eksctl 설명서에서 Installation을 참조하세요.

  • kubectl가 컴퓨터에 설치되어 있어야 합니다. 자세한 내용은 kubectl 설치 또는 업데이트 섹션을 참조하세요.

  • (선택 사항) python3이 컴퓨터에 설치되어 있어야 합니다. 설치되어 있지 않은 경우 Python downloads를 참조하여 설치 지침을 확인하십시오.

클러스터 생성

Inf1 Amazon EC2 인스턴스 노드를 사용하여 클러스터를 생성하려면
  1. Inf1 Amazon EC2 인스턴스 노드를 사용하여 클러스터를 생성합니다. inf1.2xlarge를 모든 Inf1 인스턴스 유형으로 바꿀 수 있습니다. eksctl 유틸리티는 Inf1 인스턴스 유형을 사용하여 노드 그룹을 시작한다는 것을 감지하고 Amazon EKS 최적화 가속 Amazon Linux AMI 중 하나를 사용하여 노드를 시작합니다.

    참고

    TensorFlow Serving에서는 서비스 계정에 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 Serving 애플리케이션 이미지 배포

훈련된 모델은 Inferentia 인스턴스에서 배포하기 전에 Inferentia 대상에 컴파일되어야 합니다. 계속하려면, Amazon S3 저장된 Neuron 최적화 TensorFlow 모델이 필요합니다. 아직 SavedModel이 없는 경우 Neuron 호환 ResNet50 모델 생성에 대한 자습서를 따르고 그 결과로 생성된 SavedModel을 S3에 업로드합니다. ResNet-50은 이미지 인식 작업에 사용되는 인기 있는 기계 학습 모델입니다. Neuron 모델 컴파일에 대한 자세한 내용은 AWS Deep Learning AMI 개발자 가이드에서 DLAMI를 사용한 AWS Inferentia 칩 섹션을 참조하세요.

샘플 배포 매니페스트는 AWS Deep Learning Containers에서 제공되는 사전 구축된 TensorFlow용 추론 Serving 컨테이너를 관리합니다. 이 컨테이너 내부에는 AWS Neuron 런타임 및 TensorFlow Serving 애플리케이션이 있습니다. Neuron에 최적화된 사전 구축된 딥 러닝 컨테이너의 전체 목록은 사용 가능한 이미지아래 GitHub에서 관리됩니다. 시작 시 DLC가 Amazon S3에서 모델을 가져오고, 저장된 모델로 Neuron TensorFlow Serving을 시작하고, 예측 요청을 기다립니다.

Serving 애플리케이션에 할당된 Neuron 디바이스의 수는 배포 yaml에서 aws.amazon.com/neuron 리소스를 변경하여 조정할 수 있습니다. TensorFlow Serving과 Neuron 런타임 간의 통신은 GRPC를 통해 발생하므로 IPC_LOCK 기능을 컨테이너에 전달해야 합니다.

  1. 클러스터 생성의 1단계에서 생성한 노드 인스턴스 역할에 AmazonS3ReadOnlyAccess IAM 정책을 추가합니다. 이는 샘플 애플리케이션이 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 서버에 요청할 때 식별을 위한 것입니다. 이 예에서는 모델 이름을 사용하여 예측 요청을 보내는 이후 단계에서 사용할 샘플 ResNet50 클라이언트 스크립트와 일치시킵니다.

    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 모델 Serving 애플리케이션을 위한 Kubernetes 서비스를 생성합니다.

    kubectl apply -f rn50_service.yaml

(선택 사항) TensorFlow Serving 서비스에 대한 예측

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