AEGLOSLAB 엔비디아 기술 스택

제5부 추론 최적화와 서빙

5.12 Triton II — config·동시성·인스턴스

5.12.1 이 장에서 배우는 것 / 선수 지식

5.11에서 Triton의 모델 리포지토리·config.pbtxt·백엔드로 모델을 서빙하는 구조를 잡았다. 그런데 기본 설정 그대로 기동하면 GPU가 약 절반 유휴 상태다 — 한 인스턴스가 요청 하나를 처리하는 동안 H2D/D2H 복사·런치 간극·메모리 바운드 구간에서 연산 유닛이 비기 때문이다(5.1·2.10). 이 장은 그 빈자리를 동시성(concurrency) 으로 메워 활용률·처리량을 끌어올리는 튜닝을 판다 — 핵심 손잡이는 instance_group(한 GPU에 모델 인스턴스를 여러 개)이다.

가장 중요한 개념은 인스턴스와 배칭이 직교(orthogonal)하는 두 동시성 레버라는 것이다. 배칭(5.13)은 "한 번의 실행을 더 크게", 인스턴스는 "여러 실행을 동시에" — 둘을 곱해 운영점을 찾는다. 그리고 그 운영점은 머리로 정하는 것이 아니라 perf_analyzer·Model Analyzer로 측정해 찾는다.

배우는 것:

  • 왜 동시성인가 — 단일 인스턴스가 GPU를 못 채우는 이유(복사·간극·메모리 바운드)와, 다중 인스턴스가 그것을 메우는 원리.
  • instance_group — 인스턴스 수·배치(GPU/CPU)·다중 GPU 배치, 각 인스턴스의 독립 실행 컨텍스트.
  • 인스턴스 vs 배칭 — 직교하는 두 레버, 곱(인스턴스 × 배치)으로 운영점 탐색.
  • GPU 공유와의 관계 — 기본 타임슬라이싱·MPS(공간 공유)·MIG(하드 분할)에서 인스턴스가 어떻게 동작하나(7.5).
  • 튜닝 방법론 — perf_analyzer 동시성 스윕, Model Analyzer로 config 자동 탐색, 처리량 포화·지연 곡선 읽기.
  • 인스턴스 수를 바꿔 측정하며 최적점을 찾는 실습.

선수 지식: 5.11(config.pbtxt·instance_group·perf_analyzer — 이 장의 토대), 5.1(처리량/지연·배치=마스터 노브·goodput), 2.10(스트림·오버랩), 7.5/4.10(MPS·MIG 공유 — 본격은 거기), 2.13(Nsight로 활용률). 배칭 자체는 5.13. 환경은 5.11.

정직: Model Analyzer·instance 관련 일부 필드·기본값은 버전 의존이다(도구 명칭·옵션 변화). 핵심 개념(instance_group·동시성·배칭 직교)은 안정적이나 정확한 옵션은 그 버전 문서로 확인. 모든 처리량·지연·활용률 수치는 환경 의존 개략값 — 반드시 실측.

5.12.2 왜 동시성 — 단일 인스턴스는 GPU를 못 채운다

한 모델 인스턴스가 요청 하나를 처리하는 동안 GPU에는 빈 시간이 많다:

단일 인스턴스, 요청을 순차 처리 요청1 H2D 커널들·간극 D2H 요청2 H2D 커널… D2H 시간

요청1이 끝난 뒤에야 요청2가 시작되며, 복사·간극 동안 GPU 연산 유닛이 유휴 상태다 → 활용률 낮음(2.10·5.1).

빈 시간의 출처:

  • H2D/D2H 복사: 입력·출력 전송 중 연산 유닛 유휴(스트림으로 오버랩 안 하면, 2.5·2.10).
  • 런치 간극·작은 커널: 커널 사이 호스트 오버헤드(2.11).
  • 메모리 바운드 구간: 가중치·활성화 읽는 동안 연산 유닛 여유(5.1.4).

다중 인스턴스는 이 빈자리를 다른 요청의 일로 메운다:

인스턴스 2개, 요청을 동시 처리 인스턴스A H2D 커널… D2H 인스턴스B H2D 커널… D2H 시간

