04. LMI co-host: GPU 한 장에 모델 여러 개¶
GPU 비용을 아끼면서 인코더 여러 개를 co-host 할 수 있을까요?
LMI(DJL Serving)를 사용할 수 있습니다. 이 실험에서는 GPU 한 장에 모델 3개를 배포했습니다.
어떻게 GPU 1장에 여러 모델이 올라가나요?
container 하나가 Java router와 모델별 Python process로 실행되고, process들이 같은 GPU를 공유합니다. SageMaker에서는 container 하나로 보이므로 inference component의 GPU 장 단위 할당 제약이 걸리지 않습니다.
로컬 L40S에서 모델 3개가 GPU memory 5.7GB를 사용했고 각각 정상 응답했습니다. 자세한 구조는 LMI 내부 구조에 있습니다.
과금
ml.g5.xlarge는 시간당 과금됩니다. 로컬 검증
(bash 04_gpu_cohost_lmi/scripts/serve_local_lmi.sh)을 먼저 하세요.
03(inference component)은 component copy마다 GPU를 최소 한 장 할당합니다. LMI는 container
내부에서 여러 모델이 GPU 한 장을 공유하지만, 모델별 독립 scaling과 routing 기능은 제공하지
않습니다.
| 03 inference component | 04 LMI | |
|---|---|---|
| GPU 1장에 모델 3개 | ❌ | ✅ |
| 필요 인스턴스 | ml.g6.12xlarge (GPU 4장) | ml.g5.xlarge (GPU 1장) |
| 시간당 요금 | $5.752 | $1.408 |
| GPU 메모리 (모델 3개) | 장당 1개씩 점유 | 5.7GB / 46GB |
| 모델 추가 | 컴포넌트 생성 | S3 업로드만 |
| 대상 지정 | InferenceComponentName |
TargetModel |
요금은 us-east-1 on-demand hosting 기준이며 2026-08-07에 AWS Pricing API로 조회했습니다.
실측 결과 (max_len=512 고정)¶
| p50 | p90 | p95 | p99 | b=8 throughput | batch efficiency | 100만 건 비용 | |
|---|---|---|---|---|---|---|---|
| 02 CPU+ONNX | 58.3 ms | 63.0 ms | 63.5 ms | 64.2 ms | 27/s | 1.6x | $4.20 |
| 03 inference component | 25.8 ms | 27.4 ms | 28.3 ms | 28.4 ms | 78/s | 2.0x | $20.48 |
| 04 GPU LMI | 49.7 ms | 50.9 ms | 51.5 ms | 52.8 ms | 104/s | 5.2x | $3.76 |
요금은 us-east-1 on-demand hosting 기준이며 2026-08-07에 AWS Pricing API로 조회했습니다.
100만 건 비용은 인스턴스가 그 시간 동안 계속 떠 있다고 가정한 값입니다.
batch=1 latency는 inference component가 낮았고, 처리량 기준 비용은 LMI가 낮았습니다. 전체
수치는 docs/benchmark/results.md에 있습니다.
concurrency 8에서는 inference component가 61 req/s로 LMI(39)보다 앞섭니다(GPU 4장의 여유).
LMI에서 concurrency를 올리려면 gpu.maxWorkers를 늘리세요(GPU 메모리 여유가 있습니다).
실행¶
# 로컬 검증 (과금 없음): GPU 1장에 3개가 올라가는지 먼저 확인
bash 04_gpu_cohost_lmi/scripts/serve_local_lmi.sh
# 클라우드
uv run python 04_gpu_cohost_lmi/deploy.py --dry-run # S3 업로드, endpoint 인스턴스 생성 안 함
uv run python 04_gpu_cohost_lmi/deploy.py # 모델 3개
uv run python 04_gpu_cohost_lmi/deploy.py --models mdeberta minilm
uv run python 04_gpu_cohost_lmi/invoke.py --endpoint <ep> --mode cloud --all
uv run python -m benchmark.run --mode cloud --endpoint <ep> \
--target-model mdeberta.tar.gz --pad-to-max --sweep-batch
uv run python -m common.cleanup --delete-all # 실습 리소스 삭제
어떻게 동작하나요¶
SageMaker MME 규약을 씁니다(multi-models=true 라벨 확인). S3의 한 prefix 아래에
모델별 model.tar.gz를 두고 TargetModel로 호출합니다.
s3://bucket/encoder-serving/lmi/04-lmi/
├── mdeberta.tar.gz serving.properties만 들어 있음
├── minilm.tar.gz
└── xlmr-large.tar.gz
각 tarball에는 serving.properties만 있고 model weight는 없습니다. option.model_id를
지정하면 container가 Hugging Face Hub에서 model을 내려받습니다. 실습에서는 큰 model
Artifact를 S3에 올리는 과정을 줄일 수 있습니다. 운영 환경에서는 시작 시간과 재현성을 위해
weight를 S3에 저장하는 방식을 검토하세요.
engine=Python
option.model_id=MoritzLaurer/mDeBERTa-v3-base-xnli-multilingual-nli-2mil7
option.task=text-classification
option.rolling_batch=disable
gpu.minWorkers=1
gpu.maxWorkers=1
required_memory_mb=2048
LMI가 인코더를 인식합니다¶
LmiConfigRecommender: The model task architecture [DebertaV2ForSequenceClassification]
is not supported for optimized inference. LMI will attempt to load the model using
HuggingFace Accelerate. Optimized inference is only available for the following
task architectures: [ForConditionalGeneration, LMHeadModel, ForCausalLM]
Detected rolling_batch: disable, for modelType: deberta-v2
rolling_batch: disable을 자동 선택합니다. 인코더에는 continuous batching이 의미가
없으므로 적절한 선택입니다. serving.properties에 명시하면 판단 단계를 건너뛰어 시작이 빠릅니다.
vLLM은 지원하지 않는 architecture를 거부하지만 LMI는 Hugging Face Accelerate 경로로
fallback합니다. 이 경로로 DeBERTa를 서빙할 수 있습니다
(repository의 08_engine_comparison/ 참고).
놓치기 쉬운 것들¶
Mode: "MultiModel"과 prefix. ModelDataUrl에 파일이 아니라 prefix를 줍니다.
파일로 주면 단일 모델 endpoint가 됩니다.
TargetModel은 tar.gz 이름입니다 (mdeberta.tar.gz). 모델 키가 아닙니다.
첫 호출에는 model load 시간이 포함됩니다. LMI가 요청 시점에 모델을 로드하므로 benchmark
전에 충분한 --warmup을 적용하세요.
막힌 경우 → docs/troubleshooting.md
다음으로 읽을 것¶
유휴 시간 비용을 없애려면 → 05_gpu_scale_to_zero
(이 endpoint에 MinInstanceCount: 0을 붙입니다)
전체 실측 결과: docs/concepts/findings.md, docs/benchmark/results.md