LLM WikiAccess-protected knowledge portal
← 스터디 홈
123편 · 약 14분

Sarathi-Serve와 청크형 프리필: LLM 서빙에서 TTFT-처리량 균형을 찾는 방법

요약

LLM 서빙 시스템에서 두 가지 지표가 자주 충돌한다. TTFT(Time To First Token): 사용자가 요청을 보내고 첫 토큰을 받기까지 걸리는 시간이다. 처리량(throughput): 시스템이 초당 처리하는 총 토큰 수다.

표준 연속 배칭(continuous batching)에서는 긴 프리필 요청이 배치에 들어오면 진행 중인 모든 디코딩 스텝이 멈춘다. 이를 Head-of-Line(HoL) 블로킹이라 부른다. 인터랙티브 애플리케이션에서는 TTFT가 수 초로 치솟아 사용자 경험이 급격히 나빠진다.

Sarathi-Serve(arXiv:2308.16369, OSDI 2024)는 이 문제를 청크형 프리필(Chunked Prefill)로 해결한다. 프리필 요청을 고정 크기 청크로 나눠 디코딩 스텝과 인터리브한다. 각 스케줄링 스텝에서 최대 하나의 프리필 청크만 처리하고, 나머지 슬롯은 디코딩 요청이 채운다.

결과: TTFT 급등 없이 처리량을 유지하는 것이 가능하다. 청크 크기라는 단일 파라미터로 TTFT-처리량 균형을 조절할 수 있다.

2026년 현재 vLLM·SGLang·TRT-LLM 모두 청크형 프리필을 기본값 또는 권장 설정으로 채택했다.


배경: 연속 배칭의 HoL 블로킹 문제

연속 배칭 복습

연속 배칭은 각 디코딩 스텝 후 완료된 요청을 배치에서 제거하고 새 요청을 즉시 추가한다. 요청이 완료될 때까지 기다리지 않고 GPU를 최대한 활용한다. Orca(Yu et al., 2022)가 처음 제안한 이 방식은 현대 LLM 서빙 시스템의 기반이 됐다.

[연속 배칭 배치 상태]

스텝 1: [req-A decode] [req-B decode] [req-C decode]
스텝 2: [req-A done] [req-B decode] [req-C decode] [req-D prefill→decode]
스텝 3: [req-D decode] [req-B decode] [req-C decode]

HoL 블로킹 발생 조건

긴 프롬프트(예: 4096 토큰)를 가진 요청이 배치에 진입하면, 해당 프리필 연산이 완료될 때까지 GPU의 모든 연산이 해당 요청에 집중된다. 디코딩 중인 다른 요청들은 그 스텝 동안 응답을 내보낼 수 없다.

현실적인 영향: 8K 토큰 프롬프트 요청이 2초의 프리필 시간을 차지하면, 같은 배치에서 스트리밍 중인 모든 사용자가 2초 동안 응답이 멈춘다. p99 TTFT가 평균보다 10~100배 높아지는 이유가 여기 있다.


Sarathi-Serve: 청크형 프리필 스케줄링

핵심 아이디어

긴 프리필을 한 번에 처리하지 않는다. 최대 청크 크기(chunk size) 단위로 분할하고, 각 스케줄링 스텝에서 최대 하나의 프리필 청크만 처리한다. 나머지 배치 슬롯은 디코딩 요청이 채운다.

청크형 프리필 vs 표준 연속 배칭 표준 연속 배칭 — HoL 블로킹 스텝 1 A decode B decode C decode 스텝 2 LONG prefill (4096 tokens) — HoL Blocking ⚠ 스텝 3 A decode B decode LONG decode 스텝 2에서 A/B/C 응답 완전 중단 HoL 블로킹 영향 • 스트리밍 사용자: 갑작스러운 응답 중단 • TTFT 급등: 긴 요청이 배치에 들어올 때마다 반복 • p99 TTFT가 평균보다 10~100배 높아질 수 있음 • 프롬프트가 길수록 HoL 블로킹 지속 시간 비례 증가 청크형 프리필 — Sarathi-Serve 스텝 1 A dec B dec C dec LONG chunk 1/8 스텝 2 A dec B dec C dec LONG chunk 2/8 ... (스텝 3~7: 동일 패턴) ... 스텝 8 A dec B dec C dec LONG chunk 8/8 스텝 9 A dec B dec C dec LONG decode 청크형 프리필 효과 • A/B/C 스트리밍: 8 스텝 내내 응답 지속 (HoL 없음) • LONG TTFT: 8 스텝 후 첫 토큰 (표준과 동일) • GPU 활용률: 매 스텝 decode + 프리필 청크 1개 • 청크 크기 조절로 TTFT-처리량 균형 조정 가능
청크형 프리필 vs 표준 프리필 스케줄링