A가 복사할 때 B는 연산하여 실행이 겹친다 → GPU가 빽빽이 채워짐 → 활용률·처리량↑.

각 인스턴스는 독립된 실행 컨텍스트·CUDA 스트림을 가져, Triton 스케줄러가 들어온 요청을 인스턴스들에 분배한다. 인스턴스들이 GPU에서 동시에 실행되며 서로의 빈 시간을 메운다.

핵심: 인스턴스를 늘리면 지연은 거의 그대로 두고 처리량을 높인다(빈 시간을 메우는 동안엔). 단, GPU가 이미 꽉 차면(컴퓨트 포화) 더 늘려도 처리량은 안 오르고 경합·메모리만 증가 — 그래서 측정으로 포화점을 찾는다.

5.12.3 instance_group — 인스턴스 배치

config.pbtxt의 instance_group이 인스턴스 수·위치를 정한다(5.11 복습+심화):

instance_group [
  { count: 4, kind: KIND_GPU, gpus: [ 0 ] }      # GPU0에 인스턴스 4개
]
# 다중 GPU에 분산:
instance_group [
  { count: 2, kind: KIND_GPU, gpus: [ 0 ] },     # GPU0에 2개
  { count: 2, kind: KIND_GPU, gpus: [ 1 ] }      # GPU1에 2개
]
# CPU 인스턴스(전처리·경량 모델):
instance_group [ { count: 2, kind: KIND_CPU } ]

함의:

  • count = 동시 실행 가능한 그 모델 복사본 수. 4면 최대 4개 요청(또는 4개 배치)을 동시에.
  • 각 인스턴스가 자원을 따로 쓴다: 가중치는 공유될 수도 있으나 활성화 버퍼·실행 컨텍스트·(엔진에 따라) 작업 메모리는 인스턴스마다 → 인스턴스↑ = 메모리↑. KV 캐시가 큰 LLM은 인스턴스를 늘리기 어렵다(5.7).
  • 다중 GPU: GPU마다 인스턴스를 둬 모델을 복제(5.9의 "복제로 수평 확장"). 데이터 병렬 추론.
  • CPU 인스턴스: 경량 전처리·후처리·트리 모델 등.
0 10 20 30 1 6 2 19 3 31 4 38 instance count
처리량
0 5 10 15 1 6 2 6 3 13 4 19 instance count
지연
0 10 20 30 40 1 6 2 19 3 31 4 44 instance count
메모리

처리량은 포화 전까진 증가하다 GPU가 차면 평탄해지고, 지연은 포화 전 거의 일정하다 경합이 시작되면 증가하며, 메모리는 인스턴스마다 버퍼가 들어 선형 증가한다. → '처리량이 포화되기 직전 + 지연이 SLA 안 + 메모리 OK'가 최적 instance 수.

5.12.4 인스턴스 vs 배칭 — 직교하는 두 레버

가장 흔한 혼동을 정리한다. 동시성을 높이는 두 독립적 방법:

배칭(5.13): 여러 요청을 '한 번의 실행'으로 묶음 한 커널이 더 큰 텐서를 처리 (메모리 바운드 완화, 5.1.4) GEMM 효율↑, 단 큐 대기· 지연↑ 인스턴스: '여러 실행'을 동시에 굴림 서로의 빈 시간(복사·간극)을 메움 (5.12.2) 오버랩↑, 단 인스턴스마다 메모리 둘은 직교 → 함께 쓴다 유효 동시성 ≈ 인스턴스 수 × 배치 크기
배칭인스턴스
무엇한 실행을 크게여러 실행 동시
주 효과GEMM 효율·메모리 바운드 완화복사·간극 오버랩
메모리활성화·KV가 배치에 비례인스턴스마다 버퍼
지연큐 대기로 증가 가능거의 유지(포화 전)
튜닝max_batch·동적 배칭(5.13)instance_group count

견해: 둘을 함께 스윕해 최적점을 찾는다. 작은 모델·짧은 커널은 인스턴스가, 큰 GEMM·메모리 바운드는 배칭이 더 효과적인 경향. LLM은 인플라이트 배칭(5.8)이 배치를 맡고 인스턴스는 메모리 제약(KV) 때문에 보통 적게. 비전·임베딩 같은 단발 모델은 인스턴스 × 동적 배칭 둘 다 적극 활용.

