LLM 인퍼런스 병목 및 최적화 방안
개요
기존의 웹 애플리케이션이나 마이크로서비스 아키텍처(MSA)에서는 트래픽 병목이 주로 네트워크 I/O나 데이터베이스 동시성에서 발생합니다. 그러나 AI Transformation (AX) 과정에서 자체 모델 서빙을 구축하거나 대규모 트래픽을 처리할 때 마주하게 되는 가장 큰 기술적 병목은 LLM의 인퍼런스(추론) 단계입니다.
대규모 언어 모델(LLM)의 추론은 GPU의 연산 능력(Compute)과 메모리 대역폭(Memory Bandwidth)에 극심한 부하를 주게 되며, 이를 이해하고 최적화하지 않으면 비용이 기하급수적으로 증가하고 서비스 지연(Latency)이 발생합니다.
1. LLM 추론의 2가지 단계와 병목의 원인
LLM이 사용자의 질문(Prompt)을 받고 답변을 생성하는 과정은 크게 Prefill(사전 채우기)과 Decode(해독/생성) 단계로 나뉩니다. 두 단계는 병목을 일으키는 원인이 다릅니다.
A. Prefill 단계 (프롬프트 처리)
- 과정: 사용자가 입력한 전체 프롬프트 토큰들을 한 번에 병렬로 처리하여 Key-Value (KV) 값을 계산합니다.
- 특징: 첫 번째 토큰을 생성하기 전까지의 시간인 TTFT (Time To First Token)를 결정짓습니다.
- 병목 원인 (Compute-Bound): 방대한 행렬 곱 연산이 순간적으로 일어나므로 GPU의 연산 자원(Math/Compute Limits)이 병목이 됩니다.
B. Decode 단계 (토큰 생성)
- 과정: Prefill 이후, 이전까지 생성된 모든 맥락(KV Cache)을 활용하여 다음 토큰을 하나씩 순차적으로(Autoregressive) 생성합니다.
- 특징: 토큰 한 개당 걸리는 시간인 TPOT (Time Per Output Token)을 결정짓습니다.
- 병목 원인 (Memory-Bound): 토큰 하나를 생성할 때마다 수 GB~수십 GB에 달하는 모델 가중치(Weights)와 KV 캐시 데이터를 GPU VRAM에서 연산 코어로 끌어와야(Load) 합니다. 연산 자체는 단순하지만, 메모리 대역폭(데이터 전송 속도)이 처리 속도를 따라가지 못해 생기는 지연이 병목의 핵심입니다.
2. LLM 서빙의 핵심 장애물: KV 캐시 (KV Cache)
Decode 단계의 핵심 병목을 이해하려면 KV 캐시 메모리를 이해해야 합니다. LLM은 이전 토큰을 잊지 않기 위해 과거 어텐션(Attention) 연산 결과물(Key, Value 행렬)을 VRAM에 저장합니다.
- 다중 사용자 동시 접속 시: 수천 명의 사용자가 긴 대화를 나눌 경우 이 KV 캐시가 테라바이트 수준으로 늘어날 수 있습니다.
- 메모리 단편화 (Fragmentation): 기존 서빙 구조에서는 요청이 들어올 때마다 최대 길이만큼 미리 메모리 공간을 예약(Pre-allocation)했기 때문에, 실제 사용되지 않는 빈 공간과 파편화로 인해 VRAM의 약 60~80%가 낭비되는 문제가 발생했습니다. (이로 인해 배치 사이즈를 늘리지 못하고 큐가 밀리는 현상 발생)
3. 문제를 해결하기 위한 주요 기술 방안
업계에서는 이러한 인퍼런스 병목 현상을 해결하기 위해 모델 구조, 메모리 관리 시스템, 그리고 병렬 처리 기술 관점에서 다양한 최적화를 적용하고 있습니다.
3.1. 메모리 관리 혁신: PagedAttention (vLLM)
운영체제(OS)의 가상 메모리(Virtual Memory) 페이징 기법에서 착안한 기술로, 선풍적인 인기를 끌며 현재 vLLM 엔진의 핵심 기반 기술이 되었습니다.
- 원리: KV 캐시를 연속된 큰 덩어리로 메모리에 할당하지 않고, 비연속적인 고정 크기의 ‘블록(Page)’으로 나누어 관리합니다.
- 효과: 메모리 파편화를 0%에 가깝게 줄여 VRAM 낭비를 없앴으며, 이를 통해 한 번에 처리할 수 있는 배치 크기를 대폭 늘려 서빙 처리량(Throughput)을 기존 대비 2~4배 향상시킵니다.
3.2. 효율적 스케줄링: 지속적 배칭 (Continuous Batching)
기존 정적 배칭(Static Batching)에서는 가장 긴 프롬프트 처리가 끝날 때까지 다른 요청들이 기다려야 했지만, 지속적 배칭(혹은 In-flight Batching)을 통해 동적으로 처리를 최적화합니다.
- 원리: 새로운 요청이 들어오면 대기하지 않고, 현재 진행 중인 토큰 생성(Decode) 배치 안의 빈 공간에 실시간으로 끼워넣어 연산합니다. 처리가 일찍 끝난 요청의 자리는 즉시 반환됩니다.
- 효과: GPU의 유휴 시간(Idle time)을 최소화하여 인퍼런스 처리량을 극대화합니다.
3.3. 모델 경량화: 양자화 (Quantization)
메모리 대역폭 한계(Memory-Bound)를 극복하기 위해 가장 직관적인 방법은, 메모리로 이동해야 하는 데이터의 크기 자체를 줄이는 것입니다.
- 원리: 모델의 가중치(Weights)와 활성화(Activations) 데이터의 정밀도를 실수 표현 방식(FP16 또는 BF16)에서 더 낮은 비트 수(INT8, INT4 등)로 줄입니다. 대표적으로 GPTQ, AWQ, EXL2 등의 기법이 사용됩니다.
- 효과: 모델이 차지하는 VRAM 공간이 절반 이하로 줄어들고, 메모리 대역폭 부담이 줄어 추론 속도가 빨라집니다. (극소량의 정확도 손실 발생). 최근에는 FP8 양자화를 기본 지원하는 하드웨어(NVIDIA H100)와 소프트웨어(vLLM)의 조합이 각광받고 있습니다.
3.4. 추론 가속화: 추측 디코딩 (Speculative Decoding)
토큰을 매번 1개씩 순차적으로 생성해야 하는 Autoregressive 방식의 한계를 돌파하기 위한 기법입니다.
- 원리: 아주 작고 빠른 초안 작성용 모델(Draft Model)이 미래의 여러 토큰을 매우 빠른 속도로 한 번에 예측해내고, 거대하고 무거운 목적 모델(Target Model)이 이것을 한 번의 패스로 빠르게 검증(Verification)하여 확정짓는 방식입니다.
- 효과: 거대 모델의 메모리 로드 횟수 자체를 크게 줄일 수 있어 지연 시간(Latency) 단축에 매우 유리합니다.
3.5. 분산 처리: 모델 병렬화 (Model Parallelism)
모델의 크기가 너무 커서 단일 GPU의 VRAM에 올라가지 않거나 극도의 짧은 지연 시간이 필요할 경우 사용합니다.
- 텐서 병렬화 (Tensor Parallelism): 단일 레이어 내의 행렬 연산을 여러 GPU로 쪼개어 동시에 수행한 뒤 결과를 합칩니다. 지연 시간을 줄이는데 효과적이지만, GPU 간 높은 통신 대역폭(NVLink)이 필수적입니다.
- 파이프라인 병렬화 (Pipeline Parallelism): 모델의 전체 레이어를 여러 묶음으로 나누어 1번 GPU는 앞쪽 레이어를, 2번 GPU는 중간 레이어를 순서대로 처리하게 합니다.
요약
AX 추진 중 로컬 모델 호스팅 환경에서 서비스 속도 저하와 인프라 병목 현상에 직면했다면,
- vLLM과 같은 PagedAttention 및 Continuous Batching 지원 서빙 엔진 구축.
- 정확도 하락을 감수할 수 있다면 FP8/INT8/AWQ 기반의 양자화(Quantization) 모델 채택.
- 아키텍처 관점에서 다중 모델 라우팅 체계(AI API Gateway)를 활용한 부하 분산.
이 세 가지 방안이 최적의 해결책이 될 수 있습니다.