- Published on
Triton 배포 후 지연 폭증 8가지 원인
- Authors
- Name
- 스타차일드
- https://x.com/ETFBITX
배포 직후에는 잘 보이지 않던 문제가 트래픽이 붙는 순간 p95, p99 지연을 폭발시키는 경우가 많습니다. Triton Inference Server는 고성능을 목표로 하지만, 모델 구성(config.pbtxt), 동시성, 배칭, 메모리, 네트워크, 오토스케일링 같은 여러 계층이 서로 영향을 주기 때문에 병목이 생기면 지연이 비선형적으로 커집니다.
이 글은 "배포 후 지연 폭증"이라는 증상을 기준으로, 현장에서 자주 만나는 8가지 원인을 우선순위 형태로 정리합니다. 각 항목마다 확인 방법과 바로 적용 가능한 조치(설정/운영)를 함께 제공합니다.
0. 먼저 확인할 관측 포인트(필수)
원인 분석 전에, 최소한 아래 지표를 함께 봐야 합니다.
- Triton 메트릭:
nv_inference_request_duration_us,nv_inference_queue_duration_us,nv_inference_compute_infer_duration_us,nv_inference_compute_input_duration_us,nv_inference_compute_output_duration_us - GPU:
SM utilization,GPU memory,PCIe Rx/Tx,Tensor Core사용률 - CPU:
run queue,context switch,softirq,irq비율 - 네트워크:
RTT,retransmit,conntrack테이블 사용률
Prometheus를 쓴다면 아래처럼 메트릭을 켜고(기본 8002) 대시보드를 먼저 만드세요.
docker run --rm --gpus all --net=host \
nvcr.io/nvidia/tritonserver:24.01-py3 \
tritonserver \
--model-repository=/models \
--metrics-port=8002 \
--allow-metrics=true
curl -s http://localhost:8002/metrics | head
지연이 "큐에서 늘어나는지"(queue_duration) 아니면 "연산 자체가 느려지는지"(compute_infer_duration)를 먼저 분리하면, 아래 8가지 원인 중 절반은 바로 걸러집니다.
1) 동적 배칭 설정이 트래픽 패턴과 불일치
증상
- 평균 지연은 괜찮은데
p95/p99만 급격히 증가 nv_inference_queue_duration_us가 같이 증가- QPS가 낮거나 들쭉날쭉할수록 더 심해짐
왜 발생하나
dynamic_batching은 처리량을 올리지만, 배치를 모으는 동안 요청이 큐에서 대기합니다. 특히 max_queue_delay_microseconds를 크게 잡으면, 트래픽이 얇을 때 지연이 그대로 꼬리로 쌓입니다.
조치
- 트래픽이 낮은 서비스는
max_queue_delay_microseconds를 매우 작게 시작 - 실시간성이 중요하면 배칭보다 동시성(
instance_group)을 먼저 튜닝
예시 config.pbtxt:
dynamic_batching {
preferred_batch_size: [ 1, 2, 4 ]
max_queue_delay_microseconds: 200
}
추가로, 클라이언트가 이미 배치를 만들어 보내고 있다면(예: batch=8), Triton의 동적 배칭이 이중으로 걸려 오히려 지연이 늘 수 있습니다. 이 경우 서버 배칭을 끄고 클라이언트 배칭만 유지하는 실험도 해보세요.
2) 인스턴스/동시성 부족 또는 과도한 인스턴스 생성
증상
queue_duration가 급증하며 GPU는 놀거나, 반대로 GPU는 100%인데 지연이 계속 증가- 스파이크 트래픽에서 큐가 한번 차면 회복이 느림
왜 발생하나
instance_group을 너무 적게 두면 동시 요청을 처리하지 못해 큐가 늘고, 너무 많이 두면 컨텍스트/메모리 경쟁으로 오히려 느려질 수 있습니다. 특히 큰 LLM/비전 모델은 인스턴스를 늘리는 순간 GPU 메모리 압박과 메모리 대역폭 경쟁이 발생합니다.
조치
- 먼저
instance_group을1로 두고 기준 지연을 측정한 뒤,2로 올려 비교 - GPU가 놀면 인스턴스 증가, GPU가 포화면 배칭/정밀도/커널 최적화 방향으로 전환
예시:
instance_group [
{
count: 2
kind: KIND_GPU
}
]
팁: 지연 폭증이 큐 때문인지 확인하려면, nv_inference_queue_duration_us가 전체 지연에서 차지하는 비율을 보세요. 큐 비중이 크면 동시성/배칭/오토스케일링 문제일 가능성이 높습니다.
3) 모델 워밍업 부재로 첫 요청이 폭발
증상
- 배포 직후 또는 스케일아웃 직후에만
p99가 수 초까지 튐 - 이후 안정화되지만, 오토스케일이 잦으면 계속 재발
왜 발생하나
TensorRT 엔진 로드, 커널 캐시, 메모리 할당, 그래프 최적화 등이 첫 요청에서 발생합니다. 또한 일부 백엔드는 첫 실행에서 알고리즘 탐색을 수행합니다.
조치
- 모델 로드 후 워밍업 트래픽을 강제로 주입
- Triton의 모델 워밍업 기능 또는 배포 파이프라인에서
smoke test호출
간단 워밍업 스크립트(HTTP 예시, 엔드포인트는 환경에 맞게 수정):
for i in $(seq 1 50); do
curl -s -X POST http://triton.example/v2/models/my_model/infer \
-H 'Content-Type: application/json' \
-d '{"inputs": [{"name":"input","shape":[1,3,224,224],"datatype":"FP32","data": [0]}]}' \
>/dev/null
done
오토스케일 환경에서는 "새 Pod가 Ready가 된 시점"과 "실제로 지연이 안정화되는 시점"이 다를 수 있으니, readiness probe에 워밍업 완료 조건을 반영하는 것도 고려하세요.
4) CPU 병목: 전처리/후처리, gRPC 스레드, Python backend
증상
- GPU 사용률은 낮은데 지연이 증가
- CPU 사용률이 높거나
run queue가 길어짐 compute_input_duration또는compute_output_duration비중이 큼
왜 발생하나
이미지 디코딩, 토크나이징, 후처리 NMS 같은 작업이 CPU에서 돌아가면 GPU는 기다리기만 합니다. 특히 Python backend는 GIL, 프로세스/스레드 모델, 메모리 복사 비용으로 지연 꼬리가 생기기 쉽습니다.
조치
- 전처리/후처리를 Triton 밖(별도 서비스)으로 빼거나, C++/CUDA로 이동
- 가능하면 TensorRT/ONNXRuntime 같은 네이티브 백엔드 사용
- 컨테이너
cpu request/limit을 타이트하게 잡아 스로틀링이 걸리지 않게 조정
Kubernetes에서 CPU 스로틀링 확인:
kubectl -n ml top pod
kubectl -n ml describe pod triton-xxx | sed -n '1,160p'
CPU가 원인인데 네트워크 증상처럼 보이는 경우도 많습니다. 예전에 "Pod는 뜨는데 트래픽이 0"처럼 보이는 상황을 네트워크로만 의심하다가, 실제로는 애플리케이션 스레드 고갈인 경우도 있으니 함께 점검하세요.
관련 진단 흐름은 이 글의 네트워크 체크리스트도 참고할 만합니다: EKS Pod는 뜨는데 트래픽 0 - NetPol·SG·CNI 10분 진단
5) 메모리 복사와 포맷 변환: CPU memcpy와 PCIe 병목
증상
- 입력/출력 크기가 큰 모델에서 지연이 급증
- GPU는 바쁜데 처리량이 기대보다 낮고,
PCIe Rx/Tx가 높음 compute_input_duration이 커짐
왜 발생하나
클라이언트 numpy 배열이 CPU 메모리에 있고, Triton이 이를 GPU로 복사하는 과정에서 병목이 생깁니다. NHWC와 NCHW 변환, FP32에서 FP16 변환이 런타임에 발생하면 더 악화됩니다.
조치
- 입력 텐서 포맷을 모델이 기대하는 형태로 맞춰 변환 비용 제거
- 가능한 경우 shared memory(시스템/쿠다) 사용으로 복사 비용 감소
- 큰 입력은 배치 크기와 동시성을 동시에 올리지 말고, 먼저 복사 비용을 줄인 뒤 확장
클라이언트에서 CUDA shared memory를 쓰는 경우(개념 예시):
# 개념 예시: 실제 코드는 tritonclient.utils/cuda_shared_memory API에 맞춰 작성
# 핵심은 host->device 복사를 줄이고, 큰 텐서를 공유 메모리로 전달하는 것
6) 모델 로딩/언로딩, 리포지토리 폴링으로 인한 런타임 흔들림
증상
- 일정 주기로 지연이 튐(예: 15초, 60초 간격)
- 배포/모델 업데이트 직후부터 지연이 불안정
왜 발생하나
Triton은 모델 리포지토리를 폴링하거나(옵션에 따라) 모델을 동적으로 로드/언로드합니다. 대형 모델을 로드하는 순간 GPU 메모리 재배치, 파일 I/O, 캐시 미스가 발생해 기존 요청까지 영향을 줄 수 있습니다.
조치
- 운영에서는 모델 리포지토리 폴링을 끄고, 명시적 로드 API로 제어
- 모델 업데이트는 블루/그린 또는 카나리로 분리
예시 옵션(환경에 맞게 조정):
tritonserver \
--model-repository=/models \
--model-control-mode=explicit \
--repository-poll-secs=0
7) Kubernetes 오토스케일/노드 자원 경합으로 인한 꼬리 지연
증상
- 특정 시간대에만 지연 폭증(다른 워크로드와 겹침)
- Pod 재스케줄링 이후 지연이 악화
- 노드에서
OOMKilled는 없는데도 성능이 출렁임
왜 발생하나
GPU 노드는 CPU, 메모리, 디스크 I/O도 함께 공유합니다. 같은 노드에 로깅/모니터링/사이드카가 과도하거나, 다른 워크로드가 CPU를 잡아먹으면 Triton의 입력 처리와 네트워크 스택이 느려집니다. 또한 HPA가 늦게 반응하면 큐가 한 번 쌓인 뒤 회복이 지연됩니다.
조치
- GPU 노드에
taint/toleration과nodeSelector로 워크로드 격리 - Pod
requests를 실제 사용량에 맞게 상향(특히 CPU) - HPA 기준을 GPU 메트릭 또는 Triton 큐 길이에 가깝게 설계
오토스케일이 늦어져 트래픽이 막히는 현상은 네트워크처럼 보일 수 있으니, DNS나 CNI 이슈도 함께 배제하는 것이 좋습니다. 필요하면 이 글의 진단 루틴도 참고하세요: EKS CoreDNS DNS timeout·SERVFAIL 10분 진단
8) 클라이언트 재시도 폭풍과 타임아웃 설정 미스
증상
- 지연이 늘어난 뒤 QPS가 오히려 더 증가하며 서버가 붕괴
p99가 커지고 에러율도 동반 상승- 로그에
deadline exceeded류 메시지가 증가
왜 발생하나
클라이언트가 짧은 타임아웃을 두고 공격적으로 재시도하면, 서버는 이미 느려진 상태에서 더 많은 요청을 받아 "재시도 증폭"이 발생합니다. 특히 gRPC의 기본 재시도 정책을 그대로 쓰거나, 애플리케이션 레벨에서 무제한 재시도를 구현하면 지연 폭증이 눈덩이처럼 커집니다.
조치
- 재시도는 지수 백오프와 지터를 적용하고, 최대 재시도 횟수 제한
- 타임아웃은
p99기준으로 잡되, 서버 큐가 늘어나는 상황을 고려해 단계적으로 조정 - 가능하면 idempotency를 보장하고, 서버 과부하 시 빠르게 실패하도록 회로 차단기 도입
재시도/백오프 패턴은 이 글이 실전에 바로 도움이 됩니다: OpenAI API 429 재시도·백오프 패턴 실전 가이드
간단한 지수 백오프 예시(파이썬):
import random
import time
def call_with_backoff(call, max_retries=5, base=0.1, cap=2.0):
for i in range(max_retries + 1):
try:
return call()
except Exception:
if i == max_retries:
raise
sleep = min(cap, base * (2 ** i))
sleep = sleep * (0.5 + random.random()) # jitter
time.sleep(sleep)
마무리: 지연 폭증을 "큐"와 "연산"으로 분해하라
Triton 배포 후 지연이 폭증하면, 감으로 GPU가 느려졌다고 단정하기 쉽습니다. 하지만 실제 현장에서는 다음 순서로 정리하면 빠르게 좁혀집니다.
- Triton 메트릭에서
queue대compute비중 분리 dynamic_batching과instance_group의 조합을 가장 먼저 의심- 워밍업/오토스케일 구간의 첫 요청 지연을 별도로 측정
- CPU 전처리/후처리와 메모리 복사 비용을 계측
- 재시도 정책이 지연을 증폭시키지 않는지 확인
위 8가지를 체크해도 원인이 모호하다면, 같은 입력으로 단일 요청 벤치(batch=1, 동시성 1)의 기준선을 만든 뒤, 배칭과 동시성을 하나씩 올리며 어느 지점에서 p99가 꺾이는지 찾는 방식이 가장 재현성이 좋습니다.