LLM Inference (9) - Continuous Batching

이도연·2026년 7월 24일

AI 이론 공부해보기

목록 보기
65/76
post-thumbnail

좋은 아침입니다.

PagedAttention은 필요한 만큼의 Physical Block만 할당하여 KV Cache의 메모리 낭비를 줄이는 방법이었습니다.

하지만 GPU 메모리를 효율적으로 사용하더라도 여러 사용자의 요청을 어떤 방식으로 묶어서 처리할 것인지에 따라 GPU의 사용 효율이 달라집니다.

특히 각 요청의 입력과 출력 길이가 다르면 먼저 끝난 요청의 자리가 비어 있어도 다른 요청을 바로 처리하지 못하는 문제가 발생할 수 있습니다.

이번 글에서는 여러 요청을 GPU에서 효율적으로 처리하기 위한 방법인 Continuous Batching에 대해 알아보겠습니다.


Batching

Batching은 여러 요청을 하나로 묶어 GPU에서 동시에 처리하는 방법입니다.

요청 A
요청 B
요청 C

   ↓

하나의 Batch로 구성

   ↓

GPU에서 함께 처리

GPU는 하나의 요청을 처리하는 것보다 여러 요청을 병렬로 처리할 때 연산 장치를 더 효율적으로 사용할 수 있습니다.
따라서 Batching을 사용하면 일정 시간 동안 처리할 수 있는 요청의 수인 Throughput을 높일 수 있습니다.

하지만 LLM은 요청마다 입력 길이와 출력 길이가 서로 다릅니다.

요청 A: 5개의 토큰 생성

요청 B: 20개의 토큰 생성

요청 C: 10개의 토큰 생성

이러한 특징으로 인해 일반적인 Batching 방식에서는 GPU 자원이 낭비될 수 있습니다.


Static Batching

(왼쪽이 일반적인 Batching이고, 오른쪽이 Static Batching입니다.)

Static Batching은 여러 요청을 하나의 Batch로 구성한 뒤, Batch에 포함된 요청이 모두 끝날 때까지 같은 Batch를 유지하는 방식입니다.

Batch

[ 요청 A ][ 요청 B ][ 요청 C ]

LLM은 한 번의 연산으로 전체 문장을 생성하지 않습니다.
하나의 토큰을 생성한 뒤, 생성된 토큰을 다시 입력으로 사용하여 다음 토큰을 생성합니다.

1번째 반복: 각 요청에서 토큰 1개 생성

2번째 반복: 각 요청에서 토큰 1개 생성

3번째 반복: 각 요청에서 토큰 1개 생성

이때 요청 A가 먼저 끝나더라도 요청 B와 요청 C가 끝날 때까지 Batch가 유지됩니다.

1번째 반복

[ 요청 A ][ 요청 B ][ 요청 C ]


요청 A 종료

[   빈자리   ][ 요청 B ][ 요청 C ]

빈자리가 생겼지만 대기 중인 새로운 요청을 바로 추가하지 못합니다.

결국 가장 긴 요청이 끝날 때까지 일부 GPU 연산 자원이 사용되지 않게 됩니다.

ORCA는 이러한 Request 단위의 Scheduling 문제를 해결하기 위해, 하나의 토큰을 생성하는 Iteration 단위로 요청을 관리하는 방식을 제안했습니다.


Continuous Batching

Continuous Batching은 하나의 Batch를 고정해서 유지하지 않고, 토큰을 생성하는 각 Iteration마다 Batch를 다시 구성하는 방법입니다.

Iteration-Level Batching 또는 In-flight Batching이라고도 합니다.

1. 여러 요청을 Batch로 구성

2. 각 요청에서 토큰 1개 생성

3. 종료된 요청 확인

4. 종료된 요청을 Batch에서 제거

5. 대기 중인 새로운 요청 추가

6. 다음 토큰 생성

요청이 끝나면 해당 자리에 대기 중인 새로운 요청을 바로 추가합니다.

기존 Batch

[ 요청 A ][ 요청 B ][ 요청 C ]


요청 A 종료

[   빈자리   ][ 요청 B ][ 요청 C ]


새로운 요청 D 추가

[ 요청 D ][ 요청 B ][ 요청 C ]

따라서 가장 긴 요청이 끝날 때까지 기다리지 않고 GPU의 빈자리를 계속 새로운 요청으로 채울 수 있습니다.

TensorRT-LLM에서는 이를 In-flight Batching이라고 부르며, 각 토큰 생성 Iteration에서 완료된 요청을 반환하고 새 요청을 추가할 수 있도록 지원합니다.


Continuous Batching의 동작 방식

처음에는 대기 중인 요청을 모아 하나의 Batch를 구성합니다.

Batch

[ 요청 A ][ 요청 B ][ 요청 C ]

GPU는 각 요청에 대해 다음 토큰을 하나씩 생성합니다.

요청 A → 토큰 1개 생성

요청 B → 토큰 1개 생성

