Stanford CS25: 트랜스포머 서빙 - 현장의 교훈
요약
대규모로 트랜스포머 모델을 서빙하려면 모델 능력에 집중하는 것에서 생산 추론의 “지루한 인프라”를 최적화하는 근본적인 전환이 필요합니다. 핵심 과제는 프리필(입력 처리) 단계와 디코드(토큰 생성) 단계 사이의 격차에 있으며, 디코드 단계는 일반적으로 메모리 대역폭에 제한을 받아 하드웨어 활용도가 낮아집니다. 생산 추론에서 성공하려면 서비스 수준 목표(SLO)를 통해 정확한 워크로드를 정의하고, 효율성 대 능력 한계에 따라 모델을 선택하며, 추측 디코딩 및 양자화와 같은 공격적인 최적화 기법을 적용해야 합니다.
추론 워크로드 및 SLO 정의
효과적인 추론 엔지니어링은 워크로드를 명확히 정의하는 것에서 시작되며, 이는 하드웨어와 소프트웨어 아키텍처를 결정합니다. 워크로드는 일반적으로 세 가지 전형으로 구분됩니다:
- Chatbot Plus: 인간과 상호작용하는 시스템(예: ChatGPT, Claude)으로, 주요 지표는 사용자당 초당 출력 토큰 수와 같은 인터랙티비티입니다.
- Background Agents: 초·분 단위로 복잡한 작업을 수행하는 시스템(예: 코딩 에이전트)으로, 주요 지표는 마지막 토큰까지 걸리는 시간입니다.
- Data Processors: 대용량·버스트형 워크로드(예: 문서 인덱싱)로, 주요 지표는 집계 처리량이며, 종종 달러당 메가 토큰으로 측정됩니다.
핵심 성능 지표
이러한 워크로드를 관리하려면 엔지니어가 복제본당 특정 지표를 추적하여 시스템 확장 방식을 결정해야 합니다:
- Time to First Token (TTFT): 사용자가 첫 번째 출력 바이트를 보기까지의 지연 시간.
- Inter-token Latency: 연속 토큰 사이에 경과된 시간.
- Queries Per Second (QPS): 요청량으로, 종종 높은 계절성 및 변동성을 보입니다.
- Prefix Reuse: 입력 토큰이 겹치는 빈도로, KV 캐싱을 통해 연산 비용을 줄일 수 있습니다.
모델 선택: 효율성 vs. 능력 한계
모델 선택은 작업이 효율성에 제한되는지 능력에 제한되는지에 따라 결정됩니다:
효율성 제한 워크로드
이러한 작업에서는 필요한 지능 수준이 비교적 낮고 쉽게 달성됩니다. 비용이 주요 동인이 됩니다. 이러한 워크로드는 일반적으로 오픈소스 모델(예: Mistral, Gemma)로 제공되며, 비용 대비 성능을 극대화하기 위해 단일 GPU 복제본에서 실행되는 경우가 많습니다.
능력 제한 워크로드
이러한 작업은 현재 가능한 최고 수준의 지능을 필요로 하며, 확장이 현재 유일한 해결책입니다. 이러한 모델(예: 최첨단 독점 모델)은 규모가 방대하여 복제본당 여러 GPU와 종종 여러 노드가 필요합니다. 이들은 일반적으로 다중 에이전트 시스템에서 오케스트레이터 역할을 수행하며, 더 작고 효율성 제한 하위 에이전트를 관리합니다.
추론 스택: 엔진 및 하드웨어
추론 엔진
추론 엔진은 토크나이징을 위한 서버 프로세스, CPU 상의 스케줄러, 그리고 GPU 실행으로 구성됩니다. 스케줄러의 주요 역할은 GPU가 절대 유휴 상태가 되지 않도록 하는 것입니다. 현재 주요 오픈소스 엔진은 다음과 같습니다:
- vLLM: 오픈 거버넌스로 널리 채택된 엔진.
- SGLang: 공격적인 최적화를 통해 성능에 초점을 맞춘 엔진.
- TensorRT-LLM: NVIDIA에서 제공하는 컴파일된 C++ 런타임으로, 작은 모델 및 작은 배치 크기에 최적화되어 있습니다.
하드웨어 제약
생산 추론은 고대역폭 메모리(HBM) 때문에 NVIDIA 데이터센터 GPU(SXM 폼 팩터)가 지배합니다. 디코드 단계는 심각하게 메모리 제한을 받으며, Tensor Cores가 바이트당 수천 개의 연산을 수행할 수 있는 반면 디코드 단계는 몇 개만 수행합니다. 따라서 HBM과 고속 인터커넥트(NVLink)는 연산 유닛이 유휴 상태가 되는 것을 방지하는 데 필수적입니다.
대규모 배포 및 견고성
수천 대의 GPU를 서빙하면 신뢰성 및 비용 측면에서 상당한 도전 과제가 발생합니다:
- Hardware Failure: H100 GPU는 평균 고장 시간이 일수에서 주 단위로 측정됩니다. 시스템은 하드웨어 결함이 시스템 장애로 이어지지 않도록 중복성을 갖추어야 합니다.
- Cold Start and Scaling: 가변 트래픽을 처리하면서 유휴 GPU에 비용을 낭비하지 않으려면 시스템은 빠른 복제본 시작이 필요합니다. 이는 파일 시스템의 지연 로딩, 다계층 클라우드 캐싱, 그리고 체크포인트-복원 기술(예: CRIU)을 통해 수분에 걸리는 JIT 컴파일 및 CUDA 그래프 캡처 시간을 피함으로써 달성됩니다.
성능 최적화 기법
최적화는 계층 구조를 따라 진행해야 합니다: 높은 영향력을 가진 알고리즘 변경으로 시작하고, 호스트 측 엔지니어링으로 이동한 뒤, 마지막으로 저수준 커널 작업을 수행합니다.
추측 디코딩
추측 디코딩은 디코드 단계의 메모리 대역폭 병목을 해결합니다. 작은 “draft” 모델이 다음 몇 토큰을 추측하고, 더 큰 타깃 모델이 이를 단일 전방 패스로 검증합니다. 특히 애플리케이션 전용 draft 모델을 사용할 경우 2배에서 8배까지 속도 향상을 얻을 수 있습니다.
양자화
정밀도를 낮추면(예: FP8에서 FP4로) 이동하는 바이트 수를 줄이고 초당 연산 수를 늘려 메모리 제한 및 연산 제한 시나리오 모두에서 선형적인 속도 향상을 제공합니다. 그러나 양자화는 누적 오류로 인해 긴 시퀀스에서 성능이 저하될 수 있으므로 “vibe checks”와 정식 평가를 통해 신중히 검증해야 합니다.
호스트 측 최적화
맞춤형 CUDA 커널을 작성하기 전에 엔지니어는 py-spy와 같은 도구를 사용해 Python 수준의 병목을 찾아야 합니다. 텐서를 재생성하는 대신 사전에 포인터를 딕셔너리에 캐시하는 등 간단한 변경만으로도 GPU 측 변경 없이도 상당한 이득(예: 멀티모달 추론에서 10% 향상)을 얻을 수 있습니다.
가시성 및 디버깅
가시성은 로그만으로 시스템을 디버깅할 수 있는 능력으로 정의됩니다. 핵심 실천 사항은 다음과 같습니다:
- Logging Token IDs: 문자열만 로그에 남기는 것은 충분하지 않으며, 토큰 ID를 기록해야 토크나이저 및 챗 템플릿의 미묘한 버그를 디버깅할 수 있습니다.
- Monitoring Power Draw: GPU 전력 소비와 온도는 “무료” 지표로, 호스트 측 병목을 알릴 수 있습니다(예: GPU가 3kW 대신 2kW를 소비한다면 CPU가 작업을 충분히 공급하지 못하고 있을 가능성이 높습니다).
- Evaluating Tails: P95 및 P99 지연 시간은 중간(P50) 지연이 낮더라도 사용자가 겪는 “끊김” 경험을 나타내므로 중요합니다.