BLOG

3,000개의 Amazon EKS 딥러닝 모델, AWS Inferentia를 사용하면 시간당 $50 미만으로 해결!
작성일: 2021-10-25

점점 더 많은 고객들이 클라우드에서 더욱 크고, 확장 가능하며 비용 효율적인 머신 러닝(ML) 인퍼런스 파이프라인 구축의 필요성을 느끼고 있습니다. 머신 러닝의 필수 조건 외에 프로덕션에서 ML 인퍼런스 파이프라인을 구축하는 것은 비즈니스 사용 사례에 따라 달라집니다. 추천 엔진, 감성 분석(sentiment analysis) 및 광고 랭킹과 같은 애플리케이션을 위한 일반적인 인퍼런스 아키텍처는 기존의 ML과 딥 러닝(DL) 모델이 혼합된 수많은 모델을 제공해야 합니다. 또한, 각 모델은 API(응용 프로그래밍 인터페이스) 엔드포인트를 통해 액세스할 수 있어야 하며 요청을 받은 시점부터 사전 정의된 지연 시간 예산 내에서 응답할 수 있어야 합니다.

 

이번 포스팅에서는 Salesforce의 Commerce Einstein 팀과 공동으로 개발한 인퍼런스 아키텍처에 대해 알아보겠습니다. 이 인퍼런스 아키텍처는 Amazon Elastic Kubernetes Service (Amazon EKS)를 기반으로 구축되어 기본 전제 조건을 해결할 뿐만 아니라 수천 개의 고유한 DL 모델을 확장 가능한 아키텍처로 묶습니다. 비용 및 성능 측면에서 최적의 설계를 개발하기 위해 Amazon Elastic Compute Cloud (Amazon EC2) 인스턴스 제품군(c5, g4dn, Inf1)의 혼합을 탐색합니다. 이러한 필요 사항을 충족하기 위해 FastAPI를 사용하여 Amazon EKS에서 DL 추론 서비스를 구축합니다.

 

가볍고 효율적인 Python 기반 API 서버를 개발하고 모델 간에 컴퓨팅 및 메모리 리소스를 효율적으로 공유하기 위한 모델 빈 패킹 전략을 개발합니다. 아키텍처를 로드 테스트하기 위해 huggingface.co ( bert-base-cased, 약 800MB )의 자연어 처리(NLP) 오픈 소스 모델 을 사용하고 서비스 풀에 동시 요청을 보내는 수천 명의 클라이언트를 시뮬레이션합니다. Inf1 인스턴스의 사용자 지정 ML 칩인 AWS Inferentia를 사용하여 3,000개의 고유 ML 모델을 패키징 및 제공하는 동시에 목표 대비 왕복 지연 시간이 70밀리초(P90)인 시간당 $50(온디맨드 요금) 미만으로 비용을 유지합니다. 100밀리초의. 이 아키텍처 및 최적화 접근 방식을 모든 사용자 지정 DL 모델로 확장할 수 있습니다.

 

 

솔루션 개요

 

다음은 가용 영역에 배포할 수 있는 표준 Amazon EKS 인프라를 기반으로 하는 간단하고 확장 가능하며 가용성이 높은 아키텍처입니다.

 

 

Amazon EKS 클러스터에는 노드 그룹당 하나의 EC2 인스턴스 패밀리가 있는 여러 노드 그룹이 있습니다. 각 노드 그룹은 CPU(c5), GPU(g4dn) 및 AWS Inferentia(Inf1)와 같은 다양한 인스턴스 유형을 지원할 수 있으며, 인스턴스당 여러 모델을 패킹하여 제공되는 모델 수를 최대화할 수 있습니다. 다음으로 모델 제공 애플리케이션 및 DL 프레임워크 종속성이 컨테이너화되고 이러한 컨테이너 이미지가 Amazon Elastic Container Registry (Amazon ECR)에 저장됩니다. 컨테이너 이미지는 각 인스턴스 패밀리에 맞게 사용자 지정된 배포 및 서비스 매니페스트를 사용하여 클러스터에 배포됩니다. 모델 제공 애플리케이션은 Amazon Simple Storage Service 에서 모델 아티팩트를 다운로드합니다. (Amazon S3) 서버 초기화 시 Amazon ECR의 컨테이너 이미지 크기를 줄이고 모델 데이터를 서비스 정의에서 분리합니다.

 

cluster-autoscaler, horizontal-pod-autoscaler, aws-load-balancer-controller, metrics-server, nginx-ingress-controller, neuron-device-plugin-daemonset나 nvidia-device-plugin-daemonset와 같은 서비스가 필요에 따라 클러스터에 배포됩니다. 이 디자인은 클러스터 내 서비스 엔드포인트의 이름 확인을 위해 Kubernetes coredns에 의존합니다. 각 모델은 아래 예시처럼 DNS 이름과 모델 이름의 조합을 통해 주소를 지정할 수 있습니다.

 

예) http://<model server ID>.<name space>.svc.cluster.local:8080/predictions/<model id>.

 

