추론 엔진의 세 층
LLM 추론 엔진은 한 덩어리로 보면 복잡하다.
하지만 대부분의 serving engine은 크게 세 층으로 나누어 볼 수 있다.
API / Frontend
-> Engine Core / Scheduler
-> GPU Worker / Model Runner
이 구분을 먼저 잡으면 이후에 나오는 기술들을 “어느 층의 문제를 푸는가”로 분류할 수 있다.
1. API / Frontend
API layer는 사용자의 요청을 받는 층이다.
HTTP request
OpenAI-compatible API
chat/completions schema
streaming response
auth, metrics, logging
여기서는 아직 GPU 계산이 핵심이 아니다. 중요한 일은 외부 요청을 엔진이 이해할 수 있는 내부 요청으로 바꾸는 것이다.
SGLang처럼 tokenizer와 detokenizer가 별도 manager로 분리된 엔진에서는 이 층을 조금 더 넓게 볼 수 있다.
text -> token ids
output token ids -> streamed text
즉 API layer는 사용자의 세계와 token engine의 세계를 연결한다.
2. Engine Core / Scheduler
Engine core는 추론 엔진의 교통 관제소다.
여기서 중요한 질문은 “다음 GPU step에 무엇을 태울 것인가?”이다.
request queue
prefill/decode scheduling
continuous batching
KV cache allocation
prefix cache / radix cache
preemption
speculative token scheduling
disaggregated prefill/decode routing
GPU는 비싼 자원이고, 요청은 계속 들어온다. 어떤 요청은 긴 prompt를 처리해야 하고, 어떤 요청은 decode token 하나만 만들면 된다. 어떤 요청은 KV cache 공간이 부족해서 기다려야 한다.
Engine core는 이 요청들을 batch로 묶고, KV cache 공간을 배정하고, 각 request의 상태를 갱신한다.
vLLM에서는 EngineCore, Scheduler, KVCacheManager가 이 층에 가깝다. SGLang에서는 Scheduler, ScheduleBatch, memory pool, radix cache 관련 코드가 이 층에 가깝다.
3. GPU Worker / Model Runner
GPU worker는 실제 모델 계산을 실행하는 층이다.
model forward
attention backend
KV cache read/write
sampling
CUDA graph
custom kernels
tensor parallel communication
Engine core가 “이번 step에 이 batch를 실행하라”고 정하면, GPU worker는 그 batch를 tensor 입력으로 만들고 model forward를 실행한다.
여기서 attention kernel, PagedAttention, FlashAttention, FlashDecoding, quantized GEMM 같은 주제가 등장한다.
즉 scheduler가 “무엇을 실행할지”를 정한다면, worker는 “그걸 GPU에서 어떻게 빠르게 실행할지”를 담당한다.
vLLM과 SGLang의 대응
두 엔진은 이름과 프로세스 구조가 다르지만 큰 지도는 비슷하다.
vLLM
API Server
-> Engine Core / Scheduler
-> GPU Worker / Model Runner
SGLang
HTTP Server + TokenizerManager + DetokenizerManager
-> Scheduler
-> TpModelWorker / ModelRunner
SGLang의 코드 주석은 엔진을 TokenizerManager, Scheduler, DetokenizerManager 세 컴포넌트로 설명한다. 학습 관점에서는 여기에 TpModelWorker / ModelRunner를 GPU 실행 층으로 따로 떼어 보면 vLLM과 더 잘 비교된다.
기술을 어디에 놓을까
이제 추론 기술들을 층별로 분류할 수 있다.
API / Frontend
- OpenAI-compatible API
- streaming
- request validation
- tokenizer / detokenizer
Engine Core / Scheduler
- continuous batching
- chunked prefill
- prefix caching
- KV cache allocation
- PagedAttention의 block table 관리
- speculative decoding의 verification scheduling
- prefill/decode disaggregation
GPU Worker / Model Runner
- model forward
- attention kernel
- FlashAttention
- FlashDecoding
- sampling kernel
- CUDA graph
- quantized GEMM
물론 완전히 깔끔하게 나뉘지는 않는다. 예를 들어 PagedAttention은 scheduler의 KV block 관리와 worker의 attention kernel이 함께 맞물린다.
그래도 이 구분은 유용하다. 새 기술을 볼 때 먼저 이렇게 물으면 된다.
이 기술은 request를 받는 문제인가?
batch와 KV cache를 배치하는 문제인가?
GPU에서 forward를 빠르게 실행하는 문제인가?
다음 카드로 이어지는 이유
prefill과 decode는 Engine Core와 GPU Worker 양쪽에 영향을 준다.
Engine Core 관점:
prefill 요청과 decode 요청을 어떻게 섞을까?
GPU Worker 관점:
prefill은 왜 GEMM에 가깝고, decode는 왜 memory-bound일까?
그래서 추론 엔진의 세 층을 먼저 잡고 나면 prefill-vs-decode를 더 정확히 읽을 수 있다.
확인
- API layer와 Engine Core의 책임은 어떻게 다른가?
- Scheduler가 “교통 관제소”라면, GPU worker는 어떤 역할인가?
- PagedAttention은 왜 Engine Core와 GPU Worker 양쪽에 걸친 기술인가?
- 새로운 추론 최적화 논문을 읽을 때 먼저 물어야 할 세 질문은 무엇인가?