Dongha Yoon, Younghoon Min, Hoshik Kim, Sam H. Noh, Jongryool Kim
Virginia Tech, SK Hynix America
Disaggregated LLM serving (DistServe, Splitwise, Dynamo) separates prefill and decode into distinct workers. The KV tensors generated during prefill must be transferred to decode workers. Current systems use RDMA over network, which traverses NIC queues, host DRAM buffers, and layered transport protocols. This network hop inflates prefill latency, increases tail variability, and constrains throughput—even with prefix reuse, every cache hit still requires network transfer.
TraCT uses CXL Type-3 shared memory as both a network-free KV transfer substrate and a rack-wide prefix-aware KV cache. GPUs write KV blocks directly into CXL memory via GPU-CXL DMA and fetch them back the same way—no NIC involvement, no host-to-host copies, no network serialization. This eliminates the RDMA hop entirely, turning prefill-decode communication into local load/store and DMA operations on a shared address space.
CXL Type-3 devices lack cross-node atomic instructions. TraCT implements a two-tier software lock: local_lock (per-node DRAM, pthread_mutex) ensures at most one process per node contends globally, and global_lock (CXL shared memory) coordinates across nodes. A lock manager thread polls global_lock entries, bounding contention to the number of nodes (typically 2-4 in a rack).
CXL shared memory is non-coherent across nodes. TraCT uses clflush (not clflushopt) to ensure metadata visibility: it evicts cachelines from the local hierarchy before the instruction completes, guaranteeing that other nodes observe the update. KV payloads bypass CPU caches entirely via GPU-CXL DMA, requiring no software coherence.
Two-tier allocator: global chunk allocator (CXL bitmap) + per-node heap allocators (local DRAM free-lists). Shared object store publishes only root objects (prefix index hash table) via offsets, not pointers. Offset-based addressing ensures consistency across nodes with different virtual address mappings.
CXL shared memory is registered via CUDA's host-memory registration interface and pinned as page-locked host memory. This enables true zero-copy GPU-CXL transfers via cudaMemcpy without intermediate host DRAM bounce buffers. Cache-hit KV blocks are consumed directly from CXL with no regeneration or network transfer.
| System | Avg TTFT | P99 TTFT | Peak Throughput | Cache Backend |
|---|---|---|---|---|
| NIXL/UCX (RDMA) | 1.0x (baseline) | 1.0x | 1.0x | None (transfer only) |
| LMCache (DRAM cache) | ~0.3x | ~0.4x | ~1.0x | Host DRAM (48GB) |
| TraCT (no cache) | ~0.7x | ~0.8x | 1.6x | CXL (transfer only) |
| TraCT (with cache) | 0.10x (9.83x better) | 0.16x (6.2x better) | 1.6x | CXL shared memory (64GB) |
TraCT's gains are most pronounced when the prefix reuse rate is high. Workloads like multi-turn chat (identical system prompt across turns), RAG (identical document context for multiple user queries), or agentic pipelines (identical tool definitions across calls) benefit most. For workloads with fully unique prompts (e.g., code generation with entirely new inputs each time), the TraCT no-cache configuration applies — which still provides ~3x lower transfer latency than RDMA due to eliminated NIC overhead.
Longer input sequences generate more KV blocks, increasing both the benefit and the cost of caching. For short inputs (512 tokens), the absolute KV data size is small and RDMA latency is dominated by fixed overhead — CXL's advantage is primarily in eliminating that fixed NIC overhead. For long inputs (4K–32K tokens), the total KV size grows (hundreds of MB for 70B models), making the 10.1 GB/s CXL bandwidth the primary constraint. The sweet spot for current TraCT hardware is 1K–8K token sequences with 7B–13B models.
TraCT is the first system to demonstrate rack-scale KV caching and transfer for disaggregated LLM serving on real CXL Type-3 hardware (Niagara 2.0). It proves CXL shared memory is a practical high-performance substrate for LLM inference.
By replacing RDMA with direct GPU-CXL DMA, TraCT removes the NIC, host DRAM buffers, and transport protocol overhead from the KV transfer critical path. This produces tighter, more predictable TTFT distributions.
Addresses three fundamental challenges of multi-host CXL (no atomic operations, no coherence, no shared pointers) with practical software mechanisms: two-tier locking, clflush-based visibility, and offset-based addressing.
TraCT lowers GPU SM utilization and PCIe bandwidth usage during both prefill and decode. Cache hits bypass KV regeneration entirely. These translate to lower power consumption and reduced total cost of ownership.
Compute Express Link (CXL) is a high-speed, low-latency interconnect built on top of the PCIe 5.0 physical layer. CXL 3.0 introduces Fabric Manager support and multi-host shared memory semantics. A CXL Type-3 memory device (e.g., Niagara 2.0) exposes a large DRAM pool that can be mapped into the physical address space of multiple host servers simultaneously. Unlike RDMA, which sends data through a NIC, operating system network stack, and transport queues, CXL memory is accessed via ordinary CPU load/store instructions and GPU DMA — making it feel like local DRAM to the processor.
RDMA KV Transfer Path (traditional disaggregated serving):
TraCT CXL Transfer Path:
3 hops eliminated. No NIC, no OS network stack, no transport protocol.
Even with InfiniBand HDR (200 Gb/s), the KV transfer bottleneck is not raw bandwidth — it is latency and queuing variability. For a single KV block (e.g., 4 KB for a 32-layer model with GQA), PCIe transfer takes tens of microseconds. CXL latency is ~640 ns, roughly 30–100x lower depending on block size and NIC queue depth. Moreover, NIC queues serialize requests from multiple concurrent LLM requests, creating head-of-line blocking that inflates P99 TTFT. CXL memory has no such serialization point.
Cache-hit path: KV is already in CXL pool from a previous request with the same prefix. DMA to decode GPU VRAM bypasses all compute.
When the 64 GB CXL pool is full, TraCT evicts blocks using an LRU (Least Recently Used) policy at the block level. The eviction is coordinated through the two-tier locking protocol — the global_lock must be acquired to remove a prefix entry from the shared hash table. Evicted blocks are not spilled to CPU DRAM; they are simply freed. A future request for that prefix will trigger a cache miss and full prefill recomputation.
A secondary benefit of CXL offloading is GPU VRAM pressure relief. In a non-disaggregated serving system, the KV cache must share GPU VRAM with model weights and activations. With TraCT, KV blocks for completed or long-idle requests can be offloaded from GPU VRAM to CXL, freeing VRAM for active batches. This is similar to how vLLM uses CPU DRAM swapping, but with 4–8x lower latency than DRAM DMA over PCIe.
| Component | Specification | Role in TraCT |
|---|---|---|
| GPU | NVIDIA RTX A6000 (48 GB GDDR6) | Prefill compute + decode KV attention |
| Host DRAM | 512 GB DDR5 per node | Local locks, allocator free-lists, process memory |
| CXL Memory Device | Niagara 2.0 (CXL Type-3, 64 GB) | Shared KV cache pool + in-flight KV staging |
| CXL Latency | ~640 ns (round-trip read) | vs ~80 ns local DRAM; vs ms-level RDMA |
| CXL Bandwidth | 10.1 GB/s per node | Sufficient for most KV block sizes; shared across nodes |
| LLM Model | DeepSeek-R1-Distill-Llama-8B | Evaluation model; fits on single A6000 per worker |
| Server Count | 2 nodes (1 prefill + 1 decode) | Minimum rack-scale CXL topology |
CXL is built on the PCIe 5.0 physical layer but extends it with three protocols: CXL.io (device discovery, config), CXL.cache (device-side cache coherency with host), and CXL.mem (host-managed device memory). The key difference from plain PCIe: CXL.mem exposes device DRAM as a coherent memory extension of the host's address space, allowing load/store semantics rather than explicit DMA commands for metadata. For KV payload, TraCT still uses explicit GPU DMA for throughput.
The paper demonstrates a 2-node setup (1 prefill + 1 decode). CXL 3.0 fabric can support up to 4,096 nodes in theory, though practical rack-scale deployments target 16–32 nodes. The two-tier locking overhead grows with node count: locking contention is bounded by the number of nodes, not concurrent requests. For 4 nodes, lock overhead is negligible; for 32 nodes, careful tuning of lock manager polling intervals may be needed.
The Niagara 2.0 device provides ~10.1 GB/s per node. For large models (e.g., Llama-3 70B with 80 layers), a single full-sequence KV cache can exceed 1 GB. Under high request rates, the shared 10.1 GB/s becomes a bottleneck. The paper evaluates on a smaller 8B model; scaling to 70B+ models would require either multiple CXL devices, a CXL switch providing higher aggregate bandwidth, or selective caching of only the most frequently accessed layers.
CXL Type-3 devices do not support cross-host atomic operations. TraCT's two-tier software locking adds overhead for every prefix index write. For read-heavy cache-hit workloads, read operations are lock-free (only a hash table lookup), but any metadata write — including eviction — must go through the locking protocol. Future CXL revisions or CXL.cache semantics could enable hardware-assisted atomic metadata updates.
The experimental evaluation uses a single prefill node and a single decode node. Real production disaggregated serving (e.g., Dynamo) runs with hundreds of nodes. The paper does not evaluate or characterize multi-node CXL contention, lock manager scalability, or how the CXL bandwidth degrades as more nodes simultaneously access the shared pool. These are open questions for follow-up work.
TraCT is implemented as a standalone prototype (~5K lines C/C++) rather than integrated into vLLM, TensorRT-LLM, or SGLang. The paper demonstrates feasibility but does not provide a production-ready integration path. Future work could implement TraCT as a vLLM KV cache connector plugin, analogous to how MooncakeTransferEngine or LMCache integrate. The CXL shared memory layer would sit below the PagedAttention block manager.
Near-term (hardware-side):
Near-term (software-side):
TraCT is implemented as a userspace library that prefill and decode workers link against. The library provides three primary interfaces: the CXL shared memory allocator, the prefix index (hash table over CXL), and the GPU-CXL DMA wrappers. The ~5K line count excludes the vLLM Python integration shim.
For GPU-CXL DMA to work without bounce buffers, the CXL memory region must be registered with CUDA as pinned (page-locked) host memory. TraCT calls cudaHostRegister(cxl_base_ptr, pool_size, cudaHostRegisterDefault) at initialization. This tells the CUDA runtime that the memory is host-accessible and that the GPU can DMA to/from it directly via PCIe without staging through GPU-attached DRAM. The registration is process-local: each node registers its own mapping of the CXL physical range.
A fundamental challenge with shared memory across processes and machines is that virtual address mappings differ. Node A might map the CXL pool at virtual address 0x7f0000000000, while Node B maps it at 0x7e0000000000. Raw pointers stored in the shared hash table would be meaningless across nodes. TraCT solves this by storing CXL offsets (byte distance from the start of the pool) rather than virtual addresses. Each node translates: virtual_addr = cxl_base + offset. The base pointer differs per process, but the offset is universal.
When a prefill worker wants to publish a new prefix entry, it must acquire both locks in order:
clflush (not clflushopt) is used because it serializes: the instruction does not complete until the cacheline is evicted from the local CPU cache hierarchy. clflushopt is asynchronous and would allow a remote node to observe a stale value if it reads immediately after.
TraCT uses the same prefix hashing strategy as vLLM's RadixAttention and SGLang's prefix caching. The KV cache is divided into fixed-size blocks (e.g., 16 or 32 tokens per block). Each block is identified by a hash computed over all token IDs in the block concatenated with the hash of the preceding block. This chained hashing ensures that a block hash uniquely identifies both the content and position in the sequence. The CXL prefix index maps block_hash → CXL offset for every block currently resident in the pool.