DNS 이름의 사용자 지정을 위해 수신 매니페스트를 사용할 수 있습니다. 아키텍처는 빌드, 추적, 압축, 배포 및 테스트의 5가지 간단한 단계로 실행되도록 설정됩니다. 코드 리포지토리는 GitHub 리포지토리에서 액세스할 수 있습니다.

 

1. 빌드 단계에서는 선택한 인스턴스 유형에 대한 기본 컨테이너를 빌드하고 컨테이너에 필요한 모든 기본 레이어를 설치합니다.

 

2. 추적 단계는 모델을 컴파일합니다. 모델은 대상 EC2 인스턴스에서 실행됩니다. Inf1에서 실행하려면 AWS Neuron SDK를 사용하여 모델을 추적해야 합니다. 다음은 AWS Inferentia의 bfloat16 또는 GPU 인스턴스의 AMP(자동 혼합 정밀도)에서 실행되는 모델을 추적하는 코드 조각입니다.

 

 

print(‘\nTracing model …’)

example_inputs = (   

torch.cat([inputs[‘input_ids’]] * batch_size,0),     

torch.cat([inputs[‘attention_mask’]] * batch_size,0)

)

os.makedirs(f’traced-{model_name}’, exist_ok=True)

torch.set_num_threads(6)

if ‘inf’ in processor:   

model_traced = torch.neuron.trace(model,            

example_inputs,            

verbose=1,            

compiler_workdir=f’./traced-{model_name}/compile_wd_{processor}_bs{batch_size}_seq {sequence_length}_pc{pipeline_cores}’,             

compiler_args = [‘–neuroncore-pipeline-cores’, str(pipeline_cores)])

else:

model_traced = torch.jit.trace(model, example_inputs)

 

 

3. 포장 단계는 FastAPI를 사용하여 컨테이너에 모델을 포장하며, 동일한 컨테이너 내에서 여러 모델을 포장할 수도 있습니다.

 

4. 배포 단계는 구성된 런타임(예: Kubernetes 또는 Docker)에서 모델을 실행하고 모델 서버 컨테이너의 전체 수명 주기 관리를 용이하게 합니다. 다음 코드 조각은 실행 옵션을 설정하고 구성된 런타임에서 컨테이너를 시작합니다.

 

 

echo “Runtime: $runtime”

echo “Processor: $processor” 

if [ “$runtime” == “docker” ]; then   

 server=0   

 while [ $server -lt $num_servers ]; do

   run_opts=“–name ${app_name}-${server} -e NUM_MODELS=$num_models -e POSTPROCESS=$postprocess -e QUIET=$quiet -P”      

   if [ “$processor” == “gpu” ]; then           

    run_opts=”–gpus 0 ${run_opts}”      

   fi      

   CMD=“docker run -d ${run_opts} ${registry}${model_image_name}${model_image_tag}”      

   echo “$CMD”      

   eval “$CMD”      

 server=$((server+1))   

 done

elif [ “$runtime” == “kubernetes” ]; then   

 kubectl create namespace ${namespace} –dry-run=client -o yaml | kubectl apply -f –   

 ./generate-yaml.sh   

 kubectl apply -f ${app_dir}

else   

 echo “Runtime $runtime not recognized”

fi

 

 

5. 마지막 단계에서는 런타임 환경에 배포된 모델 서버에 대해 테스트를 실행합니다.

 

 

Bin packing ML 모델

 

EC2 인스턴스에서 ML 모델의 빈 패킹(Bin packing)은 모델 간에 컴퓨팅 및 메모리 리소스를 효율적으로 공유하는 데 필수적입니다. 모델을 빈 패킹하는 작업은 조합 최적화를 사용하여 0-1 배낭 문제로 공식화하고 해결할 수 있습니다. 다음은 빈 패킹에 대한 수학적 공식입니다. nmodels 은 최대 프로세서 메모리(M max ) 및 사용률(C max ) 의 제약을 받습니다. 이 접근 방식은 최소 EC2 인스턴스 세트에서 모델의 최적의 빈 패킹을 권장합니다.

 

 

빈의 수는 빈당 하나의 모델의 간단한 솔루션으로 문제를 초기화하기 위해 극대화되며, 최소한의 빈으로 목표를 달성하기 위해 정리됩니다.

 

 

다음 시각화는 각각 고유한 메모리 및 컴퓨팅 요구 사항이 있는 78개 모델에 대한 샘플 빈 패킹 할당을 보여줍니다. 이 예에서 78개의 모델은 지정된 대상 최대 메모리(7.4GB) 및 컴퓨팅 용량(83%)을 사용하여 23개의 인스턴스(g4dn, Inf1)로 압축되었습니다. 색상 범례는 모델 인덱스를 나타냅니다.

 

 