5.12.5 GPU 공유와 인스턴스 — 타임슬라이싱·MPS·MIG

여러 인스턴스가 한 GPU에서 "동시에" 실행된다는 것이 실제로 어떻게 되나? GPU 공유 방식에 따라 다르다(본격은 7.5):

GPU 공유 방식 ① 기본 (타임슬라이싱) GPU가 컨텍스트를 시간 분할. 인스턴스들이 번갈아 실행 오버랩은 스트림 수준에서 일부 일어나나, 실제 '공간 동시'는 제한적 ② MPS (Multi-Process Service) 여러 프로세스의 커널을 '공간적으로' 함께 실행 인스턴스들이 GPU SM을 나눠 실제 동시 실행 → 활용률↑(특히 작은 커널) ③ MIG (Multi-Instance GPU) GPU를 하드웨어로 분할 (SM·메모리· 대역 격리) 각 MIG 슬라이스에 인스턴스를 둬 '격리된' 동시성 (멀티테넌시, 4.10)
공유동시성 성격인스턴스와의 관계
타임슬라이싱(기본)시간 분할인스턴스 늘려도 공간 동시성 제한
MPS공간 공유(비격리)인스턴스 동시 실행 효율↑, 격리 없음
MIG하드 분할(격리)슬라이스별 인스턴스, 성능 예측·격리

핵심: 인스턴스를 늘려도 기본 타임슬라이싱에선 한계가 있다. 작은 커널·다중 모델로 활용률을 더 극대화하려면 MPS, 멀티테넌시·격리·성능 예측이 필요하면 MIG(7.5). Triton은 셋 모두와 함께 동작한다 — 인스턴스 수와 공유 방식을 같이 정한다.

5.12.6 워크스루 (1) — 인스턴스 스윕 측정

5.11의 모델로 인스턴스 수를 바꿔가며 처리량·지연을 측정해 최적점을 찾는다.

# config.pbtxt의 instance_group count를 1,2,4로 바꿔가며(또는 별도 config) 서버 재시작 후 측정
# perf_analyzer로 동시성 스윕(5.11) — 부하를 올리며 처리량·p99 관찰
perf_analyzer -m densenet_trt -b 8 --concurrency-range 1:16:1 -u localhost:8000

# 비교 표(개략 예시 — 실측값으로 대체):
#   instance=1: 처리량 ▁, p99 낮음     → GPU 절반 유휴
#   instance=2: 처리량 ▃, p99 비슷     → 빈자리 메움(좋은 가성비)
#   instance=4: 처리량 ▅, p99 약간↑    → 포화 근처
#   instance=8: 처리량 ▅(평탄), p99↑↑  → 포화·경합·메모리 낭비 → 과투자

읽는 법(5.1 지표):

  • 처리량이 더 안 오르는 지점 = GPU 포화. 그 이전이 인스턴스 증설의 가치 구간.
  • p99가 SLA를 깨기 시작하는 지점 = 상한. 그 안에서 처리량 최대인 인스턴스 수.
  • 메모리 = 인스턴스마다 버퍼. OOM 직전까지만.
  • 운영점 = 세 제약(포화·SLA·메모리)의 교집합에서 처리량 최대.
Nsight Systems(2.13)로 교차 확인 instance=1 → 타임라인에 빈 구간(복사·간극), GPU util 낮음 instance=N → 그 구간이 다른 요청으로 채워짐, util↑ (포화하면 더 안 채워짐)

5.12.7 워크스루 (2) — Model Analyzer로 자동 탐색

인스턴스 × 배치 × (정밀도 등) 조합을 수동으로 모두 스윕하긴 힘들다. Triton Model Analyzer는 config 조합을 자동으로 탐색해 처리량·지연·메모리의 파레토 최적을 찾아준다(도구·옵션 버전 의존).

# 개념: Model Analyzer가 instance_group·dynamic_batching 조합을 자동 스윕하며 측정
#   (정확한 CLI·설정은 버전 문서 확인)
model-analyzer profile \
  --model-repository /models \
  --profile-models densenet_trt \
  --run-config-search-mode quick        # instance·batch 조합 자동 탐색

