- Authors
- Name
- はじめに
- vLLMコアアーキテクチャ
- コア最適化手法の詳細
- 詳細設定ガイド
- 性能比較:vLLM vs 競合フレームワーク
- デプロイパターン
- モニタリング戦略
- よく発生する問題と解決方法
- 高度な最適化ティップス
- FAQ
- vLLMとOllamaの違いは何ですか?
- vLLMはどのGPUで動作しますか?
- gpu-memory-utilizationを1.0に設定してはいけないのですか?
- Tensor ParallelismとPipeline Parallelismの違いは何ですか?
- Speculative Decodingは常に速いですか?
- vLLMでストリーミングレスポンスを使用すべきですか?
- 参考資料
- まとめ
はじめに
LLMをプロダクション環境でサービングすることは、単にモデルをロードしてAPIを公開するだけに留まらない複雑なエンジニアリング課題です。GPUメモリ管理、同時リクエスト処理、レイテンシ最適化、コスト効率性まで考慮しなければならない多次元的な問題です。
vLLMはUC BerkeleyのSky Computing Labが開発した高性能LLMサービングエンジンで、革新的なPagedAttentionアルゴリズムを核心としています。2023年の初公開以降、急速に業界標準レベルのサービングフレームワークとして定着し、現在多くの企業や研究機関でプロダクションに活用されています。
本記事では、vLLMのアーキテクチャとコア最適化手法、詳細設定ガイド、競合フレームワークとの比較、Kubernetesデプロイパターン、モニタリング戦略、そして実務でよく遭遇する問題と解決方法まで包括的に解説します。
vLLMコアアーキテクチャ
PagedAttentionとは
vLLMの最も革新的な貢献はPagedAttentionです。OSの仮想メモリ管理からインスピレーションを得て、KV Cacheを固定サイズのブロック(ページ)に分割し、非連続メモリ空間に保存します。
従来方式の問題点:
従来のLLMサービング(HuggingFace Transformersなど):
├─ 各リクエストに最大シーケンス長分の連続メモリを事前割り当て
├─ 実際のシーケンスが短くても最大長のメモリを占有 → 内部フラグメンテーション
├─ リクエスト間のメモリ共有不可 → 外部フラグメンテーション
└─ 結果:GPUメモリの60〜80%が無駄に
PagedAttentionの解決方式:
vLLM PagedAttention:
├─ KV Cacheを固定サイズブロック(例:16トークン)に分割
├─ ブロックは非連続メモリに保存可能
├─ 必要時にブロックを動的に割り当て/解放
├─ ブロックテーブルで論理→物理マッピングを管理
└─ 結果:GPUメモリの無駄を5%未満に削減
# PagedAttentionのブロックテーブル概念
# Logical Block → Physical Block マッピング
# Request 1: "The cat sat on the mat"
# Logical: [Block 0] [Block 1]
# Physical: [GPU Block 3] [GPU Block 7]
# Request 2: "Hello world"
# Logical: [Block 0]
# Physical: [GPU Block 1]
# システムプロンプトが同一の場合のCopy-on-Write:
# Request 3とRequest 4が同じシステムプロンプトを使用
# → システムプロンプトの物理ブロックを共有(追加メモリ消費なし)
Continuous Batching(連続バッチング)
従来の静的バッチング(static batching)では、バッチ内の最長シーケンスが完了するまで全リクエストが待機します。vLLMのContinuous Batchingはこの非効率を解消します。
静的バッチング(Static Batching):
Time →
Req A: [████████████████████] ← 生成完了
Req B: [████████] ← 早く終わったがAを待つ
Req C: [████████████] ← Bより長いがAを待つ
↑ バッチ開始 ↑ バッチ終了(A完了時点)
Continuous Batching:
Time →
Req A: [████████████████████]
Req B: [████████] → Req Dが即座に開始: [████████████]
Req C: [████████████] → Req Eが即座に開始: [██████]
↑ リクエストが終わると即座に新しいリクエストでスロット交換
効果:同じGPUでスループットが2〜5倍向上します。
全体アーキテクチャ概要
┌─────────────────────────────────────────────┐
│ vLLM Engine │
├─────────────────────────────────────────────┤
│ API Server (OpenAI Compatible) │
│ ├─ /v1/completions │
│ ├─ /v1/chat/completions │
│ └─ /v1/embeddings │
├─────────────────────────────────────────────┤
│ Scheduler │
│ ├─ Continuous Batching │
│ ├─ Priority Queue │
│ └─ Preemption (Swap/Recompute) │
├─────────────────────────────────────────────┤
│ KV Cache Manager (PagedAttention) │
│ ├─ Block Allocator │
│ ├─ Block Table │
│ └─ Copy-on-Write │
├─────────────────────────────────────────────┤
│ Model Executor │
│ ├─ Tensor Parallelism (Ray/NCCL) │
│ ├─ Quantization (GPTQ/AWQ/FP8) │
│ └─ Speculative Decoding │
└─────────────────────────────────────────────┘
コア最適化手法の詳細
Tensor Parallelism(テンソル並列化)
1つのモデルを複数のGPUに分散して実行します。vLLMはMegatron-LMスタイルのテンソル並列化をサポートしています。
# 単一GPU(デフォルト)
python -m vllm.entrypoints.openai.api_server \
--model meta-llama/Llama-3.1-70B-Instruct \
--tensor-parallel-size 1
# 4 GPUテンソル並列化
python -m vllm.entrypoints.openai.api_server \
--model meta-llama/Llama-3.1-70B-Instruct \
--tensor-parallel-size 4
# 8 GPU(A100 80GB x 8ノード)
python -m vllm.entrypoints.openai.api_server \
--model meta-llama/Llama-3.1-405B-Instruct \
--tensor-parallel-size 8 \
--pipeline-parallel-size 1
テンソル並列化サイズ決定ガイド:
| モデルサイズ | 量子化なし(FP16) | INT8量子化 | INT4量子化 |
|---|---|---|---|
| 7B | 1x A100 80GB | 1x A100 40GB | 1x RTX 4090 |
| 13B | 1x A100 80GB | 1x A100 80GB | 1x A100 40GB |
| 34B | 2x A100 80GB | 1x A100 80GB | 1x A100 80GB |
| 70B | 4x A100 80GB | 2x A100 80GB | 1〜2x A100 80GB |
| 405B | 8x A100 80GB | 4〜8x A100 80GB | 4x A100 80GB |
Speculative Decoding(投機的デコーディング)
小さな「ドラフトモデル」が複数のトークンを高速に推測生成し、大きな「ターゲットモデル」が1回のフォワードパスでそれを検証します。
# Speculative Decodingの有効化
python -m vllm.entrypoints.openai.api_server \
--model meta-llama/Llama-3.1-70B-Instruct \
--speculative-model meta-llama/Llama-3.2-1B-Instruct \
--num-speculative-tokens 5 \
--speculative-draft-tensor-parallel-size 1
動作原理:
従来の自己回帰生成(1トークン/ステップ):
Step 1 → "The"
Step 2 → "weather"
Step 3 → "is"
Step 4 → "sunny"
Step 5 → "today"
= 5回のフォワードパス(大規模モデル)
Speculative Decoding:
ドラフトモデル(高速小型モデル): "The weather is sunny today"(5トークン推測)
ターゲットモデル(1回のフォワードパス): "The weather is sunny today" ✓ 全て承認!
= 1回のフォワードパス(小型モデル) + 1回のフォワードパス(大規模モデル)
→ 潜在的に2.5〜3倍の速度向上
適切なシナリオ:
- GPUがcompute-boundの環境(バッチサイズが小さい場合)
- ドラフトモデルとターゲットモデルのトークナイザーが互換性がある場合
- 承認率が高い場合(一般的なテキスト生成)
Prefix Caching(プレフィックスキャッシング)
同一のシステムプロンプトやプレフィックスを持つリクエスト間でKV Cacheを再利用します。
# Prefix Cachingの有効化
python -m vllm.entrypoints.openai.api_server \
--model meta-llama/Llama-3.1-8B-Instruct \
--enable-prefix-caching
効果:
シナリオ:全リクエストが同一の2000トークンシステムプロンプトを使用
Prefix Caching無効:
Req 1: [システムプロンプト2000トークン処理] + [ユーザー入力処理] → TTFT: 500ms
Req 2: [システムプロンプト2000トークン再処理] + [ユーザー入力処理] → TTFT: 500ms
Req 3: [システムプロンプト2000トークン再処理] + [ユーザー入力処理] → TTFT: 500ms
Prefix Caching有効:
Req 1: [システムプロンプト2000トークン処理] + [ユーザー入力処理] → TTFT: 500ms
Req 2: [キャッシュヒット!] + [ユーザー入力処理] → TTFT: 50ms(10倍改善!)
Req 3: [キャッシュヒット!] + [ユーザー入力処理] → TTFT: 50ms
Chunked Prefill
長いプロンプトのPrefillステージをチャンクに分割し、デコーディングとインターリーブします。これにより、長いプロンプトが入っても既存のデコーディング中のリクエストのTBTが急増しません。
# Chunked Prefillの有効化
python -m vllm.entrypoints.openai.api_server \
--model meta-llama/Llama-3.1-8B-Instruct \
--enable-chunked-prefill \
--max-num-batched-tokens 2048
詳細設定ガイド
コア設定パラメータ
python -m vllm.entrypoints.openai.api_server \
--model meta-llama/Llama-3.1-8B-Instruct \
\
# GPUメモリ設定
--gpu-memory-utilization 0.90 \ # GPUメモリ使用比率(0.0〜1.0)
--max-model-len 32768 \ # 最大コンテキスト長
\
# バッチおよび同時実行設定
--max-num-seqs 256 \ # 同時処理最大シーケンス数
--max-num-batched-tokens 32768 \ # バッチあたり最大トークン数
\
# 並列化設定
--tensor-parallel-size 1 \ # テンソル並列GPU数
--pipeline-parallel-size 1 \ # パイプライン並列ステージ数
\
# 量子化設定
--quantization awq \ # 量子化方式(awq, gptq, fp8など)
--dtype auto \ # データ型(auto, float16, bfloat16)
\
# サーバー設定
--host 0.0.0.0 \
--port 8000 \
--api-key "your-secret-key"
設定パラメータ詳細説明
| パラメータ | デフォルト | 説明 | 推奨範囲 |
|---|---|---|---|
--gpu-memory-utilization | 0.9 | KV Cacheに割り当てるGPUメモリ比率 | 0.85〜0.95 |
--max-model-len | モデル設定値 | 処理可能な最大シーケンス長 | タスクに応じて調整 |
--max-num-seqs | 256 | 同時処理可能な最大シーケンス数 | 64〜512 |
--max-num-batched-tokens | なし | 1回のiterationで処理する最大トークン数 | 2048〜65536 |
--tensor-parallel-size | 1 | テンソル並列化に使用するGPU数 | 1, 2, 4, 8 |
--block-size | 16 | PagedAttentionブロックサイズ(トークン数) | 8, 16, 32 |
--swap-space | 4 | CPUスワップ空間(GB) | 4〜16 |
--enforce-eager | False | CUDAグラフの代わりにEagerモードを使用 | デバッグ時True |
シナリオ別設定例
高スループット最適化:
python -m vllm.entrypoints.openai.api_server \
--model meta-llama/Llama-3.1-8B-Instruct \
--gpu-memory-utilization 0.95 \
--max-num-seqs 512 \
--max-model-len 4096 \
--enable-prefix-caching \
--enable-chunked-prefill
低レイテンシ最適化:
python -m vllm.entrypoints.openai.api_server \
--model meta-llama/Llama-3.1-8B-Instruct \
--gpu-memory-utilization 0.85 \
--max-num-seqs 32 \
--max-model-len 8192 \
--num-scheduler-steps 1
ロングコンテキスト最適化:
python -m vllm.entrypoints.openai.api_server \
--model meta-llama/Llama-3.1-8B-Instruct \
--gpu-memory-utilization 0.92 \
--max-num-seqs 16 \
--max-model-len 131072 \
--enable-chunked-prefill \
--max-num-batched-tokens 4096
性能比較:vLLM vs 競合フレームワーク
主要LLMサービングフレームワーク比較
| 特性 | vLLM | TGI (HuggingFace) | TensorRT-LLM (NVIDIA) | Triton + TensorRT-LLM |
|---|---|---|---|---|
| 開発元 | UC Berkeley | HuggingFace | NVIDIA | NVIDIA |
| コア技術 | PagedAttention | Continuous Batching | FasterTransformerベース | モデルサービングフレームワーク |
| インストール難易度 | 非常に簡単 | 簡単 | 難しい | 非常に難しい |
| モデル互換性 | 非常に広い | 広い | 制限あり(変換必要) | 制限あり |
| API互換性 | OpenAI互換 | 独自 + OpenAI互換 | 独自API | gRPC + HTTP |
| 量子化サポート | GPTQ, AWQ, FP8, GGUF | GPTQ, AWQ, EETQ | FP8, INT8, INT4 | FP8, INT8, INT4 |
| マルチGPU | Tensor/Pipeline | Tensor | Tensor/Pipeline | Tensor/Pipeline |
| Speculative Decoding | 対応 | 対応 | 対応 | 対応 |
| プロダクション安定性 | 高い | 高い | 非常に高い | 非常に高い |
| コミュニティ | 非常に活発 | 活発 | NVIDIA主導 | NVIDIA主導 |
スループットベンチマーク(LLaMA-3.1-8B、A100 80GB基準)
| メトリック | vLLM | TGI | TensorRT-LLM |
|---|---|---|---|
| スループット (tokens/s) - batch=1 | 約120 | 約100 | 約150 |
| スループット (tokens/s) - batch=32 | 約2,800 | 約2,200 | 約3,500 |
| スループット (tokens/s) - batch=128 | 約5,500 | 約4,000 | 約7,000 |
| TTFT (ms) - 512トークン入力 | 約35 | 約40 | 約25 |
| TBT (ms) - batch=1 | 約8 | 約10 | 約6 |
| メモリ効率性 | 95%以上 | 約80% | 約90% |
注:ベンチマーク結果はハードウェア、モデル、設定によって大きく異なる可能性があります。上記の数値は参考用の概算比較です。
フレームワーク選択ガイド
素早く始めたい場合?
→ vLLM(pip install vllm → すぐにサービング)
最大性能が必要な場合?
→ TensorRT-LLM(ただしモデル変換と設定に相当な労力が必要)
HuggingFaceエコシステムを既に使用中の場合?
→ TGI(HuggingFace Hubとの自然な統合)
エンタープライズデプロイが必要な場合?
→ Triton + TensorRT-LLM(NVIDIA公式サポート、マルチモデルサービング)
デプロイパターン
単一GPUデプロイ
最もシンプルな形態で、小規模モデルのサービングに適しています。
# Dockerで単一GPUデプロイ
docker run --runtime nvidia --gpus '"device=0"' \
-v /path/to/model:/model \
-p 8000:8000 \
vllm/vllm-openai:latest \
--model /model \
--gpu-memory-utilization 0.9 \
--max-model-len 8192
マルチGPUデプロイ
# 4 GPUテンソル並列デプロイ
docker run --runtime nvidia --gpus '"device=0,1,2,3"' \
-v /path/to/model:/model \
-p 8000:8000 \
vllm/vllm-openai:latest \
--model /model \
--tensor-parallel-size 4 \
--gpu-memory-utilization 0.9
Kubernetes + Rayデプロイ
# vllm-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: vllm-serving
namespace: ml-serving
spec:
replicas: 2
selector:
matchLabels:
app: vllm-serving
template:
metadata:
labels:
app: vllm-serving
spec:
containers:
- name: vllm
image: vllm/vllm-openai:latest
args:
- '--model'
- 'meta-llama/Llama-3.1-8B-Instruct'
- '--gpu-memory-utilization'
- '0.9'
- '--max-model-len'
- '8192'
- '--max-num-seqs'
- '256'
- '--enable-prefix-caching'
- '--port'
- '8000'
ports:
- containerPort: 8000
name: http
resources:
limits:
nvidia.com/gpu: 1
memory: '32Gi'
cpu: '8'
requests:
nvidia.com/gpu: 1
memory: '16Gi'
cpu: '4'
readinessProbe:
httpGet:
path: /health
port: 8000
initialDelaySeconds: 120
periodSeconds: 10
livenessProbe:
httpGet:
path: /health
port: 8000
initialDelaySeconds: 180
periodSeconds: 30
env:
- name: VLLM_USAGE_SOURCE
value: 'production'
---
apiVersion: v1
kind: Service
metadata:
name: vllm-service
namespace: ml-serving
spec:
selector:
app: vllm-serving
ports:
- port: 80
targetPort: 8000
name: http
type: ClusterIP
---
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: vllm-hpa
namespace: ml-serving
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: vllm-serving
minReplicas: 2
maxReplicas: 8
metrics:
- type: Pods
pods:
metric:
name: gpu_utilization
target:
type: AverageValue
averageValue: '80'
マルチモデルサービングパターン
# 複数モデルを同一クラスタでサービングする場合
# 各モデルに対して別々のvLLMインスタンス + 前段にルーターを配置
# router.py(簡単な例)
from fastapi import FastAPI, Request
import httpx
app = FastAPI()
MODEL_ENDPOINTS = {
"llama-8b": "http://vllm-8b:8000",
"llama-70b": "http://vllm-70b:8000",
"codellama-34b": "http://vllm-code:8000",
}
@app.post("/v1/chat/completions")
async def route_request(request: Request):
body = await request.json()
model = body.get("model", "llama-8b")
endpoint = MODEL_ENDPOINTS.get(model)
async with httpx.AsyncClient() as client:
response = await client.post(
f"{endpoint}/v1/chat/completions",
json=body,
timeout=120.0
)
return response.json()
モニタリング戦略
コアメトリック定義
LLMサービングの性能を測定するコア指標は以下の通りです:
| メトリック | 説明 | 目標範囲 |
|---|---|---|
| TTFT(Time to First Token) | 最初のトークン生成までの時間 | < 200ms(対話型) |
| TBT(Time Between Tokens) | トークン間生成時間(= Inter-Token Latency) | < 30ms |
| E2E Latency | 全リクエスト処理時間 | タスク依存 |
| Throughput | 秒あたり生成トークン数(tokens/s) | モデル/GPU依存 |
| GPU Utilization | GPU演算ユニット使用率 | 70〜95% |
| KV Cache Usage | KV Cacheメモリ使用率 | < 95% |
| Queue Depth | 待機中のリクエスト数 | < max_num_seqs |
| Request Success Rate | リクエスト成功率 | > 99.5% |
Prometheus + Grafanaモニタリング
vLLMはデフォルトでPrometheusメトリックを/metricsエンドポイントで公開します。
# 主要Prometheusメトリック
# vllm:num_requests_running - 現在処理中のリクエスト数
# vllm:num_requests_waiting - 待機中のリクエスト数
# vllm:gpu_cache_usage_perc - KV Cache GPU使用率
# vllm:cpu_cache_usage_perc - KV Cache CPUスワップ使用率
# vllm:avg_prompt_throughput_toks_per_s - プロンプト処理スループット
# vllm:avg_generation_throughput_toks_per_s - 生成スループット
# vllm:e2e_request_latency_seconds - E2Eリクエストレイテンシヒストグラム
# vllm:time_to_first_token_seconds - TTFTヒストグラム
# vllm:time_per_output_token_seconds - TBTヒストグラム
# prometheus-scrape-config.yaml
scrape_configs:
- job_name: 'vllm'
scrape_interval: 15s
static_configs:
- targets: ['vllm-service:8000']
metrics_path: '/metrics'
アラートルール例
# prometheus-alert-rules.yaml
groups:
- name: vllm_alerts
rules:
- alert: HighKVCacheUsage
expr: vllm_gpu_cache_usage_perc > 0.95
for: 5m
labels:
severity: warning
annotations:
summary: 'KV Cache使用率が95%を超えました'
- alert: HighRequestLatency
expr: histogram_quantile(0.99, vllm_e2e_request_latency_seconds_bucket) > 30
for: 5m
labels:
severity: critical
annotations:
summary: 'P99リクエストレイテンシが30秒を超えました'
- alert: HighQueueDepth
expr: vllm_num_requests_waiting > 100
for: 2m
labels:
severity: warning
annotations:
summary: '待機中のリクエストが100件を超えました'
よく発生する問題と解決方法
OOM(Out of Memory)エラー
症状:CUDA out of memoryエラーが発生
原因と解決策:
# 1. gpu-memory-utilizationを下げる
--gpu-memory-utilization 0.80 # デフォルト0.9から下げる
# 2. max-model-lenを減らす
--max-model-len 4096 # 不必要に長いコンテキストを制限
# 3. max-num-seqsを減らす
--max-num-seqs 64 # 同時処理数を減少
# 4. 量子化を適用
--quantization awq # またはgptq, fp8
# 5. テンソル並列化(GPU追加)
--tensor-parallel-size 2
遅い最初のトークン(Slow TTFT)
症状:TTFTが異常に高い(数秒以上)
原因と解決策:
# 1. 長いプロンプト → Chunked Prefillを有効化
--enable-chunked-prefill
--max-num-batched-tokens 2048
# 2. Prefix Cachingを有効化(繰り返しプロンプトがある場合)
--enable-prefix-caching
# 3. CUDAグラフ最適化を確認
# --enforce-eagerを削除(CUDAグラフを有効化)
# 4. モデルロードの最適化
--load-format auto # 可能な場合safetensorsを使用
スループット低下
症状:tokens/sが期待値より低い
チェックリスト:
# 1. バッチサイズを確認
--max-num-seqs 256 # 小さすぎるとGPU活用率が低下
# 2. メモリ使用率を確認
--gpu-memory-utilization 0.92 # 保守的すぎるとバッチサイズが制限
# 3. Speculative Decodingを試行
--speculative-model <small-model> --num-speculative-tokens 5
# 4. 量子化を適用
--quantization awq # またはfp8(A100/H100)
リクエストタイムアウト
症状:一部のリクエストがタイムアウトで失敗
# 1. 最大トークン数を制限
# APIリクエスト時にmax_tokensを適切に設定
# 2. スワップ空間を確保
--swap-space 16 # CPUメモリへのスワップを許可
# 3. プリエンプション戦略を設定
--preemption-mode recompute # またはswap
高度な最適化ティップス
FP8量子化(H100/A100)
# NVIDIA H100でFP8量子化を活用
python -m vllm.entrypoints.openai.api_server \
--model meta-llama/Llama-3.1-70B-Instruct \
--quantization fp8 \
--tensor-parallel-size 4 \
--gpu-memory-utilization 0.92
# FP8はINT8と比較して:
# - より高い精度(FP範囲を維持)
# - H100 FP8 Tensor Coreの活用で最大性能
# - 別途キャリブレーション不要
マルチLoRAサービング
# ベースモデル + 複数LoRAアダプターの同時サービング
python -m vllm.entrypoints.openai.api_server \
--model meta-llama/Llama-3.1-8B-Instruct \
--enable-lora \
--lora-modules \
korean-chat=/path/to/korean-lora \
code-assist=/path/to/code-lora \
medical-qa=/path/to/medical-lora \
--max-loras 3 \
--max-lora-rank 64
ベンチマークツール
# vLLM内蔵ベンチマークツール
python -m vllm.entrypoints.openai.api_server \
--model meta-llama/Llama-3.1-8B-Instruct &
# スループットベンチマーク
python -m vllm.benchmark_throughput \
--model meta-llama/Llama-3.1-8B-Instruct \
--input-len 512 \
--output-len 128 \
--num-prompts 1000
# レイテンシベンチマーク
python -m vllm.benchmark_latency \
--model meta-llama/Llama-3.1-8B-Instruct \
--input-len 512 \
--output-len 128 \
--batch-size 1
FAQ
vLLMとOllamaの違いは何ですか?
Ollamaはローカル開発と実験のための便利なツールで、vLLMはプロダクションレベルのサービングのための高性能エンジンです。Ollamaはインストールと使用が非常に簡単ですが、PagedAttentionやContinuous Batchingのような高度な最適化を提供しません。プロダクショントラフィックを処理する必要がある場合はvLLMを推奨します。
vLLMはどのGPUで動作しますか?
vLLMはCUDA対応のNVIDIA GPUで動作します。A100、H100が最適で、RTX 3090/4090でも使用可能です。AMD GPU(ROCm)も実験的にサポートされています。最小要件はモデルサイズと量子化レベルによって異なります。
gpu-memory-utilizationを1.0に設定してはいけないのですか?
推奨しません。GPUにはKV Cache以外にもCUDAカーネル、cuBLASワークスペース、一時テンソルなどのメモリが必要です。0.9〜0.95が大半のケースで安全な上限であり、1.0に設定するとOOMが頻発します。
Tensor ParallelismとPipeline Parallelismの違いは何ですか?
Tensor Parallelism(TP)は1つのレイヤーを複数のGPUに分割して並列処理します。レイヤー間通信が必要なため、GPU間の高速インターコネクト(NVLink)が重要です。Pipeline Parallelism(PP)はレイヤーグループを各GPUに割り当てます。通信要件は少ないですが、「パイプラインバブル」による非効率があります。一般的に、単一ノード内ではTPを、ノード間ではPPを使用します。
Speculative Decodingは常に速いですか?
いいえ。Speculative Decodingはバッチサイズが小さくGPUがcompute-boundの場合に最も効果的です。バッチサイズが大きい場合、ドラフトモデルのオーバーヘッドが利点を相殺する可能性があります。また、ドラフトモデルの承認率が低い場合(特殊ドメイン、コード生成など)は性能向上が限定的です。
vLLMでストリーミングレスポンスを使用すべきですか?
大半のケースで推奨します。ストリーミングはユーザーの体感レイテンシを大幅に削減します。OpenAI互換APIでstream=trueに設定すると、SSE(Server-Sent Events)でトークンをリアルタイム配信します。ただし、ストリーミングレスポンスの完全性検証とエラー処理ロジックが追加で必要です。
参考資料
- Kwon, W. et al. (2023). "Efficient Memory Management for Large Language Model Serving with PagedAttention." arXiv:2309.06180
- vLLM Project. "vLLM: Easy, Fast, and Cheap LLM Serving." GitHub Repository
- vLLM Documentation. Official Docs
- Leviathan, Y. et al. (2023). "Fast Inference from Transformers via Speculative Decoding." arXiv:2211.17192
- NVIDIA. "TensorRT-LLM." GitHub Repository
- HuggingFace. "Text Generation Inference (TGI)." GitHub Repository
- Zheng, L. et al. (2023). "Efficiently Programming Large Language Models using SGLang." arXiv:2312.07104
- Agrawal, A. et al. (2024). "Taming Throughput-Latency Tradeoff in LLM Inference with Sarathi-Serve." arXiv:2403.02310
- Anyscale. "Ray Serve for LLM Serving." Documentation
- Kubernetes. "GPU Scheduling." Documentation
まとめ
vLLMはLLMプロダクションサービングのデファクトスタンダードとして定着し、速い開発ペースと活発なコミュニティのおかげで機能が継続的に拡張されています。
要点まとめ:
- PagedAttentionはメモリ効率のゲームチェンジャーです。KV Cacheの無駄を5%未満に削減し、同じハードウェアではるかに多くの同時リクエストを処理します。
- Continuous Batchingでスループットを劇的に改善します。静的バッチング比で2〜5倍向上します。
- 設定最適化が性能の鍵です。
gpu-memory-utilization、max-model-len、max-num-seqsの適切な組み合わせが重要です。 - Prefix CachingとSpeculative Decodingはシナリオに応じて追加の性能向上を提供します。
- モニタリングは必須です。TTFT、TBT、スループット、KV Cache使用率を継続的に追跡する必要があります。
- Kubernetesデプロイ時はGPUリソース管理とオートスケーリング戦略を慎重に設計する必要があります。
フレームワーク選択時、vLLMは「素早い立ち上げ + 高性能 + 広い互換性」のバランスが最も優れており、特別な理由がなければ第一選択として推奨します。