何が起きたか
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を実行すること — 残留プロセスは時間の無駄になる

