03. Inference component: 모델별 독립 스케일¶
GPU 환경에서 모델별 자원 배정과 scaling이 가능한가요?
가능합니다. 다만 GPU 인스턴스에서는 component copy마다 GPU를 최소 한 장 할당해야 합니다.
개념부터 보려면
Inference component가 무엇이고 왜 만들어졌는지는 SageMaker AI inference component에 정리했습니다 (AWS 문서와 블로그 근거 포함).
모델별 scaling과 routing이 필요할 때 선택
컴포넌트를 만들 때 GPU를 몇 장 쓸지 적어야 하는데
(NumberOfAcceleratorDevicesRequired), 이 값이 GPU 인스턴스에서는 필수이고 최솟값이 1
입니다. 0.5를 넣으면 거부됩니다. 그래서 모델이 작아도 GPU 한 장을 통째로 씁니다.
(CPU 코어는 0.25 단위로 쪼갤 수 있는데 GPU만 이렇습니다.)
이 실험에서 모델 3개를 배포하려면 GPU 4장 인스턴스가 필요했고, GPU 1장 인스턴스 3대보다 비용이 높았습니다.
여러 모델이 GPU 한 장을 공유해야 한다면
04_gpu_cohost_lmi를 검토하세요.
컨테이너 하나가 모델 여러 개를 담고 GPU 메모리를 나눠 씁니다(모델 3개가 5.7GB).
Inference component는 모델별 자원 배정과 scaling 기능이 필요할 때 사용합니다. 아래 표에서 IC = inference component, LMI = DJL Serving 컨테이너입니다.
| IC | LMI | |
|---|---|---|
| 모델별 자원 배정 | ComputeResourceRequirements |
required_memory_mb |
| 모델별 사본 조절 | ✅ CopyCount |
워커 수로만 |
| 부하 인식 라우팅 | ✅ LEAST_OUTSTANDING_REQUESTS |
서버 내부 큐 |
| 컴포넌트마다 다른 이미지 | ✅ | ❌ 공유 컨테이너 |
| 단건 latency (실측 b=1) | 25.8 ms | 49.7 ms |
| concurrency 8 throughput | 61 req/s | 39 req/s |
비교한 co-host 구성에서 inference component는 batch=1 latency와 concurrency throughput이 LMI보다 높았습니다.
구조가 다릅니다¶
기존 방식은 endpoint_config의 variant에 ModelName을 넣습니다. inference component는
그 둘을 분리합니다. endpoint를 먼저 띄우고 컴포넌트를 붙이는 순서입니다.
import boto3
sm = boto3.client("sagemaker") # 리소스 관리
rt = boto3.client("sagemaker-runtime") # 추론 호출 (다른 클라이언트입니다)
# 1) variant에는 인스턴스만 선언: ModelName 없음
sm.create_endpoint_config(
EndpointConfigName=epc,
ExecutionRoleArn=role, # ← config 레벨에 필요 (기존 방식과 다른 점)
ProductionVariants=[{
"VariantName": "AllTraffic",
"InstanceType": "ml.g6.12xlarge",
"InitialInstanceCount": 1,
"RoutingConfig": {"RoutingStrategy": "LEAST_OUTSTANDING_REQUESTS"},
}],
)
# 2) endpoint를 만들고 InService까지 대기 (실측 180초)
sm.create_endpoint(EndpointName=ep, EndpointConfigName=epc)
# 3) InService endpoint에 모델을 component로 연결
# endpoint가 없으면 "Could not find endpoint" 오류 발생
sm.create_inference_component(
InferenceComponentName="mdeberta",
EndpointName=ep, VariantName="AllTraffic",
Specification={
"ModelName": "...",
"ComputeResourceRequirements": {
"NumberOfAcceleratorDevicesRequired": 1, # 필수, 최솟값 1
"MinMemoryRequiredInMb": 1024, # 낮게 잡아야 합니다
},
},
RuntimeConfig={"CopyCount": 1},
)
# 4) 호출: sagemaker-runtime 클라이언트로
rt.invoke_endpoint(
EndpointName=ep,
InferenceComponentName="mdeberta", # ← 대상 컴포넌트 지정
ContentType="application/json",
Body=body,
)
삭제는 역순입니다. 컴포넌트가 붙어 있으면 endpoint를 지울 수 없습니다.
실행¶
uv run python 03_gpu_cohost_inference_component/deploy.py --dry-run # endpoint 인스턴스 생성 전 확인
uv run python 03_gpu_cohost_inference_component/deploy.py --instance ml.g6.12xlarge
uv run python 03_gpu_cohost_inference_component/deploy.py --models mdeberta minilm --copies 2
# 컴포넌트별 호출
uv run python 03_gpu_cohost_inference_component/invoke.py --mode cloud --endpoint <ep> --all
uv run python -m benchmark.run --mode cloud --endpoint <ep> \
--inference-component <ic> --pad-to-max --sweep-batch
uv run python -m common.cleanup --delete-all # 실습 리소스 삭제
deploy.py는 모델 수가 GPU 장수를 넘으면 경고합니다.
실측 결과 (ml.g6.12xlarge, GPU 4장)¶
| 항목 | 결과 |
|---|---|
| 컴포넌트 3개 배포 | ✅ 3/3 InService (endpoint 180초 + 컴포넌트 213초) |
| 각각 독립 호출 | ✅ 검증 sample의 판정이 다른 배포 방식과 일치 |
CopyCount 1→2 |
✅ GPU 4장을 정확히 채움 (1+1+2) |
| 5번째 사본 | ❌ deployed 1 out of 2 requested copies |
| batch efficiency (512 고정) | b=8에서 2.0x |
놓치기 쉬운 것들¶
GPU capacity는 Region과 시점에 따라 달라집니다. 이 실험에서는 quota가 있는
ml.g5.12xlarge가 50분 뒤 Failed 상태가 되었고, ml.g6.12xlarge는 약 3분 만에
생성됐습니다.
MinMemoryRequiredInMb는 실제 배포로 확인합니다. 이 실험의 ml.g5.xlarge에서는
6144와 2048 설정이 실패했고 1024에서 배포됐습니다. component 요구량 외에 container와 model
server가 사용하는 memory도 고려해야 합니다.
일부 copy만 배포돼도 상태가 InService일 수 있습니다. 요청한 copy 수가 GPU 수를 넘으면
desired=2, current=1로 남을 수 있습니다. describe_inference_component의 현재 copy 수와
FailureReason을 함께 확인하세요.
막힌 경우 → docs/troubleshooting.md
다음으로 읽을 것¶
- GPU 1장에 여러 모델 →
04_gpu_cohost_lmi - 유휴 비용 제거 →
05_gpu_scale_to_zero(이 endpoint 위에 얹습니다)
실측 근거: docs/concepts/findings.md, docs/benchmark/results.md
개념 정리: docs/deep-dive/inference-component.md