TokenDatabase(ChunkedTokenDatabase)
深度: [MEDIUM] / 確信度: [VERIFIED] 最終更新: 2026-02-16(Phase 1 セッション1)
概要
トークン列をチャンクに分割し、プレフィックスチェーンハッシュを計算してCacheEngineKeyを生成する。 vLLMのプレフィックスキャッシュと同一のハッシュアルゴリズムを使用し、キーの互換性を保証する。
参照: target/LMCache/lmcache/v1/token_database.py
クラス階層
TokenDatabase (ABC)
├── ChunkedTokenDatabase ← 標準実装(固定サイズチャンク)
└── SegmentTokenDatabase ← CacheBlend用(セパレータベースの可変長チャンク)
主要メソッド
process_tokens()
参照: target/LMCache/lmcache/v1/token_database.py:309
def process_tokens(
tokens: Optional[Union[Tensor, List[int]]] = None,
hashes: Optional[List[int]] = None,
offsets: Optional[List[int]] = None,
mask: Optional[Tensor] = None,
make_key: bool = True,
request_configs: Optional[dict] = None,
) -> Iterable[ProcessTokensResult] # (start, end, CacheEngineKey|hash)
2つの入力モード:
- tokens入力: トークン列を受け取り、チャンク分割→ハッシュ計算
- hashes入力: 事前計算済みハッシュ+offsetsを受け取り、キー生成のみ
チャンク分割アルゴリズム(tokens入力時):
_chunk_tokens(): chunk_size(デフォルト256)単位で分割save_unfull_chunk=True(デフォルト): 端数チャンクも保存save_unfull_chunk=False: 端数は切り捨て
_prefix_hash(): プレフィックスチェーンハッシュを計算- 初期値:
NONE_HASH(vLLMから取得、kv_cache_utils.init_none_hash()) - 各チャンク:
hash_func((previous_hash, token_tuple, extra_keys))
- 初期値:
- maskのFalse区間(=already-cached prefix)のチャンクをスキップ
- 制約: False数はchunk_sizeの倍数でなければならない(ValueError)
ハッシュ関数
参照: target/LMCache/lmcache/v1/token_database.py:97 (_get_vllm_hash_func)
vLLMのget_hash_fn_by_name("sha256_cbor")を直接利用。
複数のインポートパスを試行し、vLLMバージョン互換性を確保:
vllm.utils.hashing.get_hash_fn_by_name(PR#27151以降)vllm.utils.get_hash_fn_by_name(PR#27151以前)sha256_cbor_64bit→sha256_cborリネーム対応(PR#23673)- フォールバック: Python組み込み
hash()(非推奨、分散キャッシュで不整合の可能性)
CacheEngineKey生成
参照: target/LMCache/lmcache/v1/token_database.py:207 (_make_key_by_hash)
CacheEngineKey(
model_name, # メタデータから
world_size, # save_only_first_rank時は1に固定
worker_id, # GPUランク
chunk_hash, # プレフィックスチェーンハッシュ
kv_dtype, # e.g. bfloat16
request_configs, # オプション(per-requestの設定dict)
)
save_only_first_rankはMLA(Multi-head Latent Attention)使用時に有効。world_sizeを1に固定することで、異なるTP並列度でもキーが一致する。
Retrieve時の利用
Retrieveパスでも同じprocess_tokens()が使用される:
- Bulk retrieve:
_process_tokens_internal()と_async_process_tokens_internal()の両方で呼ばれ、チャンクキーを生成 - Layerwise retrieve:
retrieve_layer()内で呼ばれ、layer 0のキーでStorageManager.contains()判定 - LookupClient: Schedulerプロセス内でも独自の
ChunkedTokenDatabaseインスタンスを持ち、process_tokens(make_key=False)でハッシュのみ計算してZMQ経由でLookupServerに送信 - 非同期prefetch:
async_process_tokens_internal()ではハッシュ再計算が発生する(TODO: スキップ最適化の余地あり)
上流・下流
- 上流: LMCacheEngine(store_layer/store/retrieve等で呼び出し)、LookupClient(lookup時)
- 下流: なし(純粋な変換コンポーネント)
- 依存: vLLMのハッシュ関数ライブラリ