LabHub

LLM 서빙 · 배칭(연속 배칭)과 큐잉 · 이론

정적 배칭이 버리는 것

LabHub 에서 이어서 보기

한 줄 요약

정적 배칭은 배치 안에서 가장 긴 요청이 끝날 때까지 나머지 슬롯을 놀린다. 연속 배칭은 끝난 슬롯을 즉시 새 요청으로 채운다. 그 차이가 처리량 2~5배다.

왜 이게 필요했나

이미지 분류 같은 작업에서 배칭은 단순합니다. 입력 크기가 같고 처리 시간도 같으니 32개를 모아 한 번에 돌리면 됩니다.

LLM 생성은 다릅니다. 각 요청의 출력 길이가 제각각입니다. 어떤 요청은 10토큰, 어떤 요청은 1,000토큰입니다. 정적 배칭으로 32개를 묶으면, 31개가 10토큰에서 끝나도 1,000토큰짜리가 끝날 때까지 그 31개 슬롯이 비어 있습니다. GPU 는 32개 분량의 자원을 잡고 1개를 처리합니다.

어떻게 동작하나

연속 배칭(continuous batching, 또는 in-flight batching)은 배치를 고정된 묶음이 아니라 유동적인 슬롯 집합으로 봅니다. 매 디코딩 반복마다 스케줄러가 확인합니다 — 끝난 시퀀스가 있으면 슬롯에서 빼고, 대기 큐에 요청이 있으면 그 슬롯에 넣습니다.

그러면 GPU 는 항상 최대치에 가까운 배치를 유지합니다. 벤치마크에서 정적 배칭 대비 처리량이 2~5배 향상되는 것으로 보고됩니다.

여기서 조절할 수 있는 값이 둘입니다. max_num_seqs 는 동시에 처리할 시퀀스 수의 상한이고, max_num_batched_tokens 는 한 반복에서 처리할 토큰 수의 상한입니다. 전자는 KV 캐시 메모리에 묶이고 후자는 연산 능력에 묶입니다.

트레이드오프가 있습니다. 동시성을 올리면 처리량이 오르지만 개별 요청의 지연이 늘어납니다. 그리고 KV 캐시가 부족해지면 스케줄러가 일부 시퀀스를 선점(preempt)해서 내보냈다가 나중에 다시 넣습니다. 이때 그 시퀀스의 KV 캐시를 버리고 다시 계산하거나 CPU 로 스왑하는데, 둘 다 비쌉니다. 선점이 자주 일어나면 처리량이 오히려 떨어집니다.

또 하나의 후보가 프리픽스 캐싱입니다. 여러 요청이 같은 시스템 프롬프트로 시작하면 그 부분의 KV 캐시를 재사용할 수 있습니다. 이득은 공통 접두어 길이, 재사용률, 구현과 메모리 정책에 따라 달라지며, 프롬프트가 매번 완전히 다르면 효과가 거의 없습니다. 실제 요청 분포에서 캐시 적중률과 TTFT 를 함께 측정해야 합니다.

현장에서 만나는 모습

큐 깊이와 꼬리 TTFT 의 관계를 보면 운영 감각이 생깁니다. 유입이 처리 능력에 가까워지면 대기 큐가 자라고 높은 백분위 지연이 평균보다 먼저 나빠집니다. 제품의 사용자 경험과 트래픽 규모에 맞춰 p95 또는 p99 같은 꼬리 백분위를 SLO 지표로 선택합니다.

그리고 목표를 정할 때 순서가 있습니다. 먼저 제품과 워크로드에 맞는 TTFT SLO 를 정하고(이 실습에서는 계산을 위해 200ms 를 예시로 사용), 그것을 만족하는 최대 동시성을 찾고, 그 동시성에서의 처리량을 용량 계획의 근거로 씁니다. 처리량만 먼저 최대화하면 꼬리 지연 SLO 를 놓치기 쉽습니다.

다음 실습에서 할 것

정적 배칭과 연속 배칭 스케줄러를 각각 시뮬레이션으로 구현해 처리량을 비교합니다. 동시성 상한을 적용하고, 큐 깊이와 p99 대기의 관계를 관찰하고, prefill 과 decode 의 비용을 분리해 모델링한 뒤, 실습용 예시 SLO 인 TTFT 200ms 를 만족하는 최대 동시성을 탐색합니다.