vLLM(推論エンジン)(ブイエルエルエム(スイロンエンジン))
vLLM(Virtual Large Language Model)とは、UC Berkeleyが開発したオープンソースのLLM推論・サービングエンジンである。PagedAttentionによる効率的なKVキャッシュ管理とContinuous Batchingを組み合わせることで、従来のHugging Face Transformersと比較して最大24倍のスループットを実現する。Llama、Mistral、Qwen、Gemma、Command R等の主要なオープンソースLLMに対応しており、プロダクション環境でのLLMサービングにおけるデファクトスタンダードとなっている。
vLLMとは
vLLM(Virtual Large Language Model)は、2023年にUC BerkeleyのSky Computing Labが発表したオープンソースのLLM推論・サービングエンジンである。同研究室が提案したPagedAttentionアルゴリズムを核心技術とし、KVキャッシュのメモリ管理を仮想メモリのページング機構に倣って効率化することで、GPU VRAMの利用効率を劇的に改善した。
vLLMが解決した根本的な問題は、LLM推論におけるKVキャッシュのメモリ断片化である。従来の推論フレームワークでは、各リクエストのKVキャッシュに最大シーケンス長分の連続メモリを事前に確保する必要があった。実際の生成長は最大長よりも短いことが多いため、確保したメモリの60〜80%が無駄になっていた。PagedAttentionはKVキャッシュを固定サイズのブロック(ページ)に分割し、必要に応じて動的にブロックを割り当てることで、この浪費を解消した。
vLLMはPython APIとOpenAI互換のHTTPサーバーの両方を提供しており、既存のOpenAI SDKを使ったアプリケーションからの移行が容易である。コマンド一つでサーバーを起動でき、エンドポイントのURLをvLLMサーバーに向けるだけで、アプリケーションコードの変更なしにローカル推論へ移行できる。
PagedAttentionの仕組み
PagedAttentionはvLLMの核心技術であり、OSの仮想メモリ管理からインスピレーションを得たKVキャッシュの管理手法である。
従来方式の問題
| 問題 | 説明 | 影響 |
|---|---|---|
| 事前割り当ての浪費 | 最大シーケンス長分のメモリを確保 | メモリ利用率20〜40% |
| 外部断片化 | 解放されたメモリが不連続 | 大きなバッチを構成不能 |
| 内部断片化 | 確保したブロック内の未使用領域 | メモリ使用量の増大 |
| コピーコスト | リクエスト間でのKVキャッシュ共有不可 | Beam Searchの効率低下 |
PagedAttentionの解決策
PagedAttentionでは、KVキャッシュを固定サイズのブロック(デフォルト16トークン分)に分割する。各リクエストはブロックテーブル(論理ブロック番号→物理ブロック番号のマッピング)を保持し、ブロックは物理メモリ上で非連続に配置される。
動作の流れは以下の通りである。
- 新規リクエストが到着すると、スケジューラはブロックテーブルを初期化する
- プリフィル処理で入力トークン分のブロックを割り当てる(例: 入力128トークン → 8ブロック)
- デコードの各ステップで新しいトークンが生成されると、現在のブロックに追加する
- ブロックが満杯になると、フリーリストから新しいブロックを取得して追加する
- 生成が完了すると、使用していたブロックをフリーリストに返却する
この方式により、メモリの外部断片化が完全に解消され、内部断片化はブロックの最終ブロック内の未使用領域のみに限定される。メモリ利用効率は90%以上に向上する。
Copy-on-Writeによるメモリ共有
PagedAttentionはCopy-on-Write(CoW)機構を実装しており、Beam SearchやParallel Samplingなどの複数の生成パスが同一の入力プレフィックスを共有する場合に、KVキャッシュブロックの物理コピーを回避する。各生成パスは同一の物理ブロックを参照し、書き込みが発生した時点でのみブロックの複製が行われる。これにより、Beam Search(ビーム幅4)のメモリ使用量は従来方式の約25%に削減される。
vLLMのアーキテクチャ
vLLMのアーキテクチャは以下の主要コンポーネントで構成される。
| コンポーネント | 役割 | 実装言語 |
|---|---|---|
| LLMEngine | 推論パイプラインの制御 | Python |
| Scheduler | Continuous Batchingのスケジューリング | Python |
| BlockManager | PagedAttentionのブロック管理 | Python |
| Worker | GPU上のモデル実行 | Python + CUDA |
| CacheEngine | KVキャッシュのGPU/CPU間転送 | Python + CUDA |
| ModelRunner | モデルのforward実行 | Python + PyTorch |
| APIServer | OpenAI互換HTTPサーバー | Python (FastAPI) |
LLMEngineが全体のオーケストレーションを行い、各デコードステップでSchedulerがバッチ構成を決定し、Workerがモデルのforward計算を実行する。Continuous Batchingのスケジューリングでは、Schedulerがwaiting(待機中)、running(実行中)、swapped(CPU退避中)の3つのキューを管理する。
分散推論ではRayまたはPyTorchの分散フレームワークを使用し、テンソル並列(各GPUがモデルの異なるアテンションヘッドを処理)とパイプライン並列(各GPUがモデルの異なるレイヤーを処理)の両方をサポートする。70B以上の大型モデルでは、4〜8台のGPUにテンソル並列で分散するのが一般的である。
vLLMと他のサービングエンジンの比較
主要なLLMサービングエンジンの特性を比較する。
| 特性 | vLLM | TGI | TensorRT-LLM | SGLang |
|---|---|---|---|---|
| 開発元 | UC Berkeley | Hugging Face | NVIDIA | Stanford |
| 実装言語 | Python + CUDA | Rust + Python | C++ + CUDA | Python + CUDA |
| KVキャッシュ | PagedAttention v2 | Paged KV Cache | Paged KV Cache | RadixAttention |
| 量子化 | AWQ/GPTQ/FP8/INT8/GGUF | AWQ/GPTQ/BitsAndBytes | FP8/INT4/SmoothQuant | AWQ/GPTQ/FP8 |
| マルチモーダル | 対応(LLaVA、Qwen-VL等) | 限定的 | 対応 | 対応 |
| 構造化出力 | Outlines統合 | Grammar-based | 限定的 | 高速実装 |
| Speculative Decoding | 対応 | 対応 | 対応 | 対応 |
| LoRAサービング | 動的LoRA切り替え | 限定的 | 限定的 | 対応 |
| API互換性 | OpenAI互換 | OpenAI互換 | Triton/OpenAI | OpenAI互換 |
| ライセンス | Apache 2.0 | Apache 2.0 | Apache 2.0 | Apache 2.0 |
vLLMの最大の強みは、広範なモデルサポートとOpenAI互換APIの充実度にある。Hugging Faceのモデルハブに公開されている主要モデルの大半をサポートしており、新しいモデルへの対応も迅速である。TGIはRust実装のルーターにより低レイテンシのリクエスト処理に優れる。TensorRT-LLMはNVIDIA GPU上での最高スループットを実現するが、セットアップの複雑さが課題である。SGLangはRadixAttentionによるプレフィックスキャッシュの効率的な再利用に優れ、マルチターンチャットやFew-shot推論で高い性能を示す。
vLLMの主要パラメータと設定
vLLMを本番環境で運用する際の重要な設定パラメータを整理する。
| パラメータ | 説明 | デフォルト | 推奨設定 |
|---|---|---|---|
| --model | 使用するモデル名 | - | Hugging Faceモデル名 |
| --tensor-parallel-size | テンソル並列GPU数 | 1 | モデルサイズに応じて設定 |
| --gpu-memory-utilization | GPU VRAM使用率上限 | 0.90 | 0.85〜0.95 |
| --max-model-len | 最大コンテキスト長 | モデル依存 | 必要最小限に設定 |
| --max-num-seqs | 最大同時シーケンス数 | 256 | SLA要件に応じて調整 |
| --max-num-batched-tokens | 1イテレーションの最大トークン数 | 自動 | プリフィル長に応じて設定 |
| --block-size | PagedAttentionのブロックサイズ | 16 | 16(変更は通常不要) |
| --swap-space | CPU退避メモリ(GB) | 4 | VRAM不足時に増加 |
| --quantization | 量子化方式 | なし | awq/gptq/fp8 |
| --enforce-eager | PyTorch eagerモード強制 | false | デバッグ時にtrue |
| --enable-chunked-prefill | チャンクドプリフィル有効化 | false | 長入力が多い場合にtrue |
gpu-memory-utilizationはOOM防止の安全弁であり、0.90がデフォルトだがKVキャッシュの動的な変動を考慮して0.85〜0.90に設定するのが安全である。max-model-lenはモデルの設計上のコンテキスト長(例: Llama 3.1は128K)よりも実際の使用に必要な長さに制限することで、KVキャッシュのメモリ消費を抑えてバッチサイズを増やせる。
よくある質問(FAQ)
Q1: vLLMはどのようなモデルに対応していますか?
vLLM v0.6以降は、Hugging Face Transformersのモデル形式に対応する主要なデコーダーモデルのほぼすべてをサポートしている。具体的にはLlama系(Llama 2/3/3.1、Code Llama)、Mistral系(Mistral、Mixtral MoE)、Qwen系(Qwen、Qwen2、Qwen2.5)、Gemma系(Gemma、Gemma 2)、Phi系(Phi-2、Phi-3)、Command R/R+、DeepSeek系、Yi、InternLM、Falcon、MPT等に対応している。マルチモーダルモデルもLLaVA、Qwen-VL、InternVL、Pixtral等をサポートしている。MoE(Mixture of Experts)モデルについてはMixtral 8x7B/8x22B、DBRX、DeepSeek-V2/V3等に対応しており、Expert Parallelismによる効率的な分散推論が可能である。GGUFフォーマットのモデルも読み込み可能であり、llama.cpp由来の量子化モデルを利用できる。
Q2: vLLMでの量子化モデルの使い方は?
vLLMは複数の量子化方式をサポートしている。AWQ量子化モデルは--quantization awqオプションで読み込める。GPTQ量子化モデルは--quantization gptqで指定する。FP8量子化はH100以降のGPUで利用可能で、--quantization fp8で有効化する。量子化によりモデルのVRAM使用量が削減され、同一GPUでより大きなバッチサイズを実現できる。例えばLlama 3.1 70BのAWQ 4bit量子化版は、FP16の約140GBに対して約35GBとなり、A100 80GB 1台で実行可能になる。ただし量子化による品質低下を事前に評価することが重要であり、パープレキシティの測定やタスク固有のベンチマークでFP16との差異を確認する必要がある。
Q3: vLLMのスケーラビリティの限界は?
vLLMのスケーラビリティはテンソル並列とパイプライン並列で確保されるが、いくつかの制約がある。テンソル並列は8GPU程度までが実用的で、それ以上はGPU間通信のオーバーヘッドが支配的になる。パイプライン並列を組み合わせることで数十GPU規模まで拡張可能だが、パイプラインバブル(ステージ間のアイドル時間)によりスケーリング効率が低下する。マルチノード構成ではRayを使用するが、ノード間の通信帯域(InfiniBand推奨)がボトルネックとなりやすい。極めて大規模な推論(数百GPU)では、TensorRT-LLMのほうがNVIDIA環境に最適化されており高い効率を示す場合がある。実用的には、70Bモデルを4〜8台のA100/H100で運用する構成が最もコストパフォーマンスに優れている。
Q4: vLLMとllama.cppの違いは何ですか?
vLLMはGPUを前提とした高スループット推論エンジンで、プロダクション環境での大規模サービングに最適化されている。llama.cppはCPU推論を主眼としたC++実装で、消費者向けハードウェア(ノートPC、デスクトップ)での個人利用に適している。vLLMはContinuous BatchingとPagedAttentionにより複数リクエストの同時処理に優れるが、GPU(最低16GB VRAM推奨)が必須である。llama.cppはGGUF量子化モデルをCPUのみで実行でき、Metal(macOS)やVulkanによるGPUオフロードにも対応しているが、バッチ処理のスループットはvLLMに大幅に劣る。用途で選択すべきであり、APIサーバーとして複数ユーザーにサービスする場合はvLLM、個人のローカル推論にはllama.cppが適している。