LLM推論サーバーにおいて、リクエスト単位ではなくイテレーション(1トークン生成ステップ)単位でバッチを動的に再構成する手法。完了したリクエストを即座に除外し、新規リクエストを即座に挿入することでGPU利用率を最大化する。
Continuous Batching(連続バッチング)とは、LLM推論サーバーにおけるリクエストスケジューリング手法の一つで、従来のStatic Batching(バッチ内の全リクエストが完了するまで待つ方式)を置き換える技術である。2023年にvLLMプロジェクトが本格実装し、以降TensorRT-LLM、SGLang、LMDeployなど主要推論エンジン全てが採用している。リクエストの到着・完了をイテレーション単位で柔軟に処理し、GPUのアイドル時間を最小化する。
従来のStatic Batchingでは、バッチ内の全リクエストが生成を完了するまで新しいリクエストを受け付けられない。
4リクエストのバッチで、生成トークン数がそれぞれ10, 50, 200, 30の場合:
| バッチ方式 | GPU利用率 | レイテンシ | スループット | 実装複雑度 |
|---|---|---|---|---|
| Static Batching | 30〜50% | 高(最長リクエスト依存) | 低 | 低 |
| Dynamic Batching | 50〜70% | 中(バッファ待ち) | 中 | 中 |
| Continuous Batching | 80〜95% | 低(即時挿入) | 高 |
| 高 |
新規リクエストはprefillフェーズ(プロンプト全体の処理)が必要だが、既存リクエストはdecodeフェーズ(1トークンずつ生成)にある。Continuous Batchingではこれらを同一イテレーション内で混在処理する。
Chunked Prefill: 長いプロンプト(4,096トークン以上)のprefillを512〜1,024トークンのチャンクに分割し、decode中のリクエストとインターリーブすることで、prefillによるdecodeの遅延を防止する。SGLangとvLLM 0.5以降で実装。
max_num_seqsパラメータでバッチサイズ上限を制御(デフォルト256)NVIDIA H100 80GB SXM × 1台、Llama 3.1 70B INT4(AWQ量子化)
| 同時リクエスト数 | Static Batch TPS | Continuous Batch TPS | 改善率 |
|---|---|---|---|
| 1 | 45 | 45 | 1.0× |
| 8 | 120 | 280 | 2.3× |
| 32 | 150 | 850 | 5.7× |
| 64 | 160 | 1,200 | 7.5× |
| 128 | OOM | 1,500 | ∞ |
同時リクエスト数が増えるほどContinuous Batchingの優位性が顕著になる。128同時リクエストではStatic BatchingがOOM(メモリ不足)で動作不可な一方、PagedAttention併用のContinuous Batchingは安定動作する。
Q1: Continuous BatchingとDynamic Batchingの違いは何ですか? A: Dynamic Batchingは一定時間(例: 50ms)リクエストをバッファしてバッチを構成する方式で、バッチ実行中は新規挿入不可。Continuous Batchingは各イテレーション(1トークン生成ごと)にバッチを再構成し、完了リクエストの即時除外・新規リクエストの即時挿入が可能。
Q2: Continuous Batchingのデメリットはありますか? A: スケジューラのオーバーヘッドが各イテレーションに加算される(通常0.1ms以下で無視可能)。また実装が複雑で、KVキャッシュの動的管理(PagedAttention等)が事実上必須となるため、自前実装のハードルは高い。
Q3: ローカルのOllamaやllama.cppでもContinuous Batchingは使えますか?
A: llama.cppのサーバーモード(llama-server)はContinuous Batching相当の機能を--cont-batchingフラグで提供。Ollamaも内部的にllama.cppベースでContinuous Batchingを活用している。