# 산출: 조합별 처리량·p99 지연·GPU 메모리의 표/그래프 + 추천 config
#   예: "instance=3, max_batch=16, dynamic_batching delay=100us"가
#       'p99<X ms 제약 하 처리량 최대' → 그 config.pbtxt를 채택

견해: 운영 전에 Model Analyzer로 한 번 탐색해 두면, 추측으로 instance·batch를 고르다 과투자·저활용하는 것을 피한다. SLA(지연 제약)를 주면 그 제약 하 처리량 최대 config을 찾아준다 — 5.1의 "SLA → 운영점" 사고를 자동화. 단 실제 트래픽 분포로 부하를 줘야 의미 있다(합성 부하의 한계 인지).

5.12.8 중간 점검 (체크포인트)

  • [ ] 단일 인스턴스가 GPU를 못 채우는 이유(복사·간극·메모리 바운드)와, 다중 인스턴스가 빈 시간을 메우는 원리를 설명한다.
  • [ ] instance_group으로 인스턴스 수·GPU 배치를 정하고, 인스턴스↑가 처리량·지연·메모리에 미치는 영향을 안다.
  • [ ] 인스턴스와 배칭이 직교함을, 유효 동시성 ≈ 인스턴스 × 배치로 설명한다.
  • [ ] 타임슬라이싱·MPS·MIG에서 인스턴스 동시성이 어떻게 다른지(공간 공유·격리) 안다.
  • [ ] perf_analyzer 동시성 스윕으로 포화점·SLA·메모리의 교집합에서 운영점을 찾는다.
  • [ ] Model Analyzer로 instance × batch 조합을 자동 탐색해 추천 config을 얻는다.

증상→의심: 인스턴스 늘려도 처리량 안 오름 → GPU 이미 포화(컴퓨트 바운드) 또는 타임슬라이싱 한계 → MPS/MIG 검토·배칭으로 전환. 인스턴스 늘리니 OOM → 인스턴스마다 버퍼·KV → count↓·MIG로 메모리 격리. GPU util 낮은데 처리량 낮음 → 인스턴스 1·배칭 off → 둘 다 켜기(5.13). p99가 튐 → 인스턴스 과다 경합 또는 배치 과대 → 스윕으로 균형. LLM 인스턴스 못 늘림 → KV 메모리(5.7) → 인스턴스 대신 인플라이트 배칭(5.8).

5.12.9 트레이드오프·대안

활용률을 어떻게 끌어올리나.

레버누구에게비고
인스턴스↑복사·간극·메모리 바운드로 빈 GPU메모리↑, 포화 전까지 처리량↑·지연 유지
배칭(5.13)큰 GEMM·메모리 바운드GEMM 효율↑, 지연↑(큐)
인스턴스 × 배칭대부분곱으로 운영점, Model Analyzer로 탐색
MPS(7.5)작은 커널·다중 모델 공간 공유격리 없음, 활용률↑
MIG(4.10·7.5)멀티테넌시·격리·예측하드 분할, 슬라이스별 인스턴스
다중 GPU 복제수평 처리량GPU당 인스턴스, 데이터 병렬

견해: 인스턴스와 배칭을 함께 스윕해 SLA 하 처리량 최대점을 찾는 것이 정석이고, Model Analyzer로 자동화하라. 활용률을 더 극대화해야 하면 MPS(작은 커널·다중 모델), 격리·멀티테넌시가 필요하면 MIG. LLM은 인스턴스보다 인플라이트 배칭이 주력(KV 메모리 제약). "무조건 인스턴스 많이"는 메모리·경합으로 역효과 — 측정이 답.

비엔비디아 정직: 동시성·배칭·자원 공유는 모든 서빙 시스템의 공통 과제다(KServe·Ray Serve 등도 복제·배칭). Triton의 강점은 instance_group·동적 배칭·MPS/MIG·Model Analyzer의 통합으로 측정 기반 튜닝이 쉽다는 것. 최적 config은 모델·GPU·트래픽마다 다르니 실측.

