LLMサービングの効率を劇的に向上させるvLLMの魅力に迫る!
1. はじめに:LLM推論の課題とvLLMの登場
近年、大規模言語モデル(LLM)は目覚ましい発展を遂げ、自然言語処理の分野に革命をもたらしました。しかし、その巨大なモデルサイズと計算量は、推論(テキスト生成など)を実行する際に大きな課題となります。特に、多くのユーザーにサービスを提供する場合、GPUメモリの制約と処理速度の遅延が深刻な問題となります。😥
従来のLLM推論ライブラリ、例えばHugging Face Transformersなどは、広く使われていますが、特に同時リクエスト数が多い場合や長いシーケンスを扱う場合に、メモリ効率やスループットの点で限界がありました。
vLLMの主な目的は、LLMの推論プロセスにおけるボトルネックを解消し、高スループットと効率的なメモリ管理を実現することです。これにより、より多くのリクエストを同時に、かつ高速に処理することが可能になり、LLMを活用したアプリケーションの応答性やスケーラビリティが大幅に向上します。✨
2. コア技術:PagedAttentionとは?🤔
vLLMの高速性とメモリ効率の鍵を握るのが、PagedAttentionという革新的なアルゴリズムです。これは、従来のAttentionメカニズムにおけるKVキャッシュ管理の問題点を解決するために考案されました。
従来のAttentionメカニズムの課題
TransformerベースのLLMでは、Attentionメカニズムが重要な役割を果たします。推論時には、過去のトークンのAttention Key(K)とValue(V)を計算し、「KVキャッシュ」としてGPUメモリに保存します。これにより、次のトークンを生成する際に再計算の手間を省き、処理を高速化します。
しかし、従来のKVキャッシュ管理には以下のような問題がありました:
- メモリの浪費: KVキャッシュはシーケンス長に応じて増加しますが、最大シーケンス長を想定して事前に大きなメモリ領域を確保するため、短いシーケンスでは多くのメモリが無駄になります。
- メモリ断片化 (Fragmentation): KVキャッシュは連続したメモリ領域を必要としますが、リクエストの処理と解放が繰り返されるうちに、利用可能なメモリが細切れ(断片化)になり、大きなキャッシュを確保できなくなる問題(外部断片化)が発生します。また、確保したブロック内での未使用部分(内部断片化)も問題でした。
これらの問題により、GPUメモリの使用効率が低下し、同時に処理できるリクエスト数が制限されていました。
PagedAttentionによる解決策💡
PagedAttentionは、オペレーティングシステムにおける仮想記憶とページングの考え方から着想を得ています。主なアイデアは以下の通りです:
- KVキャッシュのブロック分割: KVキャッシュを連続したメモリ領域として扱うのではなく、固定サイズの小さな「ブロック」に分割します。各ブロックは、任意の数のトークンのKeyとValueを保持できます。
- 動的なブロック割り当て: トークンが生成されるたびに、必要に応じてKVキャッシュ用のブロックを動的に割り当てます。これにより、シーケンスの長さに応じて必要な分だけメモリを使用し、無駄な確保を防ぎます。
- 非連続なメモリ配置: 各ブロックは物理的に連続している必要はありません。仮想メモリのように、論理的なブロックと物理的なブロックのマッピングを管理することで、メモリ断片化(特に外部断片化)の影響を受けにくくなります。
- 効率的なメモリ共有 (Copy-on-Write): 複数のリクエストが同じプロンプトを共有する場合(例:並列サンプリングやビームサーチ)、KVキャッシュのブロックを共有し、変更が必要になった時点でコピーを作成します。これにより、メモリ使用量を大幅に削減できます。
3. vLLMの主要な機能 ✨
PagedAttention以外にも、vLLMはLLM推論を高速化・効率化するための様々な機能を備えています。
機能 | 説明 |
---|---|
高スループット | PagedAttentionと後述の連続バッチングにより、最先端のサービングスループットを実現します。 |
連続バッチング (Continuous Batching) | リクエストが到着次第、動的にバッチに追加して処理を開始します。従来の静的バッチングのように、バッチが一杯になるまで待つ必要がないため、GPUのアイドル時間を削減し、レイテンシを短縮、スループットを向上させます。 |
最適化されたCUDA/HIPカーネル | Attention計算やその他の主要な操作のために、高度に最適化されたカスタムCUDA/HIPカーネルを実装しています。FlashAttentionやFlashInferなどの最新技術も統合されています。 |
分散推論 | テンソル並列処理(Tensor Parallelism)やパイプライン並列処理(Pipeline Parallelism)をサポートし、単一GPUに収まらない巨大なモデルも複数のGPUに分散して推論を実行できます。 |
ストリーミング出力 | トークンが生成されるたびにリアルタイムでクライアントに出力を送信(ストリーミング)できます。チャットボットなど、インタラクティブなアプリケーションに不可欠な機能です。 |
豊富なモデルサポート | Hugging Face Hubで公開されている多くの人気オープンソースLLM(Llamaシリーズ, Mistral, Mixtral, Gemma, GPT-2, Falcon, Qwenなど)やマルチモーダルモデル(LLaVAなど)、埋め込みモデル(E5-Mistralなど)をシームレスにサポートします。 |
量子化サポート | GPTQ, AWQ, SqueezeLLM, FP8, INT8, INT4などの量子化技術をサポートしています。モデルの重みを低精度で表現することで、メモリ使用量を削減し、推論速度を向上させることができます。 |
OpenAI互換APIサーバー | OpenAIのAPIと互換性のあるHTTPサーバーを簡単に起動できます。これにより、既存のOpenAI APIクライアントコードを最小限の変更でvLLMバックエンドに接続できます。 |
LoRAサポート | 複数のLoRA (Low-Rank Adaptation) アダプタを効率的に管理し、単一のベースモデルで複数のファインチューニング済みタスクを同時に処理できます(Multi-LoRA)。 |
投機的デコーディング (Speculative Decoding) | 小さなドラフトモデルで候補トークンを予測し、大きなターゲットモデルでそれを検証することで、デコーディングプロセスを高速化します。 |
プレフィックスキャッシング (Prefix Caching) | 複数のリクエスト間で共通するプロンプト(プレフィックス)部分の計算結果(KVキャッシュ)を再利用し、冗長な計算を削減します。会話型のインタラクションなどで特に有効です。 |
多様なハードウェアサポート | NVIDIA GPUだけでなく、AMD GPU, Google Cloud TPU, Intel CPU/GPU, AWS Trainium/Inferentia, IBM Power CPUなどもサポートしています(PyTorchを介して)。2024年12月にはPyTorchエコシステムプロジェクトにも参加し、連携を強化しています。 |
4. インストール方法 💻
vLLMのインストールは非常に簡単です。主にpip
を使用して行います。
前提条件
- Python 3.8 以上 (公式ドキュメントでは3.9〜3.12が推奨される場合もあります)
- NVIDIA GPUを使用する場合: CUDA 11.8 以上 (CUDA 12.1 が推奨されることが多いです)
- PyTorch 2.1 以上 (vLLMのバージョンによって要求されるPyTorchバージョンが異なる場合があります)
- (オプション) NVIDIAドライバ
Dockerを使用すると、環境構築の手間を省くことができます。公式のDockerイメージも提供されています。
基本的なインストール
以下のコマンドで最新の安定版をインストールできます。
pip install vllm
これにより、お使いのCUDAバージョンに対応したPyTorchとvLLMがインストールされます。
特定のCUDAバージョンでのインストール
特定のCUDAバージョン(例: 12.1)に合わせてインストールしたい場合は、対応するPyTorchを先にインストールしてからvLLMをインストールするか、公式ドキュメントで案内されている特定のビルド済みホイールを使用することが推奨されます。 例えば、公式ドキュメントやGitHubリポジトリでは、特定のPyTorch/CUDAバージョンに対応したインストールコマンドが提供されている場合があります。
最新の情報や、AMD GPUなど他のハードウェアでのインストール手順については、vLLM公式ドキュメントのインストールページを参照してください。
5. 基本的な使い方 🚀
vLLMは、オフラインでのバッチ推論と、オンラインでのAPIサーバーとしての利用の両方をサポートしています。
オフライン推論 (Pythonスクリプト)
Pythonスクリプト内で直接LLMをロードし、テキスト生成を行うことができます。
from vllm import LLM, SamplingParams
# 使用するモデルを指定 (Hugging FaceのモデルIDまたはローカルパス)
# 例: MetaのLlama 3.1 8B Instructモデル
model_name = "meta-llama/Meta-Llama-3.1-8B-Instruct"
# LLMインスタンスを作成
# tensor_parallel_sizeで使用するGPU数を指定 (デフォルトは1)
# dtypeでデータ型を指定 (auto, float16, bfloat16など)
# quantizationで量子化方式を指定 (None, "awq", "gptq"など)
llm = LLM(model=model_name, tensor_parallel_size=1, dtype="bfloat16")
# 生成パラメータを設定
# temperature: ランダム性の度合い (低いほど決定的)
# top_p: Top-pサンプリングの確率閾値
# max_tokens: 生成する最大トークン数
# n: 各プロンプトに対して生成する応答数
sampling_params = SamplingParams(temperature=0.7, top_p=0.95, max_tokens=256, n=1)
# 生成したいプロンプトのリスト
prompts = [
"日本の首都はどこですか?",
"AIについて詩を書いてください。",
"vLLMとは何ですか?簡単に説明してください。",
]
# テキスト生成を実行
outputs = llm.generate(prompts, sampling_params)
# 結果を表示
for output in outputs:
prompt = output.prompt
generated_text = output.outputs[0].text # n=1なので最初の応答を取得
print(f"プロンプト: {prompt}")
print(f"生成結果:\n{generated_text.strip()}")
print("-" * 20)
LLM
クラスでモデルをロードし、SamplingParams
で生成時の挙動を制御します。generate
メソッドにプロンプトのリストとパラメータを渡すことで、効率的にバッチ処理が行われます。
OpenAI互換APIサーバー
vLLMは、OpenAIのAPIと互換性のあるインターフェースを持つHTTPサーバーを簡単に起動できます。これにより、curlやPythonのrequests
ライブラリ、あるいは既存のOpenAIクライアントライブラリを使ってLLMと対話できます。
以下のコマンドでAPIサーバーを起動します(ターミナルで実行):
python -m vllm.entrypoints.openai.api_server \
--model meta-llama/Meta-Llama-3.1-8B-Instruct \
--dtype bfloat16 \
--port 8000 \
--tensor-parallel-size 1
--model
: 使用するモデル名またはパス--dtype
: データ型--port
: サーバーがリッスンするポート番号 (デフォルトは8000)--tensor-parallel-size
: 使用するGPU数- その他、
--quantization
,--max-model-len
など多くのオプションがあります。
サーバーが起動したら、別のターミナルやPythonスクリプトからリクエストを送信できます。
curlを使った例:
curl http://localhost:8000/v1/chat/completions \
-H "Content-Type: application/json" \
-d '{
"model": "meta-llama/Meta-Llama-3.1-8B-Instruct",
"messages": [
{"role": "system", "content": "あなたは親切なAIアシスタントです。"},
{"role": "user", "content": "vLLMの主な利点は何ですか?"}
],
"max_tokens": 150,
"temperature": 0.7
}'
Python requests
を使った例:
import requests
import json
api_url = "http://localhost:8000/v1/chat/completions"
model_name = "meta-llama/Meta-Llama-3.1-8B-Instruct" # サーバーで起動したモデル
headers = {"Content-Type": "application/json"}
data = {
"model": model_name,
"messages": [
{"role": "system", "content": "You are a helpful AI assistant."},
{"role": "user", "content": "What are the main benefits of vLLM?"}
],
"max_tokens": 150,
"temperature": 0.7,
"stream": False # ストリーミングしない場合
}
response = requests.post(api_url, headers=headers, data=json.dumps(data))
if response.status_code == 200:
result = response.json()
print(json.dumps(result, indent=2, ensure_ascii=False))
# print(result['choices'][0]['message']['content']) # 応答テキストのみ表示
else:
print(f"Error: {response.status_code}")
print(response.text)
OpenAI互換APIサーバーは、既存のアプリケーションやツールとの連携を非常に容易にします。👍
6. パフォーマンスについて ⚡
vLLMの最大の魅力はそのパフォーマンスです。PagedAttentionと連続バッチングの組み合わせにより、特に複数のリクエストを同時に処理するシナリオにおいて、他の推論エンジンと比較して大幅なスループット向上とレイテンシ削減を実現します。
- スループット向上: 公式の発表やユーザーの報告によると、vLLMはHugging Face Transformersと比較して最大24倍、Hugging Face Text Generation Inference (TGI) と比較しても数倍高いスループットを達成することがあります。これは、同じ時間内により多くのリクエストを処理できることを意味します。
- レイテンシ削減: 連続バッチングにより、リクエストがキューで待機する時間が短縮され、応答時間が改善されます。特にP50レイテンシ(応答時間の中央値)が大幅に削減されると報告されています。
- メモリ効率: PagedAttentionによる効率的なメモリ管理により、GPUメモリの断片化を防ぎ、使用量を最適化します。これにより、より大きなモデルや長いコンテキスト長を扱ったり、より多くの同時リクエストをサポートしたりすることが可能になります。
vLLMは、TensorRT-LLM, SGLang, LMDeployなどの他の高性能推論エンジンと比較しても、多くの場合で競争力のある、あるいはそれを上回るパフォーマンスを示します。セットアップの容易さやHugging Faceエコシステムとの親和性の高さも、vLLMが広く採用されている理由の一つです。
具体的なパフォーマンス数値は、使用するモデル、ハードウェア(GPUの種類と数)、バッチサイズ、入出力シーケンス長、ワークロードの特性などによって大きく変動します。
最新のベンチマーク結果や他のエンジンとの詳細な比較については、vLLMのGitHubリポジトリのREADMEや、公式ブログ記事、ベンチマークスイートのドキュメントなどを参照することをお勧めします。
2024年12月のAmazon Prime Dayでは、AmazonのAIアシスタントRufusのバックエンドとしてvLLMが採用され、AWS Trainium/Inferentiaチップ上で大規模に稼働し、低レイテンシで膨大なリクエストを処理した実績も報告されています。
7. 発展的なトピックとユースケース ⚙️
vLLMは基本的な機能に加えて、より高度な設定やユースケースにも対応しています。
- 分散推論:
LLM
クラスの初期化時やAPIサーバー起動時にtensor_parallel_size
を指定することで、モデルを複数のGPUに分割してロード・実行できます。巨大なモデル(例: Llama 3.1 405B)の推論に不可欠です。パイプライン並列もサポートされています。 - 量子化モデルの利用:
quantization
パラメータに'awq'
や'gptq'
などを指定することで、対応する形式で量子化されたモデルをロードできます。これにより、メモリ使用量を削減し、場合によっては推論速度も向上します。# AWQ量子化モデルを使用する場合 llm = LLM(model="path/to/your/awq_model", quantization="awq")
- LoRAアダプタの活用:
複数のLoRAアダプタを動的にロードし、リクエストごとに異なるアダプタを適用できます。
enable_lora=True
で機能を有効化し、LLM.generate
メソッドのlora_request
引数でアダプタを指定します。 - Beam Search:
より高品質なテキスト生成が求められる場合に、Beam Searchを使用できます。
SamplingParams
でuse_beam_search=True
を設定し、best_of
(探索するビーム数)を指定します。 - マルチモーダルモデル: LLaVAなどのマルチモーダルモデルもサポートしており、テキストと画像の入力を受け付けて応答を生成できます。APIサーバーやPythonコードから画像データを入力として渡すことが可能です。
- カスタムモデルの統合: 公式でサポートされていない独自のモデルアーキテクチャをvLLMに統合することも可能です(高度な知識が必要)。公式ドキュメントにはカスタムモデルを追加するためのガイドラインがあります。
- メトリクスとトレーシング: Prometheus形式でのメトリクス出力やOpenTelemetryによるトレーシングをサポートしており、運用時のモニタリングやパフォーマンス分析に役立ちます。
これらの機能により、研究開発から本番環境での大規模なサービス提供まで、幅広いニーズに対応できる柔軟性を持っています。
8. まとめと今後の展望 🌟
vLLMは、PagedAttention、連続バッチング、最適化されたカーネルといった革新的な技術により、大規模言語モデルの推論とサービングにおけるパフォーマンスと効率を劇的に向上させるPythonライブラリです。
- ✅ 圧倒的な高スループット: より多くのリクエストを同時に処理。
- ✅ 優れたメモリ効率: PagedAttentionによるKVキャッシュの最適化。
- ✅ 低レイテンシ: 連続バッチングによる応答時間の短縮。
- ✅ 簡単な導入と利用: Hugging Faceモデルとのシームレスな統合、OpenAI互換API。
- ✅ 高い柔軟性と拡張性: 分散推論、量子化、LoRA、多様なハードウェアサポート。
- ✅ 活発なオープンソースコミュニティ: 継続的な改善と新機能の追加。
これらの特徴により、vLLMはLLMを活用したアプリケーション開発やサービス提供において、デファクトスタンダードとも言える地位を確立しつつあります。研究プロトタイピングから大規模な商用サービスまで、vLLMは開発者がLLMのパワーを最大限に引き出すための強力なツールとなります。
vLLMコミュニティは非常に活発であり、パフォーマンスのさらなる最適化、新しいモデルアーキテクチャやハードウェアへの対応、より高度な機能(例:より洗練された投機的デコーディング、効率的なマルチモーダル処理など)の追加が継続的に行われています。今後もLLM推論技術の進化を牽引していくことが期待されます。
LLMの推論速度やコストに課題を感じている方は、ぜひvLLMの導入を検討してみてはいかがでしょうか? 🎉
コメント