Attention-DP KV Cache Connector#
Source NVIDIA/TensorRT-LLM.
1# SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
2# SPDX-License-Identifier: Apache-2.0
3"""V2 ADP filesystem connector: stable prefix keys and atomic publication.
4
5Set both connector classes below and enable_attention_dp=True. Every owner
6must see the same CONNECTOR_CACHE_FOLDER. Use a separate folder per model,
7KV representation and block size. This example requires one full-attention
8layer group and does not support chunked prefill or attention TP sharding.
9Cache keys and file contents use the base filesystem example's format.
10"""
11
12import os
13from pathlib import Path
14from tempfile import NamedTemporaryFile
15
16import torch
17from llm_kv_cache_connector import PersistentKvCacheConnectorLeader as BaseConnectorLeader
18from llm_kv_cache_connector import PersistentKvCacheConnectorWorker as BaseConnectorWorker
19
20from tensorrt_llm.llmapi.llm_args import TorchLlmArgs
21
22
23class PersistentKvCacheConnectorWorker(BaseConnectorWorker):
24 supports_attention_dp = True
25
26 def __init__(self, llm_args: TorchLlmArgs) -> None:
27 super().__init__(llm_args)
28
29 if llm_args.tensor_parallel_size > 1 and not llm_args.enable_attention_dp:
30 raise NotImplementedError("The example requires unsharded attention KV cache.")
31
32 self.kv_cache_tensor = None
33
34 def wait_for_save(self, stream: torch.cuda.Stream) -> None:
35 # Make sure the forward pass is complete before beginning our save.
36 stream.synchronize()
37
38 for path, block_id in self._metadata.save:
39 cpu_tensor = self.kv_cache_tensor[block_id].cpu()
40
41 # Don't write anything if this specific block already exists.
42 if Path(path).exists():
43 continue
44
45 # Publish only complete files. Multiple ADP owners can save the
46 # same prefix concurrently, while another owner starts a restore.
47 with NamedTemporaryFile(dir=Path(path).parent, delete=False) as tmp:
48 temporary_path = Path(tmp.name)
49 try:
50 torch.save(cpu_tensor, temporary_path)
51 os.replace(temporary_path, path)
52 finally:
53 temporary_path.unlink(missing_ok=True)
54
55
56class PersistentKvCacheConnectorLeader(BaseConnectorLeader):
57 supports_attention_dp = True