5.12.10 흔한 함정

  • 인스턴스를 맹목적으로 늘림. GPU가 포화하면 처리량은 안 오르고 메모리·경합만↑. 포화점까지만, 측정으로.
  • 인스턴스와 배칭 혼동. 둘은 직교 레버다. "인스턴스를 늘렸으니 배칭은 불필요"는 오해 — 함께 곱으로.
  • 메모리 예산 무시. 인스턴스마다 활성화·작업 버퍼(LLM은 KV). 늘리다 OOM. 메모리를 계산하고 늘려라.
  • 타임슬라이싱 한계를 모름. 기본 공유는 공간 동시성이 제한적 → 인스턴스 효과가 기대보다 작을 수 있다. MPS/MIG 검토.
  • 합성 부하만으로 튜닝. perf_analyzer 기본 부하는 균일·고정일 수 있다. 실제 트래픽 분포(시퀀스·배치 분포)로 측정해야 운영에서 맞다.
  • SLA 없이 처리량만. 처리량 최대가 p99를 깨면 goodput은 떨어진다(5.1). 지연 제약 하 처리량으로.
  • LLM에 인스턴스 다수. KV 메모리 때문에 인스턴스를 늘리기 어렵고, 인플라이트 배칭이 동시성을 담당(5.8). 일반 모델과 다르게 접근.
  • config 변경 후 미검증. instance·batch를 바꾸면 처리량·지연·메모리가 변한다 — 변경마다 perf_analyzer로 재측정.

5.12.11 연습문제

연습 1 (왜 인스턴스). 단일 인스턴스로 서빙하니 GPU 활용률이 40%인데 처리량이 낮다. (a) GPU 유휴 시간의 출처 셋, (b) 다중 인스턴스가 이를 어떻게 개선하나, (c) 인스턴스를 계속 늘리면 언제 멈춰야 하나?

정답

(a) ① H2D/D2H 복사 중 연산 유닛 유휴(2.5·2.10), ② 커널 사이 런치 간극·작은 커널(2.11), ③ 메모리 바운드 구간에서 연산 여유(5.1.4). (b) 다중 인스턴스는 각자 독립 스트림·컨텍스트로 동시 실행해, 한 인스턴스가 복사·간극일 때 다른 인스턴스가 연산 → 빈 시간을 메워 활용률·처리량↑. (c) 처리량이 더 안 오르는 포화점(GPU 컴퓨트가 참)에 도달하거나, p99가 SLA를 깨거나, 메모리(버퍼)가 한계에 닿으면 멈춘다. 그 셋의 교집합에서 처리량 최대인 인스턴스 수가 최적 — 측정으로.

연습 2 (직교 레버). "인스턴스 4개를 띄웠으니 배칭은 안 해도 된다"는 주장을 반박하고, 인스턴스와 배칭을 함께 쓰는 것이 왜 나은지 메커니즘으로 설명하라.

정답

반박: 인스턴스와 배칭은 다른 빈자리를 메운다. 인스턴스는 복사·런치 간극을 오버랩으로 메우지만, 각 인스턴스의 실행이 메모리 바운드(작은 배치) 면 그 안의 GEMM은 여전히 비효율이다(5.1.4). 배칭은 한 실행의 텐서를 키워 GEMM 효율·메모리 바운드를 완화한다 — 인스턴스로는 못 푸는 부분. 함께 쓰면 유효 동시성 ≈ 인스턴스 × 배치로, 인스턴스가 오버랩을, 배칭이 각 실행의 산술 강도를 높여 둘 다 개선. 그래서 instance × batch를 함께 스윕(Model Analyzer)해 최적점을 찾는 것이 정석. 단 LLM은 배치를 인플라이트 배칭(5.8)이 맡고 인스턴스는 KV 때문에 제한.

연습 3 (공유 방식). 인스턴스를 1→4로 늘렸는데 처리량이 거의 안 올랐다. 작은 커널이 많은 모델이다. (a) 기본 타임슬라이싱의 한계, (b) MPS가 어떻게 돕나, (c) 멀티테넌시·격리가 필요하면?

정답