요청 C → 토큰 1개 생성

토큰 생성이 끝나면 Scheduler는 각 요청의 상태를 확인합니다.

요청 A → 생성 완료

요청 B → 생성 중

요청 C → 생성 중

완료된 요청 A를 Batch에서 제거하고 대기 중인 요청 D를 추가합니다.

다음 Iteration

[ 요청 D ][ 요청 B ][ 요청 C ]

이 과정을 토큰을 생성할 때마다 반복합니다.

1. 토큰 생성

2. 완료된 요청 제거

3. 새로운 요청 추가

4. Batch 재구성

5. 다음 토큰 생성

vLLM도 들어오는 요청을 Continuous Batching 방식으로 처리하여 GPU 사용률과 Serving Throughput을 높입니다.


Static Batching과 Continuous Batching 비교

Static Batching

Static Batching은 처음 구성된 Batch를 모든 요청이 끝날 때까지 유지합니다.

구현 방식이 비교적 단순하지만 먼저 끝난 요청의 자리를 바로 재사용할 수 없습니다.

[ 완료 ][ 실행 중 ][ 실행 중 ]

따라서 요청의 출력 길이 차이가 클수록 GPU 자원이 낭비될 수 있습니다.

Continuous Batching

Continuous Batching은 각 Iteration이 끝날 때마다 완료된 요청을 제거하고 새로운 요청을 추가합니다.

[ 새로운 요청 ][ 실행 중 ][ 실행 중 ]

GPU의 빈자리를 계속 채울 수 있기 때문에 여러 요청을 처리하는 환경에서 GPU 사용률과 Throughput을 높일 수 있습니다.


Continuous Batching의 장단점

장점

Continuous Batching은 먼저 종료된 요청의 자리에 새로운 요청을 바로 추가합니다.

따라서 가장 긴 요청이 끝날 때까지 기다릴 필요가 없습니다.

GPU의 빈자리를 줄여 연산 자원을 더 효율적으로 사용할 수 있습니다.

동시에 더 많은 요청을 처리할 수 있어 LLM Serving의 Throughput을 높이는 데 도움이 됩니다.

또한 새로운 요청이 기존 Batch가 모두 종료될 때까지 기다리지 않아도 되므로 대기 시간을 줄일 수 있습니다.

단점

Continuous Batching은 토큰을 생성할 때마다 요청의 상태를 확인하고 Batch를 다시 구성해야 합니다.

따라서 Static Batching보다 Scheduler의 구조가 복잡합니다.

각 요청의 입력 길이와 현재 생성된 토큰 수가 다르기 때문에 서로 다른 길이의 데이터를 함께 처리할 수 있는 별도의 관리 방식도 필요합니다.

또한 한 번에 너무 많은 요청을 Batch에 추가하면 Throughput은 증가할 수 있지만, 각 요청이 토큰을 받기까지의 시간은 길어질 수 있습니다.

따라서 Serving 환경에서는 GPU 메모리와 요청의 지연 시간을 고려하여 적절한 Batch 크기를 설정해야 합니다.

요약

이번 글에서는 Continuous Batching에 대해 알아보았습니다.

핵심 내용을 정리하면 다음과 같습니다.

  • Batching은 여러 요청을 하나로 묶어 GPU에서 동시에 처리하는 방법입니다.

  • LLM은 요청마다 입력 길이와 출력 길이가 서로 다릅니다.

  • Static Batching은 처음 구성된 Batch를 모든 요청이 끝날 때까지 유지합니다.

  • 먼저 종료된 요청이 있어도 가장 긴 요청이 끝날 때까지 빈자리가 발생할 수 있습니다.

  • Continuous Batching은 각 토큰 생성 Iteration마다 Batch를 다시 구성합니다.

  • 완료된 요청은 Batch에서 제거하고 대기 중인 새로운 요청을 바로 추가합니다.

  • Continuous Batching은 Iteration-Level Batching 또는 In-flight Batching이라고도 합니다.

  • GPU의 빈자리를 계속 새로운 요청으로 채워 GPU 사용률을 높일 수 있습니다.

  • GPU가 동시에 처리할 수 있는 요청이 증가하면 LLM Serving의 Throughput도 높아질 수 있습니다.

  • Continuous Batching은 Static Batching보다 Scheduler와 Batch 관리 방식이 복잡합니다.


다음 글에서는 작은 모델이 여러 토큰을 먼저 생성하고, 큰 모델이 이를 검증하는 Speculative Decoding에 대해 알아보겠습니다.

Speculative Decoding은 큰 모델의 토큰 생성 횟수를 줄이면서도 기존 모델의 출력 분포를 유지하여 LLM 추론 속도를 높이는 방법입니다.

부족한 글 읽어주셔서 감사합니다.

틀린 내용이나 피드백은 댓글로 남겨주시면 감사하겠습니다.

감사합니다.


그림 출처 : https://dytis.tistory.com/59

profile
저희.서이.하실래요?

0개의 댓글