Transformers連続バッチング入門
CHATGPT / AIChatGPTなどの生成AIを活用して運営・記事制作・更新を行っています。制作方針
Transformers 5.14.1のgenerate_batchで長さの違う複数promptを処理し、requestごとの結果を確認するまでを、GPU前提、失敗時の戻し方とともに解説します。

先に結論
Transformers 5のgenerate_batch()は、長さの違う複数の入力を1つの固定batchとして最後まで待たせるのではなく、生成stepごとに完了したrequestを外して次を入れるcontinuous batching(連続バッチング)を扱えます。最初は性能調整をせず、3つのpromptをtokenizeし、返り値がrequest IDをkeyにした辞書であることと、3件すべての生成結果を取得できたことを確認します。
この機能はPaged Attentionを前提とし、実用的な確認には対応GPUと十分なGPU memoryが必要です。この記事はTransformers v5.14.1へ固定した公式資料ベースの手順であり、実機でmodelをdownload・実行した結果や速度値ではありません。
確認日時: 2026年8月4日 05:30(Asia/Tokyo)
固定した版: Transformers v5.14.1、commita08ace4(2026年7月16日公開)。continuous batching文書とAPI referenceは2026年8月4日に再監査
想定環境: Python 3.10以上、PyTorch 2.4以上、PyTorchから認識できるCUDA対応GPU、modelを格納できるdiskとGPU memory
検証区分: 公式documentationとreleaseを照合した机上調査です。Python例の構文だけを確認し、GPU実行、model取得、生成品質、latency、throughput、VRAM使用量は未検証です。
対象外: CPUだけの性能評価、Apple Silicon、複数GPU、HTTP serving、productionの負荷試験
連続バッチングで何が変わるか
通常の固定batchでは、同時に始めたrequestのうち最も長い生成が終わるまでbatchの構成を保ちます。短いrequestが先に終わっても、その位置を次のrequestへすぐ渡せません。連続バッチングではscheduler(どのrequestを次の計算へ入れるか決める仕組み)が生成stepごとに状態を確認し、完了したrequestを外して待機中のrequestを入れます。
固定batch: A ━━━━━━━ 完了
B ━━━━━━━━━━━━━ 完了 ← Aの終了後も構成を維持
連続batching: A ━━━━━━━ 完了
C ━━━━━━━ ← 空いた枠へ入る
B ━━━━━━━━━━━━━ 完了
Transformersの公式文書では、requestは待機、prefill、decode、完了の状態を進みます。prefillは入力promptを処理してKV cacheを作る段階、decodeは出力tokenを1つずつ生成する段階です。Paged AttentionはKV cacheを固定長blockで管理し、長さの違うrequestが同じmemory poolを使えるようにします。
generate_batch()はprompt一覧をまとめて渡し、内部のschedulingが終わるまで待って全結果を返す入口です。途中参加やstreamingを扱うserver用途ではContinuousBatchingManagerを直接使いますが、初回はlife cycleを自分で管理しなくてよいgenerate_batch()から始めます。
始める前の確認
Transformersの公式installation文書はPython 3.10以上、PyTorch 2.4以上を検証対象として案内しています。GPU driverやPyTorchのCUDA buildは環境ごとに適切な組み合わせが異なるため、この記事では新規install commandを一律に指定しません。既存の隔離された仮想環境で次を確認します。
python --version
python -c 'import torch, transformers; print(torch.__version__, transformers.__version__)'
python -c 'import torch; print(torch.cuda.is_available())'
期待する状態は、Pythonが3.10以上、Transformersが5.14.1、最後のcommandがTrueです。Falseならmodelを取得する前に止まり、PyTorch公式の環境別install手順へ戻ります。GPU名と空きmemoryもread-onlyで確認します。
nvidia-smi
例では公式のoptimization文書にも登場するQwen/Qwen3-0.6Bを使います。初回実行時はmodel fileを取得するため、必要なdisk容量、利用条件、組織のnetwork policyを先に確認してください。model名を変える場合は、architectureがcontinuous batchingとPaged Attentionを支えるか、必要memoryへ収まるかを別に確認します。
最短手順:3件をgenerate_batchへ渡す
次をcb_first_run.pyとして保存します。最初の確認では追加packageを必要としないPyTorch標準のSDPAを明示し、samplingを無効化します。max_batch_tokens=256は小さな確認用の上限であり、最適値ではありません。
import torch
from transformers import AutoModelForCausalLM, AutoTokenizer
from transformers.generation import ContinuousBatchingConfig, GenerationConfig
MODEL_ID = "Qwen/Qwen3-0.6B"
tokenizer = AutoTokenizer.from_pretrained(MODEL_ID)
model = AutoModelForCausalLM.from_pretrained(
MODEL_ID,
attn_implementation="paged|sdpa",
device_map="cuda",
dtype=torch.bfloat16,
)
prompts = [
"重力を一文で説明してください。",
"猫の品種を一つ挙げてください。",
"連続バッチングと固定バッチの違いを三文で説明してください。",
]
inputs = [tokenizer.encode(prompt) for prompt in prompts]
generation_config = GenerationConfig(
max_new_tokens=64,
eos_token_id=tokenizer.eos_token_id,
pad_token_id=tokenizer.pad_token_id,
do_sample=False,
)
batching_config = ContinuousBatchingConfig(
max_batch_tokens=256,
max_requests_per_batch=3,
use_cuda_graph=False,
use_async_batching=False,
)
outputs = model.generate_batch(
inputs=inputs,
generation_config=generation_config,
continuous_batching_config=batching_config,
progress_bar=True,
)
if len(outputs) != len(prompts):
raise RuntimeError(f"expected {len(prompts)} results, got {len(outputs)}")
for request_id, output in outputs.items():
text = tokenizer.decode(output.generated_tokens, skip_special_tokens=True)
print(f"[{request_id}] {text}")
実行は仮想環境内で行います。
python cb_first_run.py
device_map=“cuda”はmodelをCUDA deviceへ配置します。paged|sdpaはPaged AttentionとPyTorch SDPAを明示する指定です。公式文書ではFlashAttention経路の方が効率的になりやすいと説明されていますが、追加packageと対応条件が増えるため、最初の成功確認からは分離します。
成功をどう確認するか
最初の成功は「速くなった気がする」ではなく、次の4点で判定します。
- programがexceptionなしで終了する
- 結果の辞書にpromptと同じ3件が入る
- 各valueに
generated_tokensがあり、decodeできる - 出力をprompt順だと思い込まず、request IDと結果の組で扱う
generate_batch()はrequest IDからGenerationOutputへの辞書を返します。IDは入力配列のindexそのものとは限らないため、productionで元requestと結び付ける必要がある場合はContinuousBatchingManagerで自分のrequest_idを付ける設計へ進みます。
この1回では、固定batchより速いこと、GPU使用率が高いこと、3件が同時に処理されたことまでは証明できません。性能比較には入力長分布、同時到着、warm-up、測定区間を固定した別の負荷試験が必要です。
つまずきやすい点と戻し方
CUDAを認識しない
torch.cuda.is_available()がFalseなら、Transformersの設定値を変える前にPyTorch、driver、CUDA互換性へ戻ります。CPUへ自動fallbackさせて成功扱いにすると、GPU前提のmemoryとlatencyの判断が崩れます。
model loadでGPU memoryが足りない
OOM(out of memory)がmodel load中に出る場合、max_batch_tokensを下げてもmodel weight自体は小さくなりません。processを終了してGPU memoryを解放し、より小さい対応modelを選ぶか、別のGPU環境へ戻します。量子化を試す場合は別条件として記録し、未量子化の結果と混ぜません。
Paged Attention backendで止まる
errorにattention backendや未対応architectureが示されたら、paged|sdpaという文字列を推測で変更せず、利用中versionのContinuous batching公式ガイドとmodelの対応状況を確認します。FlashAttentionを追加するのは、SDPA経路の正しさを確認した後の別変更にします。
生成結果が空または途中で終わる
まずeos_token_id、pad_token_id、max_new_tokensを確認します。結果の内容が不適切でも、batchingの失敗とmodel品質の問題を混同しません。同じprompt、sampling無効、同じmodel revisionで再現するかを記録します。
初回だけ長くかかる
初回はmodel取得、weight load、kernel初期化などを含み得ます。2回目と単純比較せず、downloadを含む初回、load後のwarm-up、測定区間を分けます。CUDA graphsを有効にするとcapture時間と追加memoryも入るため、入門手順では明示的に無効化しています。
固定batchとの役割を分ける
連続バッチングは、長さや到着時刻が異なる複数requestをGPUへ流し続ける場面に向きます。入力が同じ長さで、全件を一括処理して終了する小さなoffline jobでは、固定batchの単純さが勝る場合があります。機能名だけで置き換えず、実際のworkloadで判断します。
llama.cppのserver側で同じ概念を調べる場合は、llama-serverの連続バッチング設定がparallel slotと共有KVの関係を扱っています。Transformers標準APIでmemory予算と測定軸まで決める場合は、Transformers連続バッチングのKV予算設計へ進んでください。
参考資料
- Hugging Face公式:Continuous batching(2026年8月4日確認)
- Hugging Face公式:Continuous batching API reference(2026年8月4日確認)
- Hugging Face公式:Installation(2026年8月4日確認)
- Hugging Face公式GitHub:Transformers v5.14.1(2026年7月16日公開、2026年8月4日確認)


