vLLM을 검색하다가 LLM 서빙에 대해 궁금해졌어요. 학습 진행하였고 정리해보았습니다.
LLM 서빙 프레임워크가 필요한 이유.
학습된 LLM은 수십억~수백억 개의 파라미터를 포함하고 있어, 사용자 요청마다 실시간 추론(inference)을 수행하려면 매우 큰 연산량과 GPU 메모리가 필요하다.
일반적인 LLM 서비스 구조는 다음과 같습니다.
- 클라이언트 → API 서버 → LLM 추론 서버(GPU) → 응답 반환
LLM 추론 시에는 다음과 같은 문제가 발생합니다.
- 모델 파라미터 로딩으로 인한 GPU 메모리 사용량 증가
- Autoregressive 생성 특성으로 인한 지연(latency) 증가
- KV cache로 인한 메모리 단편화
- 요청 길이 가변성으로 인한 GPU 활용률 저하
따라서 LLM 서빙 프레임워크는 다음 목적을 갖습니다.
- GPU 메모리 사용 최적화
- 추론 속도(latency) 개선
- 처리량(throughput) 증가
- 비용 절감
주요 LLM 서빙 프레임워크
- TGI (Text Generation Inference)
- Hugging Face 제공
- 다양한 오픈소스 모델 지원
- REST/gRPC 인터페이스 제공
- Production-ready (SSE streaming 등 지원)
👉 범용성이 가장 높은 표준 LLM 서버
- vLLM
- Python 기반
- PagedAttention 구현
- Continuous batching 지원
- Triton Inference Server 연동 가능
👉 현재 가장 높은 GPU 효율을 보이는 LLM 서버 중 하나
- LightLLM
- Python 기반 경량 LLM 서버
- 메모리 사용량 최소화에 집중
- 소형/경량 모델 환경에 적합
👉 리소스 제한 환경용
- TensorRT-LLM
- NVIDIA 개발
- CUDA 전용
- TensorRT 최적화 커널 사용
- Triton Inference Server 연동
- 모델을 TensorRT 포맷으로 변환 필요
👉 NVIDIA GPU 환경에서 최고 성능
vLLM vs LightLLM 성능 비교
카카오페이 내부 실험 기준
- 2B / 7B 모델 비교
- 동일 GPU 환경 테스트
- latency: vLLM < LightLLM
- throughput: vLLM 우수
Autoregressive 모델과 KV Cache
LLM은 Autoregressive 방식으로 텍스트를 생성합니다.
즉,
이전 토큰 출력 → 다음 토큰 입력 → 반복
Transformer에서는 이전 토큰의 attention 계산을 위해
Key/Value를 캐시에 저장하는데 이를 KV cache라고 합니다.
KV cache 사용 효과
- 중복 attention 계산 제거
- 추론 속도 향상
KV Cache 문제점
내부 메모리 단편화와 메모리 예약
- 입력 데이터의 길이를 예측할 수 없기에 요청마다 최대 길이에 해당하는 메모리를 할당하게 되는데 입력 값이 짧을 경우 비어 있는 메모리가 발생하게 되어 메모리가 낭비되어 배치 크기 및 처리량을 제한한다.
외부 메모리 단편화
GPU 메모리는 연속 공간 할당이 중요하기 때문에
작은 빈 공간이 많아지면 새로운 요청을 배치하기 어려워진다.
solution
PagedAttention
- block(page)단위로 나눠진 공간을 만들어 사용 효율을 높힘.
- 논리적 공간과 물리적 공간으로 나누어서 랜덤하게 논리적 공간을 물리적 공간에 지정함으로써 해결함.
개념
- KV cache = 여러 page로 분할
- 논리 주소 ↔ 물리 page 매핑
- 필요한 page만 할당
효과
- 메모리 단편화 감소
- GPU 사용률 증가
- 더 큰 batch 가능
- throughput 증가
👉 GPU 메모리를 가상 메모리처럼 사용
LLM Inference Batching
- 동시 처리
- 병렬로 할 수 있어 동시에 처리 가능함.
Static Batching vs Continuous Batching
| 구분 | Static Batching | Continuous Batching |
|---|
| 배치 구성 방식 | 일정 시간 동안 요청을 모아 배치 구성 | 요청 종료 시 즉시 새 요청 투입 |
| 처리 시작 시점 | 모든 요청을 동시에 시작 | 각 요청이 준비되는 즉시 시작 |
| 스케줄링 단위 | 요청(request) 단위 | 토큰(token) 단위 |
| 지연(latency) | 늦게 온 요청 대기 증가 | 대기 최소화 |
| GPU 활용률 | idle 발생 가능 | idle 최소화 |
| 처리량(throughput) | 제한적 | 높음 |
| 실시간 서비스 적합성 | 낮음 | 매우 높음 |
| 대표 프레임워크 | 기존 inference 서버 | vLLM 등 최신 LLM 서버 |
효율적으로 서빙하기.
1. 양자화
- 4bit, 8bit의 작은 비트로 데이터를 변환하여 추론을 수행하는 것.
- 메모리 로딩의 부하를 줄여주고 속도 이익을 얻는 것이 원리.
- activation까지 양자화를 하게되면 연산 커널을 적용하여 속도 향상을 얻을 수 있지만 평가 성능 감소의 영향이 있다.
Weight Only Quantization vs Weight/Activation Quantization Process
| 구분 | Weight Only Quantization | Weight + Activation Quantization |
|---|
| 양자화 대상 | Weight만 양자화 | Weight + Activation 모두 양자화 |
| Activation 정밀도 | FP16 / FP32 유지 | INT8 / INT4 등 저비트 |
| 연산 방식 | 기존 FP 연산 | 저비트 INT 연산 커널 사용 |
| 메모리 절감 효과 | 중간 | 매우 큼 |
| 속도 향상 | 제한적 | 큼 |
| GPU bandwidth 절감 | 일부 | 크게 절감 |
| 정확도 영향 | 거의 없음 | 감소 가능 |
| 구현 난이도 | 낮음 | 높음 |
| 안정성 | 높음 | 튜닝 필요 |
| 대표 알고리즘 | GPTQ, AWQ | SmoothQuant, ZeroQuant 등 |
| 적용 사례 | 대부분 LLM 서비스 | 고성능/초대형 모델 서빙 |
주요 양자화 방법
GPTQ
- 발생한 에러를 주변의 Weight로 전파 시켜 보상한다.
- Inverse Hesseion은 에러의 민감도를 의미한다.
AWQ
- 소수의 activation outlier 들이 activation quantization을 어렵게 한다.
- Activation의 진폭(scale)을 weight 쪽으로 옮겨준다.
QQQ
방법 1. Adaptive smoothing을 적용 - Outlier suppression
방법 2. GPTQ 수행 - Weight의 손실을 주변 weight을 통해 보상하는 방법
2. Speculative
구조
- Draft model (작은 모델)
- Target model (큰 모델)
동작
- 작은 모델이 여러 토큰 예측
- 큰 모델이 한 번에 검증
- 맞으면 여러 토큰 확정
- 틀리면 재생성
효과
- 큰 모델 호출 횟수 감소
- latency 감소
- throughput 증가
참고
https://youtu.be/GZtrmqgZk_I
https://youtu.be/mdninhUqp5o