(a) 기본 타임슬라이싱은 GPU 컨텍스트를 시간 분할해, 인스턴스들이 실제 공간 동시로 SM을 나눠 쓰지 못하는 경우가 많다 → 작은 커널이 SM을 다 못 채워도 다른 인스턴스 커널이 함께 실행되지 못해 활용률이 안 오름. (b) MPS는 여러 프로세스의 커널을 공간적으로 함께 실행(SM을 나눠) → 작은 커널들이 동시에 실행되어 활용률·처리량↑. 격리는 없음(한 인스턴스 오류가 영향 가능). (c) MIG(4.10·7.5) — GPU를 하드웨어로 분할해 SM·메모리·대역을 격리, 각 슬라이스에 인스턴스를 둬 격리된 멀티테넌시·성능 예측. 테넌트 간 간섭 방지가 필요할 때.

연습 4 (운영점 찾기). perf_analyzer 동시성 스윕에서 instance=2,4,8의 (처리량, p99)가 (1000, 20ms), (1800, 28ms), (1900, 55ms)였다. SLA가 p99<30ms일 때 어느 config인가? instance=8이 처리량은 가장 높은데 왜 안 고르나?

정답

SLA p99<30ms를 만족하는 것은 instance=2(20ms)와 instance=4(28ms). 그중 처리량이 더 높은 instance=4(1800, 28ms) 가 최적 — SLA 안에서 처리량 최대. instance=8은 처리량 1900으로 가장 높지만 p99=55ms로 SLA(30ms)를 위반 → 그 처리량은 goodput이 아니다(SLA 깬 요청은 실패, 5.1). 게다가 2→4에서 +800인데 4→8은 +100뿐(포화 근처)이라 지연을 두 배로 내주고 얻는 것이 거의 없다. SLA 제약 하 처리량 최대가 운영 목표.

연습 5 (LLM vs 일반 모델). 비전 분류 모델과 LLM을 같은 GPU에서 Triton으로 서빙한다. 동시성을 높이는 접근이 둘이 어떻게 달라야 하는지 설명하라.

정답

비전 분류(단발 forward): instance_group으로 인스턴스를 여러 개 + 동적 배칭(5.13)을 함께 적극 활용. 활성화 버퍼가 작아 인스턴스를 늘리기 쉽고, 인스턴스×배치로 활용률·처리량을 끌어올림. MPS로 작은 커널 공간 공유도 효과적. LLM(자기회귀): 인스턴스를 늘리면 인스턴스마다 KV 캐시(5.7)가 들어 메모리가 폭발 → 인스턴스는 보통 1~소수. 대신 동시성은 인플라이트(연속) 배칭(5.8)이 한 인스턴스 안에서 많은 요청을 스텝 단위로 처리해 담당. 즉 비전은 인스턴스×배칭, LLM은 인플라이트 배칭이 주력. 한 GPU 공유 시 MIG/MPS로 둘을 격리·배분 고려(7.5).

5.12.12 요약 · 다음 장

  • 단일 인스턴스는 복사·런치 간극·메모리 바운드로 GPU를 못 채운다. instance_group으로 인스턴스를 늘려 빈 시간을 다른 요청으로 메워 활용률·처리량을 높인다 — 포화점·SLA·메모리의 교집합까지만.
  • 인스턴스와 배칭은 직교한다: 배칭은 한 실행을 크게(GEMM 효율), 인스턴스는 여러 실행 동시(오버랩). 유효 동시성 ≈ 인스턴스 × 배치 — 함께 스윕한다.
  • 인스턴스 동시성은 GPU 공유 방식에 좌우된다: 기본 타임슬라이싱(제한적)·MPS(공간 공유)·MIG(하드 분할·격리, 7.5).
  • 튜닝은 추측이 아니라 측정: perf_analyzer 동시성 스윕 + Model Analyzer 자동 탐색으로 SLA 하 처리량 최대 config을 찾는다.
  • LLM은 인스턴스보다 인플라이트 배칭(5.8)이 동시성 주력(KV 메모리 제약). 비전·임베딩은 인스턴스×배칭.
  • 정직: 도구·옵션 일부 버전 의존, 모든 수치 실측, 합성 부하의 한계 인지.

다음 장: 5.13 Triton III — 동적·시퀀스 배칭. 이 장의 인스턴스에 더해, 서버가 요청을 모아 배치로 묶는 동적 배칭(처리량)과, 상태 있는 모델(시퀀스·스트리밍)을 위한 시퀀스 배칭을 판다 — 큐 지연·선호 배치 크기·max delay의 트레이드오프를 perf_analyzer로 측정하며 본다.