vLLMのValueError: max seq lenがKVキャッシュ容量を超える問題の修正

intermediate🧠 AI Tools2026-05-22| Linux (Ubuntu 20.04+)、Python 3.9+、vLLM 0.3.x〜0.5.x、NVIDIA GPU (CUDA 11.8+)

Error Message

ValueError: The model's max seq len (32768) is larger than the maximum number of tokens that can be stored in KV cache. Try increasing gpu_memory_utilization or decreasing max_model_len.
#vllm#llm#gpu#kv-cache

何が起きたか

vLLMを起動してモデル(Llama 3、Mistral、Qwenなど)を提供しようとしたところ、最初のリクエストを処理する前にクラッシュしました:

ValueError: The model's max seq len (32768) is larger than the maximum number of tokens that can be stored in KV cache. Try increasing gpu_memory_utilization or decreasing max_model_len.

これは推論の途中ではなく、起動時にクラッシュします。vLLMはGPUの空きメモリからKVキャッシュに収まるトークン数を計算し、それをmax_model_lenと比較します。1つの完全なシーケンスさえ収まらない場合、起動しません。

なぜこれが起きるか

vLLMは初期化時にKVキャッシュ用のGPUメモリを事前に割り当てます。使用可能なメモリ量は4つの要素で決まります:

  • GPU VRAMの総量 — 絶対的な上限
  • gpu_memory_utilization — vLLMが使用できるVRAMの割合(デフォルト:0.90)
  • モデルの重み — キャッシュのサイズ決定前にすでにロード済み
  • max_model_len — モデルがサポートする最大シーケンス長

重みが最初にロードされます。残ったVRAM(gpu_memory_utilizationを掛けた値)がKVキャッシュに割り当てられます。その残量がmax_model_lenトークンの1シーケンスも保持できない場合、このエラーが発生します。

典型的なシナリオ:24 GBのGPU上で32Kまたは128Kコンテキストのモデルを動かす場合、重みだけで18 GB以上消費します。もう1つのよくある原因は、vLLMが起動する前に古いJupyterカーネルや残留CUDAコンテキストがVRAMを占有しているケースです。

クイックフィックス — max_model_lenを減らす

ほとんどのワークロードは32Kトークンを使い切ることはありません。コンテキストを制限して先に進みましょう:

python -m vllm.entrypoints.openai.api_server \
  --model meta-llama/Meta-Llama-3-8B-Instruct \
  --max-model-len 8192

またはPython APIを使う場合:

from vllm import LLM

llm = LLM(
    model="meta-llama/Meta-Llama-3-8B-Instruct",
    max_model_len=8192
)

4096または8192から始めましょう — ほとんどのチャットアプリケーションには十分です。実際に収まる値がわかったら、より大きな値に調整できます。

代替フィックス — gpu_memory_utilizationを増やす

max_model_lenを縮小せずに長いコンテキストが必要ですか?GPUからより多くを引き出しましょう:

python -m vllm.entrypoints.openai.api_server \
  --model meta-llama/Meta-Llama-3-8B-Instruct \
  --gpu-memory-utilization 0.95

0.95を超えないようにしてください。推論はアクティベーションにもメモリが必要です — それ以上にするとリクエスト途中でOOMエラーが発生し、クリーンな起動失敗よりも深刻です。0.95を実質的な上限として扱ってください。

恒久的な解決策 — 起動前にVRAMを解放する

nvidia-smiを実行して、vLLMを起動する前にGPUを占有しているプロセスを確認しましょう:

nvidia-smi

VRAMを占有しているプロセス(Jupyterカーネル、別のモデルサーバー、ゾンビCUDAコンテキストなど)を見つけたら、まずそれを終了させましょう:

# nvidia-smiの出力からPIDを確認する
kill -9 <PID>

# またはGPU上のすべてのPythonプロセスをクリア(慎重に使用すること)
fuser -k /dev/nvidia*

クリーンなGPUでvLLMを再起動してください。他のプロセスがメモリを競合していなければ、デフォルトのgpu_memory_utilization=0.90で通常は十分です。

マルチGPUオプション

テンソル並列処理を使って複数のGPUに負荷を分散させましょう:

python -m vllm.entrypoints.openai.api_server \
  --model meta-llama/Meta-Llama-3-70B-Instruct \
  --tensor-parallel-size 2 \
  --max-model-len 32768

2つのGPUを使うと、KVキャッシュに使えるVRAMがほぼ2倍になります。これにより、1つのGPUでは処理できない70Bモデルでも32Kの全コンテキストを実行できるようになります。

環境に適したmax_model_lenの見つけ方

普遍的に機能する計算式はありません — 推測より二分探索の方が速いです。4096から始めて、エラーになるまで倍にしていきましょう:

# 徐々に増加するコンテキスト長でテストする
for LEN in 4096 8192 16384 32768; do
  echo "Testing max_model_len=$LEN"
  python -c "
from vllm import LLM
try:
    llm = LLM('meta-llama/Meta-Llama-3-8B-Instruct', max_model_len=$LEN)
    print('OK: $LEN works')
except ValueError as e:
    print('FAIL:', e)
" 2>&1 | grep -E 'OK|FAIL'
done

OKと表示される最大の値が、そのGPU/モデルの組み合わせにおける上限です。メモしておきましょう — 別のモデルをロードしたり、マシンに別のプロセスを追加したりすると変わります。

修正の確認

正常に起動すると、KVキャッシュの割り当てがログに記録されます — GPUブロック数の行を確認してください:

INFO:     # GPU blocks: 1234, # CPU blocks: 512
INFO:     Avg prompt throughput: 0.0 tokens/s, ...
INFO:     Application startup complete.

各ブロックはデフォルトで16トークンを保持します。つまり1234ブロック × 16 = 19,744トークンの実際のキャパシティです。この数値はmax_model_len以上でなければならず、そうでなければ起動を通過できなかったはずです。

推論が実際にエンドツーエンドで動作することを確認しましょう:

curl http://localhost:8000/v1/completions \
  -H "Content-Type: application/json" \
  -d '{
    "model": "meta-llama/Meta-Llama-3-8B-Instruct",
    "prompt": "Hello, world!",
    "max_tokens": 50
  }'

まとめ

  • 最速の修正:起動コマンドに--max-model-len 8192(またはそれ以下)を追加する
  • より長いコンテキストが必要?まず--gpu-memory-utilization 0.95を試し、次にVRAMをクリアする
  • VRAMが少ない環境での大規模モデル:複数のGPUで--tensor-parallel-size 2を使用する
  • vLLMを起動する前に必ずnvidia-smiを実行すること — 残留プロセスは時間の無駄になる

Related Error Notes