스케줄러 로직

Sarathi의 스케줄러는 매 스텝마다 다음 결정을 내린다:

  1. 디코딩 요청 수집: 진행 중인 모든 decode 요청을 배치에 포함
  2. 프리필 청크 선택: 대기열에서 하나의 요청을 골라 최대 chunk_size 토큰만 처리
  3. 배치 구성: 나머지 GPU 메모리와 연산 예산 내에서 슬롯 채우기

핵심 불변식: 한 스텝에서 최대 하나의 프리필 청크만 처리한다.

프리필이 완료되지 않은 요청은 다음 스텝에서 남은 청크를 이어 처리한다. 이 과정에서 이미 계산된 KV 캐시는 누적되어 재사용된다.


청크 크기와 TTFT-처리량 트레이드오프

청크 크기는 Sarathi-Serve의 핵심 조절 파라미터다.

청크 크기별 동작 요약

청크 크기TTFT 영향처리량 영향적합한 워크로드
64~128 토큰최소 (HoL 거의 없음)감소 (스케줄링 오버헤드 증가)인터랙티브 채팅, TTFT 민감
256~512 토큰양호양호일반 목적 API
1024~2048 토큰허용 가능최대화에 근접배치 처리, 처리량 우선

vLLM 기본값: --max-num-batched-tokens 2048과 함께 청크형 프리필 기본 활성화 (v0.4.0+)

처리량 손실이 생각보다 적은 이유

프리필 연산과 디코딩 연산은 GPU 자원 사용 패턴이 다르다.

  • 프리필: 입력 토큰 전체를 행렬 연산으로 병렬 처리 → compute-bound
  • 디코딩: 한 토큰씩 순차 생성 → memory-bandwidth-bound

청크형 프리필에서 프리필 청크와 디코딩 요청이 같은 스텝에 있으면, 서로 다른 GPU 자원을 주로 사용하므로 실제 충돌이 예상보다 적다. 이것이 청크형 프리필이 처리량 손실 없이 TTFT를 개선할 수 있는 핵심 이유다.

최적 청크 크기 선택 가이드

워크로드 프로파일링 → 청크 크기 결정

1. 평균 프롬프트 길이 측정
   짧음 (< 512 토큰): chunk_size 256 이하로 시작
   중간 (512~4096):   chunk_size 512~1024
   긺 (4096+):        chunk_size 1024~2048

2. TTFT SLO 확인
   p99 TTFT < 500ms: 작은 청크 (256~512)
   p99 TTFT < 2s:    중간 청크 (512~1024)

3. GPU 활용률 모니터링
   MFU < 60%: 청크 크기 늘려 처리량 개선
   TTFT p99 급등: 청크 크기 줄여 HoL 억제

운영 시스템별 구현 현황 (2026)

vLLM

vLLM v0.4.0부터 청크형 프리필을 지원하고, v0.25.0부터 기본값으로 전환됐다.

# 청크형 프리필 설정 (기본값으로 이미 활성화)
vllm serve meta-llama/Llama-4-Scout-17B-16E-Instruct \
  --enable-chunked-prefill \           # 기본값 true
  --max-num-batched-tokens 2048 \      # 청크 크기 제어 (토큰)
  --max-num-seqs 256

vLLM에서 --max-num-batched-tokens가 사실상 청크 크기를 결정한다. 프리필 요청이 이 값을 초과하면 자동으로 청크로 분할된다.

SGLang

SGLang은 ChunkFill이라는 자체 구현을 사용한다. 연속 배칭 루프에서 prefill-decode 인터리빙을 정밀하게 제어하며, 기본 스케줄러 정책으로 채택됐다.