위의 방법을 사용하여 인스턴스 간에 모델을 최적으로 비닝할 수 있습니다. 다음 표에는 Inf1 및 g4dn 인스턴스에 대한 bin 패킹 결과가 요약되어 있습니다. 트랜스포머 기반 NLP 모델은 예상 대기 시간을 달성하기 위해 하드웨어 가속이 필요하기 때문에 이러한 인스턴스 패밀리를 선택했습니다. Neuron 컴파일러의 자동 캐스팅 기능이 자동으로 FP32 모델을 16비트 bfloat으로 변환하여 처리량을 최대화하기 때문에 g4dn.12xlarge(192GiB 메모리)에 비해 Inf1.6xlarge(48GiB 메모리)에 더 많은 모델을 bin pack할 수 있었습니다.

 

 

 

테스트 방법론 및 관찰

 

대규모로 테스트를 로드하기 위해 테스트 풀에 동시 요청을 보내는 40개 이상의 클라이언트를 시뮬레이션했습니다(여러 클라이언트에서 로드). 더 많은 사용자 요청으로 시스템을 로드하면 지연 시간은 늘어나고 처리량이 증가합니다. 테스트는 처리량-대기 시간 곡선을 스윕하여 리소스 사용이 최적화된 데이터 포인트를 찾도록 설계되었습니다. 처리량과 지연 시간(P50, P90, P95)을 측정하고 지연 시간, 처리량(초당 추론), 인스턴스당 제공되는 모델 수, 비용의 네 가지 지표에 대한 결과를 요약했습니다. 또한, 테스트 풀의 각 모델에 GET 또는 POST 요청을 보내기 위해 curl을 사용하여 단일 순차 및 단일 무작위 요청을 시뮬레이션하는 테스트를 만들었습니다. 이 실험의 목적은 우리가 예상할 수 있는 최상의 대기 시간을 기준으로 측정하는 것이었습니다.

 

우리는 최소 비용으로 최고의 성능을 얻을 수 있는 최소 EC2 인스턴스 세트에서 최적의 모델 패킹을 찾기 위해 여러 실험을 실행했습니다. 다음 표에는 이러한 테스트 결과 중 일부가 요약되어 있습니다. 최상의 결과는 DNS 캐싱이 활성화된 40개의 Inf1.6xl 인스턴스를 사용하여 66밀리초(P90 지연 시간)의 처리량으로 3,040개 모델을 제공하고 비용은 시간당 $47.2(온디맨드)로 관찰되었습니다. 32개의 inf1.6xl 및 21개의 g4dn.12xl 인스턴스를 사용하는 최상의 혼합 인스턴스 배포는 3,048개의 모델을 제공했지만 초당 248개의 요청으로 처리량이 훨씬 낮았고, 시간당 비용은 $119.91 증가했습니다. 이 아키텍처에서 비용 최적화를 위한 수단으로 EC2 스팟 인스턴스를 사용하지는 않았지만, 추론 워크로드가 시간에 유연하고 내결함성이 있는 경우 Spot을 사용하는 것이 좋습니다. 다음 표에는 인스턴스 유형에 대한 관찰이 요약되어 있습니다.

 

 

 

결론

 

이 확장 가능한 아키텍처를 통해 우리는 3,000개 모델에 걸쳐 추론을 확장하여 100밀리초의 목표 지연 시간을 달성하는 동시에 최소한의 집합에 걸쳐 모델을 효율적으로 빈 포장하여 비용을 최적화함으로써 비용을 시간당 $50(온디맨드) 미만으로 유지할 수 있었습니다. EC2 인스턴스. 모든 테스트에서 Inf1 인스턴스는 다른 인스턴스에 비해 가장 높은 처리량, 가장 낮은 비용, 가장 빠른 응답 시간 및 최대 bin 패킹 비율을 산출했습니다. Snap, Airbnb, Sprinklr 등과 같은 AWS 고객 AWS Inferentia를 사용하여 다양한 배포에서 최고의 성능과 최저 비용을 달성했습니다. 테스트된 DL 모델은 Inf1 및 g4dn 인스턴스 유형에서 하드웨어 가속을 사용해야 하지만 설명된 방법론을 사용하여 그에 따라 다른 인스턴스 유형(Inf1, CPU, GPU) 및 bin 팩 모델이 있는 다른 모델 유형을 일치시킬 수 있습니다.

 

Neuron SDK를 사용하여 AWS Inferentia에서 사용자 지정 ML 파이프라인 실행을 시작하려면 AWS Inferentia 칩 및 EC2 Inf1 인스턴스 에 대해 자세히 알아보세요.

 

원문URL: https://aws.amazon.com/ko/blogs/machine-learning/serve-3000-deep-learning-models-on-amazon-eks-with-aws-inferentia-for-under-50-an-hour/

메가존 클라우드 TechBlog는 AWS BLOG 영문 게재 글이나 관련 기사 중에서 한국 사용자들에게 유용한 정보 및 콘텐츠를 우선적으로 번역하여 내부 엔지니어 검수를 받아 정기적으로 게재하고 있습니다. 추가로 번역 및 게재를 희망하는 글에 대해서 관리자에게 메일 또는 SNS 페이지에 댓글을 남겨주시면, 우선적으로 번역해서 전달해드리도록 하겠습니다.