LMCache/LMCache
主な特徴
- **vLLM v1との統合**: 高性能CPUオフローディング、分散プレフィル、P2P KVキャッシュ共有
- **非プレフィックスKVキャッシュのサポート**: 任意の位置のテキストを再利用可能
- **多層ストレージサポート**: GPU、CPU、ディスク、NIXL(分散ストレージ)
- **CacheGen圧縮技術**: 算術符号化による効率的なKVキャッシュ圧縮
- **CacheBlend技術**: 複数のテキストチャンクからKVキャッシュをブレンド
- **本番環境対応**: vLLM Production Stack、llm-d、KServeでの公式サポート
- **Prometheusメトリクス統合**: 観測可能性とモニタリング
リポジトリ解析: LMCache/LMCache
基本情報
- リポジトリ名: LMCache/LMCache
- 主要言語: Python, C++/CUDA
- スター数: 2,885
- フォーク数: 約200
- 最終更新: アクティブに開発中(毎週コミット)
- ライセンス: Apache License 2.0
- トピックス: LLM serving, KV cache, vLLM, performance optimization, GPU optimization, cache storage
概要
一言で言うと
LMCacheは、LLMサービングエンジンの拡張機能で、KVキャッシュの再利用により、特に長文脈シナリオでTTFT(Time To First Token)を大幅に削減し、スループットを向上させる。
詳細説明
LMCacheは、再利用可能なテキストのKVキャッシュを様々な場所(GPU、CPU DRAM、ローカルディスク)に保存し、任意のサービングエンジンインスタンスで任意の再利用テキスト(必ずしもプレフィックスでなくても)のKVキャッシュを再利用する。これにより、貴重なGPUサイクルを節約し、ユーザーレスポンスの遅延を削減する。vLLMと組み合わせることで、マルチラウンドQAやRAGなどの多くのLLMユースケースで3〜10倍の遅延削減とGPUサイクル削減を実現する。
主な特徴
- vLLM v1との統合: 高性能CPUオフローディング、分散プレフィル、P2P KVキャッシュ共有
- 非プレフィックスKVキャッシュのサポート: 任意の位置のテキストを再利用可能
- 多層ストレージサポート: GPU、CPU、ディスク、NIXL(分散ストレージ)
- CacheGen圧縮技術: 算術符号化による効率的なKVキャッシュ圧縮
- CacheBlend技術: 複数のテキストチャンクからKVキャッシュをブレンド
- 本番環境対応: vLLM Production Stack、llm-d、KServeでの公式サポート
- Prometheusメトリクス統合: 観測可能性とモニタリング
使用方法
インストール
前提条件
- Python 3.10-3.12
- PyTorch 2.7.0
- CUDA対応GPU(compute capability 7.0以上)
- Linux環境(NVIDIA GPUプラットフォーム)
インストール手順
# 方法1: pipによるインストール
pip install lmcache
# 方法2: ソースからビルド(開発版)
git clone https://github.com/LMCache/LMCache.git
cd LMCache
pip install -e .
# vLLMと一緒にインストール
pip install vllm lmcache
基本的な使い方
Hello World相当の例
# 最小限のvLLM + LMCache使用例
from vllm import LLM
from vllm.config import KVTransferConfig
# KV転送設定
ktc = KVTransferConfig(
kv_connector="LMCacheConnectorV1",
kv_role="kv_both", # キャッシュの保存と取得の両方
)
# LLMインスタンスの作成
llm = LLM(
model="meta-llama/Meta-Llama-3.1-8B-Instruct",
kv_transfer_config=ktc,
max_model_len=8000,
gpu_memory_utilization=0.8,
)
# 推論実行
response = llm.generate("Hello, how are you?")
print(response)
実践的な使用例
# CacheBlendを使用したRAGの例
import yaml
from vllm import LLM
from vllm.config import KVTransferConfig
# 設定ファイルの読み込み
with open('lmcache_config.yaml', 'r') as f:
config = yaml.safe_load(f)
# LMCache設定
ktc = KVTransferConfig(
kv_connector="LMCacheConnectorV1",
kv_role="kv_both",
kv_connector_config=config,
)
llm = LLM(
model="meta-llama/Meta-Llama-3.1-8B-Instruct",
kv_transfer_config=ktc,
max_model_len=16384,
)
# RAGコンテキストの準備
documents = ["Document 1 content...", "Document 2 content..."]
query = "What is the main topic?"
# CacheBlendセパレータを使用
blend_separator = config.get('blend_separator', '[BLEND_SEP]')
prompt = f"{documents[0]}{blend_separator}{documents[1]}{blend_separator}{query}"
# 推論実行(KVキャッシュは自動的に管理される)
response = llm.generate(prompt)
高度な使い方
# lmcache_config.yaml - 高度な設定
# チャンクサイズとストレージ設定
chunk_size: 256
local_device: "cpu"
max_local_cpu_size: 10 # GB
local_disk: "file://cache_storage/"
# CacheBlend設定
enable_blending: true
blend_recompute_ratio: 0.15
blend_min_tokens: 256
blend_separator: "[BLEND_SEP]"
# P2P共有設定
enable_p2p: true
lookup_url: "localhost:8100"
distributed_url: "localhost:8200"
# リモートストレージ(Redis)
remote_url: "lm://redis-server:65432"
remote_serde: "cachegen" # 圧縮形式
# 分散プレフィル設定(NIXL使用)
prefill_url: "nixl://prefiller-node:8000"
prefill_channel: "nvlink" # nvlink, rdma, tcp
# 分散プレフィルの実装例
from lmcache.config import LMCacheConfig
from lmcache.cache_engine import LMCacheEngine
# プレフィラーノードの設定
prefiller_config = LMCacheConfig(
chunk_size=256,
enable_nixl=True,
nixl_role="prefiller",
nixl_channel="nvlink",
)
# デコーダーノードの設定
decoder_config = LMCacheConfig(
chunk_size=256,
enable_nixl=True,
nixl_role="decoder",
prefill_url="nixl://prefiller:8000",
)
# マルチラウンドQAでの使用例
class MultiRoundChatbot:
def __init__(self, model_name):
self.ktc = KVTransferConfig(
kv_connector="LMCacheConnectorV1",
kv_role="kv_both",
kv_connector_config={
"chunk_size": 256,
"enable_blending": True,
"local_device": "cpu",
"max_local_cpu_size": 20,
},
)
self.llm = LLM(
model=model_name,
kv_transfer_config=self.ktc,
max_model_len=32768,
tensor_parallel_size=4,
)
self.conversation_history = []
def chat(self, user_input):
# 会話履歴の構築
self.conversation_history.append(f"User: {user_input}")
prompt = "\n".join(self.conversation_history)
# 推論(前回のKVキャッシュを再利用)
response = self.llm.generate(prompt)
self.conversation_history.append(f"Assistant: {response}")
return response
ドキュメント・リソース
公式ドキュメント
- README.md: プロジェクト概要、インストール方法、基本的な使い方
- CONTRIBUTING.md: 貢献ガイドライン、開発環境セットアップ
- docs.lmcache.ai: 包括的な公式ドキュメントサイト
- blog.lmcache.ai: 技術ブログ、アップデート情報
サンプル・デモ
- examples/blend_kv/: CacheBlend機能の実装例
- examples/cache_controller/: キャッシュコントローラーの設定例
- examples/frontend/: チャットセッションのフロントエンド実装
- examples/disagg_prefill/: 分散プレフィルの実装例
- examples/kv_cache_reuse/: KVキャッシュ再利用のデモ
- examples/online_session/: オンラインセッション管理
- examples/sgl_integration/: SGLang統合の例
チュートリアル・ガイド
- Quickstart Examples: 公式ドキュメントのクイックスタートガイド
- Multi-round QA Benchmark: ベンチマークの実行方法
- RAG Benchmark: RAGシステムでの使用方法
- KV Cache Calculator: KVキャッシュサイズ計算ツール
- YouTube Channel: 実装デモとチュートリアル動画
技術的詳細
アーキテクチャ
全体構造
LMCacheは、LLMサービングエンジン(主にvLLM)の拡張として動作し、KVキャッシュの階層的ストレージと再利用を実現する。GPU、CPU、ディスクにまたがる多層キャッシュシステムを提供し、異なるサービングインスタンス間でKVキャッシュを共有可能。
ディレクトリ構成
lmcache/
├── lmcache/ # メインパッケージ
│ ├── blend/ # CacheBlend実装
│ │ ├── executor.py # ブレンド実行エンジン
│ │ └── retriever.py # キャッシュ取得ロジック
│ ├── storage_backend/ # ストレージバックエンド
│ │ ├── abstract_backend.py
│ │ ├── local_backend.py # CPU/GPUローカルストレージ
│ │ ├── remote_backend.py # Redis/Valkeyリモートストレージ
│ │ └── hybrid_backend.py # ハイブリッドストレージ
│ ├── v1/ # vLLM v1統合
│ │ ├── cache_engine.py # キャッシュエンジンコア
│ │ ├── gpu_connector.py # GPU間転送
│ │ └── memory_management.py # メモリプール管理
│ ├── cache_engine.py # キャッシュエンジン(メイン)
│ ├── config.py # 設定管理
│ └── protocol.py # プロトコル定義
├── csrc/ # CUDAカーネル
│ ├── ac_enc.cu # 算術符号化エンコード
│ ├── ac_dec.cu # 算術符号化デコード
│ ├── cachegen_kernels.cuh # CacheGen圧縮カーネル
│ ├── mem_kernels.cu # メモリ操作カーネル
│ └── pos_kernels.cu # 位置エンコーディングカーネル
├── benchmarks/ # ベンチマークツール
│ ├── multi-round-qa/ # マルチラウンドQAベンチマーク
│ └── rag/ # RAGベンチマーク
└── tests/ # テストスイート
主要コンポーネント
-
CacheEngine: KVキャッシュの管理とオーケストレーション
- 場所:
lmcache/cache_engine.py - 依存: StorageBackend、Protocol、Config
- インターフェース:
get(),put(),has(),evict()
- 場所:
-
StorageBackend: 階層的ストレージの抽象化
- 場所:
lmcache/storage_backend/ - 依存: 各種ストレージドライバー
- インターフェース:
retrieve(),store(),contains(),evict()
- 場所:
-
CacheGen Compression: 高速KVキャッシュ圧縮
- 場所:
csrc/cachegen_kernels.cuh - 依存: CUDA Runtime
- インターフェース: CUDA kernels for encode/decode
- 場所:
-
BlendExecutor: CacheBlend実行エンジン
- 場所:
lmcache/blend/executor.py - 依存: Retriever、CacheEngine
- インターフェース:
blend_kv_caches(),compute_blend_ratio()
- 場所:
技術スタック
コア技術
- 言語:
- Python 3.10-3.12(メインロジック)
- C++/CUDA(高性能カーネル)
- フレームワーク:
- vLLM(LLMサービングエンジン)
- PyTorch 2.7.0(テンソル操作)
- 主要ライブラリ:
- transformers (≥4.51.1): モデルトークナイザー
- aiohttp/aiofiles: 非同期I/O
- cufile-python: GPU Direct Storage
- msgspec: 高速シリアライゼーション
- prometheus_client: メトリクス収集
- redis: リモートキャッシュストレージ
- nvtx: GPUプロファイリング
開発・運用ツール
- ビルドツール:
- setuptools(Pythonパッケージング)
- nvcc(CUDAコンパイル)
- Docker(コンテナ化)
- テスト:
- pytest(単体テスト)
- Buildkite(統合テスト)
- GitHub Actions(コード品質チェック)
- CI/CD:
- Unit Tests(Buildkite)
- Integration Tests(vLLM統合)
- Code Quality Checks(GitHub Actions)
- デプロイ:
- pip/PyPI(パッケージ配布)
- Docker Hub(コンテナイメージ)
- Kubernetes(本番環境)
設計パターン・手法
- 階層的キャッシュアーキテクチャ: GPU→CPU→ディスクの多層キャッシュ
- チャンクベース管理: 256トークン単位でKVキャッシュを管理
- 非同期パイプライン: 非同期I/Oによる高速データ転送
- プラグイン可能なバックエンド: 新しいストレージ追加が容易
- ゼロコピー転送: GPU Direct Storageでのダイレクト転送
- 適応的圧縮: CacheGenによる動的圧縮率調整
データフロー・処理フロー
1. KVキャッシュ生成要求
↓
2. チャンクへの分割(256トークン単位)
↓
3. 圧縮(オプション:CacheGen)
↓
4. ストレージへの保存
- L1: GPU memory(高速)
- L2: CPU DRAM(中速)
- L3: Local Disk/Remote(低速)
↓
5. メタデータ登録(キー、場所、タイムスタンプ)
↓
6. 取得時の処理
- キャッシュヒット判定
- 必要に応じて上位層へプロモート
- 解凍(CacheGen使用時)
↓
7. CacheBlend(該当時)
- 複数チャンクの取得
- ブレンド比率計算
- 部分再計算
↓
8. vLLMへのKVキャッシュ供給
API・インターフェース
公開API
KVTransferConfig (vLLM統合)
- 目的: vLLMとLMCacheの統合設定
- 使用例:
from vllm.config import KVTransferConfig
ktc = KVTransferConfig(
kv_connector="LMCacheConnectorV1", # コネクタータイプ
kv_role="kv_both", # kv_producer, kv_consumer, kv_both
kv_rank=0, # 分散環境でのランク
kv_ip="0.0.0.0", # P2P共有用IP
kv_port=12345, # P2P共有用ポート
kv_connector_config={ # LMCache固有設定
"chunk_size": 256,
"enable_blending": True,
"blend_separator": "[BLEND_SEP]",
},
)
CacheEngine API
- 目的: 直接的なキャッシュ操作
- 使用例:
from lmcache.cache_engine import LMCacheEngine
from lmcache.config import LMCacheConfig
config = LMCacheConfig(
chunk_size=256,
local_device="cpu",
max_local_cpu_size=10,
)
engine = LMCacheEngine(config)
# キャッシュの保存
engine.put(key="conversation_123", kv_cache=kv_tensors)
# キャッシュの取得
if engine.has("conversation_123"):
cached_kv = engine.get("conversation_123")
# キャッシュの削除
engine.evict("conversation_123")
設定・カスタマイズ
設定ファイル
# lmcache_config.yaml - 完全な設定例
# 基本設定
chunk_size: 256 # トークン単位のチャンクサイズ
format: "torch" # "torch" or "cachegen"
# ローカルストレージ
local_device: "cpu" # "cpu" or "cuda"
max_local_cpu_size: 20 # GB単位
max_local_gpu_size: 5 # GB単位
local_disk: "file://cache/" # ローカルディスクパス
# リモートストレージ
remote_url: "lm://redis:65432"
remote_serde: "cachegen" # 圧縮形式
# CacheBlend設定
enable_blending: true
blend_recompute_ratio: 0.15 # 再計算比率
blend_min_tokens: 256 # 最小ブレンドトークン数
blend_separator: "[BLEND_SEP]"
# P2P共有
enable_p2p: true
lookup_url: "localhost:8100"
distributed_url: "localhost:8200"
# メトリクス
enable_metrics: true
prometheus_port: 8090
環境変数による設定
# LMCache環境変数
export LMCACHE_CHUNK_SIZE=256
export LMCACHE_LOCAL_CPU=True
export LMCACHE_MAX_LOCAL_CPU_SIZE=20
export LMCACHE_LOCAL_DISK="file://cache_storage/"
export LMCACHE_REMOTE_URL="lm://redis:65432"
export LMCACHE_ENABLE_BLENDING=True
export LMCACHE_BLEND_SEPARATOR="[BLEND_SEP]"
拡張・プラグイン開発
新しいストレージバックエンドの追加例:
from lmcache.storage_backend.abstract_backend import LMCStorageBackend
class CustomStorageBackend(LMCStorageBackend):
def __init__(self, config):
super().__init__(config)
# カスタム初期化
def put(self, key, value):
# カスタム保存ロジック
pass
def get(self, key):
# カスタム取得ロジック
pass
def contains(self, key):
# 存在確認
pass
def evict(self, key):
# 削除ロジック
pass
パフォーマンス・スケーラビリティ
パフォーマンス特性
- ベンチマーク結果:
- TTFT削減: 3-10倍(マルチラウンドQA)
- GPUサイクル削減: 最大90%(頻繁に再利用されるコンテキスト)
- スループット向上: 2-5倍(RAGワークロード)
- 最適化手法:
- CacheGen圧縮: 算術符号化による高効率圧縮
- ゼロコピー転送: GPU Direct Storage
- 非同期パイプライン: オーバーラップI/O
- NVLink/RDMA: 高速ノード間通信
スケーラビリティ
- 水平スケーリング:
- P2P共有による分散キャッシュ
- 複数ノードでのキャッシュ共有
- ロードバランシング対応
- 垂直スケーリング:
- GPU/CPU/ディスクの階層的利用
- 動的メモリ割り当て
- 適応的エビクション
- 分散プレフィル:
- 専用プレフィラーノード
- XP1D構成(複数プレフィラー、1デコーダー)
制限事項
-
技術的な制限:
- チャンクサイズは固定(デフォルト256トークン)
- CUDA compute capability 7.0以上が必要
- Linux NVIDIA GPUプラットフォームのみ対応
- 最大モデルサイズはGPUメモリに依存
-
運用上の制限:
- キャッシュの一貫性は手動管理
- 異なるモデル間でのキャッシュ共有は不可
- トークナイザーの変更時は再キャッシュが必要
- ネットワーク遅延がP2P共有性能に影響
評価・所感
技術的評価
強み
- 実績のある性能向上: 3-10倍のTTFT削減は実用的に大きなインパクト
- 柔軟なストレージ階層: GPU/CPU/ディスクを効率的に活用
- 本番環境対応: vLLM Production Stack、KServeでの公式サポート
- 活発な開発: 毎週のコミュニティミーティング、継続的な改善
- 包括的な機能: 圧縮、分散、P2P共有など先進的機能を網羅
- 優れたドキュメント: 詳細な技術文書とサンプルコード
改善の余地
- プラットフォーム制限: Linux NVIDIA GPUのみ対応
- 設定の複雑さ: 最適な性能を出すには詳細なチューニングが必要
- モデル依存性: 異なるモデル間でのキャッシュ共有は不可
- メモリオーバーヘッド: メタデータ管理のメモリ使用
向いている用途
- マルチラウンド対話システム: チャットボット、カスタマーサポート
- RAGシステム: 文書検索を伴う質問応答システム
- コード生成: 共通のインポートやボイラープレートを持つコード生成
- バッチ処理: 同じプロンプトテンプレートを使う大量処理
- エンタープライズLLMサービス: 高トラフィック、コスト最適化が重要な環境
向いていない用途
- 単発の推論: キャッシュの恩恵を受けない一度きりの処理
- 極めて短いコンテキスト: オーバーヘッドが利益を上回る
- リアルタイムストリーミング: 遅延が極めて重要な用途
- 異種モデルの混在: 頻繁にモデルを切り替える環境
総評
LMCacheは、LLMサービングの効率化において画期的なソリューションである。特に長文脈や繰り返しの多いワークロードでは、劇的な性能向上を実現する。vLLMとの深い統合、本番環境での実績、活発なコミュニティサポートなど、エンタープライズ利用に必要な要素を備えている。設定の複雑さはあるものの、適切に構成すれば、コスト削減とユーザー体験向上の両立が可能。LLMをプロダクション環境で大規模に運用する組織にとって、検討する価値の高いツールである。