TensorRT-LLM

TRT-LLM은 CHUNKED_CONTEXT 모드로 청크형 프리필을 지원한다. CUDA Graph와 함께 사용할 때는 별도 설정이 필요하다 — CUDA Graph는 고정 배치 크기를 가정하기 때문이다.


청크형 프리필과 PD 분리의 관계

청크형 프리필은 단일 서버 내 HoL 블로킹을 제거하는 기법이다. 더 나아가, Prefill-Decode 분리(PD Disaggregation)는 프리필과 디코드를 아예 다른 서버 풀에서 실행한다. (ai-frontier/23 참조)

두 기법은 계층적으로 적용 가능하다:

  • PD 분리 환경에서도 프리필 서버 내부에서 청크형 프리필을 사용하면 초장문 요청(100K+ 토큰) 처리 시 메모리 압력을 줄일 수 있다
  • 청크형 프리필이 단기 TTFT SLO를 달성하면 PD 분리 없이도 대부분의 인터랙티브 워크로드를 커버 가능하다

언제 PD 분리가 필요한가

상황청크형 프리필로 충분PD 분리 필요
평균 프롬프트 < 4K 토큰
실시간 스트리밍, p99 TTFT < 1s
평균 프롬프트 > 8K 토큰
TTFT SLO 매우 엄격 (< 200ms)
처리량을 극한까지 최적화

운영 체크리스트

설정 검증:

  • --max-num-batched-tokens 값이 워크로드 평균 프롬프트 길이의 1/4~1/2 수준인가
  • 청크형 프리필 활성화 여부: vLLM의 경우 vllm_config.scheduler_config.chunked_prefill_enabled 확인

지표 모니터링:

  • vllm:e2e_request_latency_seconds 히스토그램의 p50/p95/p99 분포
  • vllm:num_preemptions_total — 프리필 인터럽트로 인한 선점 횟수
  • vllm:avg_generation_throughput_toks_per_s — 처리량 기준

주의 사항:

  • 매우 짧은 프롬프트 워크로드(평균 < 64 토큰)에서는 청크형 프리필의 이점이 제한적
  • CUDA Graph와 청크형 프리필을 함께 사용하면 그래프 크기 증가로 GPU 메모리 오버헤드 발생
  • 청크형 프리필은 TTFT를 개선하지만, 동일 요청의 총 완료 시간(completion latency)은 청크 수만큼 디코딩 대기가 추가될 수 있음

요점 정리

연속 배칭에서 긴 프리필 요청이 야기하는 HoL 블로킹은 인터랙티브 LLM 서빙의 근본적 도전이었다. Sarathi-Serve의 청크형 프리필은 단 하나의 파라미터(청크 크기)로 이 문제를 해결한다.

핵심 교훈:

  • 청크 크기 = TTFT와 처리량 사이의 조절 손잡이
  • 2026년 주요 서빙 프레임워크에서 기본값으로 채택 완료
  • PD 분리의 개념적 전신이자 실용적 보완 기법

청크형 프리필을 이해하지 않고 LLM 서빙 인프라를 운영하면, TTFT 이상 징후의 원인을 진단하기 어렵다. vLLM --max-num-batched-tokens 설정 하나가 사용자 경험을 크게 바꿀 수 있다.


References

  • Agrawal, A. et al., "Sarathi: Efficient LLM Inference by Piggybacking Decodes with Chunked Prefills" — arXiv:2308.16369 (2023); presented at OSDI 2024
  • vLLM Chunked Prefill 공식 문서: https://docs.vllm.ai/en/latest/serving/chunked_prefill.html
  • Yu, G. et al., "Orca: A Distributed Serving System for Transformer-Based Generative Models" — OSDI 2022; 연속 배칭의 원조 논문
  • "Splitwise: Efficient Generative LLM Inference Using Phase Splitting" — arXiv:2311.18677 (2023); PD 분리 개념 선구 연구
  • "Taming Throughput-Latency Tradeoff in LLM Inference with Sarathi-Serve" (Microsoft Research Blog): https://www.microsoft.com/en-us/research/blog/sarathi-serve/
  • vLLM GitHub: https://github.com/vllm-project/vllm — scheduler/chunked_prefill 구현 참조