Reusing shared context across processes and storage
Related requests often contain the same text at different positions. KMesh aims to keep one saved source for each shared segment and prepare the model state needed by each request. The work starts with safe restoration, then measures model outputs and storage costs before optimizing the loading path.
Shared source, request-specific model state
A language model saves attention state for text it has processed. This is its key/value (KV) cache. vLLM runs the model; LMCache stores saved state outside the engine. Reusing that state can avoid recalculating work for the same text. A token is a small piece of text.
When requests begin with identical text, they can share a cached prefix. The next target is text that appears after different instructions:
| Request | Illustrative prompt order |
|---|---|
| First request | Shared report → question A |
| Follow-up | New instructions → shared report → question B |
Restoration loads saved state into the follow-up's GPU memory. Repair recalculates selected model work because the text now has a different position and preceding context. CacheBlend supplies selective recalculation. Our TokenDance-style integration identifies the shared segments and their positions, keeps each request's working state private, and requires recalculation wherever saved state is missing.
Correctness before latency optimization
vLLM already manages GPU cache blocks, and LMCache already supports a separate cache process. Our recovery code must place state in the requested blocks, respect ownership across the process boundary and wait for GPU work to finish before memory is reused. These are engineering requirements for safe reuse. Their validation establishes correctness, rather than a new model algorithm or a performance gain.
Established findings
For each of four requests, generated tokens, saved attention data and next-token scores match exactly across three executions:
- Our TokenDance-style CacheBlend code loads and repairs state inside the model process, finishing one request at a time.
- The same repair code consumes state loaded through a separate cache process, still finishing one request at a time.
- The separate cache process supplies a group that advances all four requests through one model layer before moving to the next.
These comparisons establish that the process boundary and execution order leave this workload's results unchanged. All three use approximate reuse of saved state; equality to recalculating the entire prompt is a separate question.
A separate SSD comparison finds 3.7% shorter read-call time with DMA-BUF than with host staging, while complete restoration remains mixed. It runs children one at a time. Singleflight, which lets matching requests wait for one load, is off. The retention fix is enabled, and the benchmark explicitly evicts the saved sources before every child to force fresh SSD reads. The grouped model test uses sources in host RAM. These results were measured on one RTX 4090 on October 23–24, 2026.
Optimization decision
A follow-up GPU SHA-256 test removes the checksum's 12 MiB payload download, but our CUDA kernel makes complete restoration slower in every matched pair. CPU hashing remains the default. Another GPU candidate must improve complete restoration before adding read/hash overlap. Combining grouped model execution with SSD loading and retaining shared sources across children also needs its own evaluation.
21. Restoring state into vLLM's GPU cache
Before running the model, we verify that restoration places saved state in the right vLLM cache blocks. The GPU checks exercise our destination writes and position adjustment using allocations managed by vLLM.
vLLM divides its saved attention state into memory blocks. Those blocks can store tokens, attention heads and key/value data in different orders. An attention head is one of the model's parallel attention calculations. The restore code must find the right addresses for each supported arrangement.
Position matters too. The model encodes a token's position by rotating its key vectors, a method called rotary position embedding (RoPE). When shared text moves, the restore code adjusts that rotation. This adjustment handles position; it does not by itself fix the effect of different preceding text. The real-model comparison checks the additional recalculation needed when the preceding context changes.
All 32 required synthetic GPU cases passed on October 23. They check that values stay unchanged, moved keys receive the expected positional adjustment, and memory outside the requested destination stays untouched. These use small, constructed arrays rather than a language model, so they establish correct copying and addressing, rather than answer quality or speed.
Array layouts, numerical checks and test runtime
The controls cover head-major and token-major storage (whether heads or tokens are grouped first in memory), separate key/value planes and formats that pack keys and values together. They include multiple saved-object groups, partly filled final blocks and repeated reuse of destination slots. These storage orders describe memory layout. Layer-major execution describes the order in which requests pass through model layers.
Values and keys that stay at the same position preserve their raw BF16 bits, including negative zero. BF16 is the two-byte floating-point format used for the saved state. Moved keys match an independent CPU rotation with absolute tolerance 0.03125 and zero relative tolerance. Destinations start with invalid data so unintended writes are visible. Each synthetic group has four layers, two heads, head width 16, eight-token chunks and four-token blocks.
The RTX 4090 runtime uses Python 3.13.15, PyTorch 2.13.0+cu130, CUDA runtime 13.0 and pytest 9.1.1, with two OpenMP/MKL CPU threads. The source and native binaries are pinned in the GPU qualification instructions. Some handler tests use stand-ins for storage and event transport; the array addressing and GPU operations are real.
22. Owning shared state across processes
Sharing saved state through LMCache's existing cache process requires clear ownership: a request must be allowed to use each allocation, and that allocation must remain alive until the request's work finishes. The tests check these rules across the process boundary.
The model worker and cache service run as separate processes on the same machine. The cache service holds the shared originals while individual requests come and go. Before it accesses GPU memory, the worker registers it: it supplies the memory handles, describes their layout and establishes which client owns them. The service must distinguish that exact allocation from a later allocation at the same address.
The tested service keeps ownership tied to the actual client and allocation. A replacement client cannot reuse an old registration merely by claiming the same instance number. Closing a registration stops new work, but its buffers remain reserved until already accepted copies and GPU operations finish.
Consider a cancelled request whose copy is still running. If its destination were immediately handed to another request, the old copy could overwrite the new request's state. The service therefore waits for physical completion before releasing memory. Losing a heartbeat or cancelling a request is insufficient proof that the GPU has stopped.
Detailed ownership checks and their limits
The following prerequisite tests check client identity, ordering, memory lifetimes and cleanup. Some run on the CPU with simulated device errors; others run actual GPU transfers between processes. Counts overlap and must not be added together or interpreted as numbers of model-serving runs.
| Control | Passed cases | Scope |
|---|---|---|
| GPU storage layouts and position adjustment | 32 | Constructed arrays check numerical results and destination addresses. |
| CPU registration and transfer ownership | 292 | Real CPU registrations and both request transports; device failures are simulated. |
| GPU/host copies across processes | 6 | Real copies, completion waits and injected errors. |
| vLLM connector and configuration controls | 414 | Configuration behavior, including refusal of unsupported multiprocess recovery. |
| Wait before publishing CPU snapshots | 316 | Complete private copies before sharing; check ownership with both transports. |
| Wait before publishing GPU snapshots | 6 | Both transports wait for producer writes and retain buffers if cleanup fails. |
| Direct CUDA memory imports | 3 | Import between processes, release shared references, then retry an injected failure before the driver call. |
| Failed imports and closes | 6 | Retry only when safe; reserve uncertain mappings and check all shared references. |
| Private copies of position tables | 323 CPU + 4 CUDA | Hold memory before importing it, wait for writes and keep buffers after failed cleanup. |
| Managed imported GPU allocations | 327 CPU + 9 CUDA | Wait for initialization and transfers, release all references and make repeated close safe. Active GPUDirect Storage is refused in this profile. |
| Store and restore text segments | 341 CPU + 24 CUDA | Check unchanged sources, unaligned destinations, missing/corrupt data and cleanup; includes ten direct-import lifetime cases. |
| Segments from inside a saved prompt | 341 CPU + 36 CUDA | Save from token five in 24 layers, restore earlier and later, and retain buffers after failed cleanup; overlaps earlier cases. |
| Service-controlled memory release | 331 CPU + 10 CUDA | Both transports check receiving ownership; the exporter can free and reallocate after acknowledged release while the importer stays alive. |
A server boot, storage generation, worker registration and accepted operation each have an explicit identity. A generation identifies a particular version of a resource, preventing a late completion from referring to its replacement. The service keeps exact buffer versions while completion is uncertain and refuses store clearing or shutdown with unfinished work.
Every selected setup, test body and teardown must pass; skipped and expected-failure cases do not qualify. The 414 vLLM cases test configuration and connector behavior, including refusal of unsupported multiprocess recovery; they do not run a model. ZeroMQ and gRPC are the two tested request transports.
The cache service derives memory-layout and positional-rotation facts from registered state. It does not load or verify the worker's declared model weights, tokenizer or configuration. Client identities prevent accidental cross-client reuse; they do not authenticate a hostile client.
23. Completing GPU copies before memory reuse
Requests can fail while a GPU transfer is still running. We test that the recovery code waits for accepted transfers before releasing memory, including when the first cleanup attempt fails.
The memory stays reserved until pending work has actually finished. GPU copies can run asynchronously: the call that submits a copy may return before the copy completes. The service must also wait for the model's earlier writes before reading their results.
Six tests exercise real copies between GPU memory and host RAM with separate processes. Each direction has a successful case, an error whose pending work can be completed, and an error where the first attempt to wait is refused. In that last case, the source and destination remain held until a later wait succeeds. All six passed.
The implementation calls this wait a drain. Draining finishes already submitted work; it does not mean submitting the failed operation again. This is what makes it safe to release buffers or recalculate a failed request into them.
How the copy-ordering tests work
An exporter process shares real CUDA interprocess communication (IPC) handles with the test service. A download waits for an intentionally delayed producer on a separate GPU stream, then copies the position-rotation tables and compares exact host bytes. An upload starts from a completed private host snapshot, copies into a private GPU allocation and compares bytes after the copy stream finishes. Errors are injected after actual copy submission.
The BF16 paged allocation has shape [2, 16, 4, 2, 8]; the FP32
rotation table is [64, 8], or 2,048 bytes. A sequence of 512 matrix
multiplications on FP32 [2048, 2048] inputs keeps the producer
busy. This deliberately tests ordering, rather than modelling serving latency.
The six-case transfer profile supplies the receiving identity explicitly; later registration and service tests exercise actual transport requests. The exporter stays alive through cleanup. Device faults and exporter death are untested. These are ordinary CUDA IPC and host/device copies, with no DMA-BUF storage I/O. Finishing a copy and closing an imported memory mapping are separate checks; exporter teardown also needs the service's release acknowledgement.
24. Evaluating model outputs and DMA-BUF loading costs
For each request, the generated tokens match when loading inside the model process and when loading through the separate cache process. Their saved attention data and next-token scores also match exactly. DMA-BUF gives a small, consistent reduction in read-call time, but no consistent reduction in complete restoration time. These are separate comparisons.
Model and workload
The model is Qwen2.5-0.5B-Instruct, a small model with 24 layers. A layer is one stage of the model's computation; each request passes through all 24. One leader request supplies saved attention state for four shared text segments, totalling 416 tokens. Four follow-up requests, called children, each have a 512-token prompt and place those segments at different positions.
The shared-segment workload and the CacheBlend comparison
The TokenDance-style case supplies the multi-request workload and sharing information; CacheBlend supplies the selective recalculation. Original CacheBlend already addresses combining cached text chunks with different preceding context. Here the application knows which four children will reuse which segments. Our integration carries those exact segment identities and positions into each request and can coordinate the children as a group.
The experiment gives the cache process an unchanged source and restores it into each child's private model state. It then coordinates the children without letting one request alter another's working data. The prompts, shared segments and repair settings stay fixed so the comparison isolates loading and execution order.
A stock CacheBlend workload would also be a valid way to study DMA-BUF loading. This experiment measures our existing multi-request integration. It establishes no advantage of our additions over stock CacheBlend. A direct comparison would need a separate stock CacheBlend control with clearly defined segment inputs and recomputation settings, alongside full-prompt recalculation.
CacheBlend repair and the TokenDance-style integration
It uses our TokenDance-style recovery code built on LMCache's CacheBlend implementation. LMCache calls the feature CacheBlend, or cache blending. It implements the selective recalculation approach from the CacheBlend paper: reuse saved attention state and recalculate selected tokens to account for their changed preceding context.
In our fork, the one-request entry point is
LMCBlender.blend(). Our TokenDance-style additions supply explicit
shared text segments and their positions, give each request its own execution
state, and force recalculation of every position without restored data.
The four-request version uses our LMCBlender.blend_group()
extension. This is our reproduction built with LMCache, rather than the
TokenDance authors' implementation. The first comparison already includes
our additions; it is not an unmodified upstream CacheBlend run.
First we run that extended serial implementation with loading inside the model process. Then we load the same saved segments through the separate cache process, place them in each child's private GPU memory, and run the same repair algorithm. Here serial means finishing one child before moving to the next. The shared source data stays unchanged; each child has its own working copy because repair changes model state.
Repair is needed because a token's saved state depends on the text before it, as well as its position. Adjusting key rotation fixes the position component. CacheBlend's selection determines which restored positions receive additional work, and our extension adds every position missing restored state. This is approximate reuse of earlier computation; the comparison is against the same method running serially, rather than recalculating the entire prompt.
Model outputs across the cache-process boundary
No differences were observed against that reference in this test. All four children have bit-for-bit identical saved keys and values and logits, the scores used to choose the next token. Their generated tokens and choices of which positions to recalculate also match. We check those choices at every layer: four children × 24 layers gives 96 comparisons.
Seven failure controls also pass, including missing or corrupt saved data and failure after GPU work has been submitted. Recalculation is allowed only after pending work finishes and releases the destination memory. If cleanup cannot complete, the request must wait or fail safely.
DMA-BUF loading measurements
We compare two ways of loading the saved segments from an NVMe SSD, a fast PCIe-connected solid-state drive. The model, data and repair algorithm stay the same. Children still run one at a time.
- Host staging: SSD → locked host RAM → GPU memory. The RAM buffer is pinned so the device can access it throughout the transfer.
- DMA-BUF: SSD → GPU memory through a registered buffer shared with the kernel. DMA-BUF is Linux's buffer-sharing interface; this route avoids the host staging step for the storage read.
This is a forced-read storage comparison. Singleflight is off; the retention fix is present and enabled in both routes. We run seven matched pairs, alternating which route goes first. Each pair runs all four children through each route, one child at a time.
Singleflight and shared-source reuse
The earlier engine singleflight mechanism joins requests with an identical prefix, so they can adopt one restored prefix inside vLLM. This workload puts shared text at different positions after different input. Each child therefore keeps its own position-adjusted and repaired model state. That exact-prefix mechanism is not the mechanism for sharing these interior segments. Prefix caching is disabled in this fixture so recovery is attributed to the explicitly named segments.
Sharing one stored source is still useful. Several children can use the same unchanged saved bytes while keeping their repaired GPU copies private. Retaining that source across children, and joining simultaneous loads of it, are the relevant storage optimizations. This particular transfer test runs children serially and forces a fresh load for every child, so it can time the SSD routes. The combined shifted-segment read-once serving test remains to be evaluated.
The test explicitly removes the four retained objects from LMCache's memory tier before every child. Each child therefore reads the same saved objects from SSD again: 12 MiB per child, 48 MiB across four children. This eviction makes every child exercise the selected SSD route instead of timing a hit in the memory cache. The repeated reads are deliberately requested by the benchmark, rather than caused by losing the retained copy unexpectedly.
The earlier read-once experiment had a different setup: singleflight was on, and the fixed retention kept one 48 MiB ancestor available across the children. It read that ancestor from SSD once. Here, forced eviction takes away that cross-child reuse to compare the two storage routes.
| Setting | Earlier exact-prefix read-once experiment | This shifted-segment SSD comparison |
|---|---|---|
| Engine singleflight: one request loads while matching followers wait | On. | Off. Children run one at a time. |
| Fixed external retention | On. Keep the loaded ancestor for subsequent children. | On. The benchmark explicitly evicts the four objects before every child. |
| Resulting SSD payload reads | One 48 MiB ancestor read across the group. | 12 MiB per child; four reads of the source set, totalling 48 MiB. |
On a small screen, scroll the timing table sideways to see every column.
| Timed part of the work | Median paired change | Median paired percentage | Pairs faster with DMA-BUF | Range of paired changes |
|---|---|---|---|---|
| Storage backend read calls | −0.152 ms | −3.7% | 7/7 | −0.273 to −0.012 ms |
| Checking the loaded data for corruption | +0.722 ms | +10.5% | 0/7 | +0.556 to +1.288 ms |
| Complete restoration into the child's GPU memory | −0.114 ms | −0.7% | 4/7 | −0.890 to +1.139 ms |
| Restoration, instrumented model repair and source cleanup | −1.613 ms | −0.8% | 5/7 | −5.009 to +4.070 ms |
Negative values mean DMA-BUF took less time. For each pair we first take the median of its four children for each route, then compare those two medians. The table reports the median of those seven paired differences and ratios. The timed parts overlap: reads and corruption checking are inside restoration, and restoration is inside the final row. They must not be added together.
The storage read calls are faster in every pair, by a median 0.152 ms. That benefit does not consistently carry through to complete restoration, which is faster in four pairs and slower in three. A typical full restore takes about 17 ms per child; the outer interval with model repair and cleanup takes about 189 ms. These are instrumented replay timings, rather than measurements of how long a serving client waits for its first token.
The path still has costs beyond the read. To check for corruption, the GPU route copies the entire 12 MiB payload back to the CPU for a SHA-256 checksum. It also copies the shared GPU source into each child's private working memory. The table measures those remaining costs too. It does not demonstrate a path with no host copies.
GPU SHA-256: exact checksums, slower restoration
The tested GPU checksum removes the payload download but makes complete restoration slower in all seven matched pairs. We keep CPU hashing as the default for this profile. The result applies to our experimental CUDA kernel and the existing whole-object checksum format.
The original storage comparison above used CPU SHA-256 in both routes. This follow-up holds the DMA-BUF route fixed and changes only the checksum implementation. Both arms keep the retention fix enabled, singleflight off and explicit eviction before every child. Each child reads the same four padded 3 MiB objects from SSD, then uses the same CacheBlend repair code.
Before timing, every saved object receives an independent CPU digest. The GPU implementation must match it. During restoration, it hashes the same complete bytes, including padding, before position adjustment. Its four 32-byte digests return 128 bytes per child, replacing the checksum's 12 MiB payload download. This byte reduction is specific to the checksum; full model-state captures remain active.
| Timed part of the work | CPU checksum median | GPU checksum median | Median paired change | Pairs faster with GPU hashing |
|---|---|---|---|---|
| Storage backend read calls | 3.909 ms | 4.048 ms | +0.140 ms | 2/7 |
| Checking source bytes for corruption | 7.812 ms | 249.388 ms | +241.524 ms | 0/7 |
| Complete restoration into the child's GPU memory | 17.319 ms | 259.192 ms | +242.187 ms | 0/7 |
| Restoration, instrumented model repair and source cleanup | 190.037 ms | 435.585 ms | +244.127 ms | 0/7 |
For each pair, take the median of its four children for each arm. The table shows the medians across seven pairs and the median of their paired changes. Positive changes mean GPU hashing is slower. Read calls and checking are inside restoration, which is inside the final row; these intervals must not be added.
All model comparisons pass. The same-source reference and sixteen registered runs cover two poisoned-buffer arrival checks and fourteen timed arms. Each registered run matches the reference's raw keys, values, next-token scores, generated tokens, retrieval masks and all 96 per-layer recalculation choices. Maximum numerical differences are 0.0. Every arm completes its native reads and releases the source buffers with checked physical cleanup.
Four whole-object hashes limit parallel work
Our kernel assigns one GPU thread to each complete object. Standard SHA-256 processes each message's 64-byte blocks in order, carrying the previous result forward. A 3 MiB object has 49,152 data blocks, followed by the hash's padding block. The four objects supply only four independent chains.
A standalone test isolates this computation using deterministic synthetic bytes. Across fifteen trials with rotating method order, hashing the full 12 MiB set takes 5.512 ms with CPU hashing, including the download, 249.010 ms with four serial GPU calls, and 62.252 ms when one GPU call hashes all four objects concurrently. The concurrent case is an opportunity check; the model restore still hashes sources one at a time. Returning fewer bytes cannot compensate for this kernel's much longer computation.
This does not rule out a faster GPU implementation. It does show that moving our existing whole-object SHA-256 calculation onto this kernel is a poor optimization. Keep the measured CPU path while evaluating another candidate.
Checksum qualification, runtime and reproduction
The standalone checks cover 66 zero, all-one and random byte cases across
empty and unaligned inputs and SHA-256 padding boundaries. They also check a
published abc vector and BF16 raw bytes. Four byte corruptions change only
the affected object's digest and match an independent CPU checksum. A producer
CUDA event orders writes before hashing on another stream. These are byte and
ordering controls, not device-fault injection.
The model comparison uses the same 24 GiB CUDA GPU and runtime as the
GPU validation setup, with two OpenMP/MKL CPU threads.
The CUDA kernel is built with NVCC 13.4.92, optimization enabled and native
architecture 89 code. LMCache remains at fe15939e, vLLM at
9df1493c and the model at its pinned revision. The
checksum reproducer
changes the dedicated experiment's observer; it leaves production defaults
unchanged. It uses our standard-based CUDA kernel. cuPQC was not tested.
Follow the
GPU checksum guide
to build the kernel, run standalone checks and select
defconfig-kmesh-registered-gpu-checksum-cuda. With the source,
model and reference paths configured, make kmesh-registered-storage-pair
runs the seven checksum pairs. Both arms must first load correct bytes after
the entire free 64 MiB source pool is filled with invalid data.
GPU hashing starts only after the existing storage path completes its reads. The service keeps source leases through checking and restoration, and its existing failed-operation handling retains memory until an actual device drain. Source CPU checks and GPU warmup happen before timed children. Full numerical captures and duplicate reference storage remain active. These are instrumented restore measurements, not production serving latency or total memory savings.
Further optimization targets
Overlapping independent SSD reads and GPU checks remains untested. It should first use a checksum implementation that can improve complete restoration. Changing to independently hashed smaller pieces could expose more parallel work, but it would change the integrity format; combining those digests does not reproduce the current whole-object SHA-256. That needs a separate design and matched comparison.
CUDA streams
can overlap independent GPU work. Our io_uring reads are not
automatically ordered in a CUDA stream: any new overlap must establish external
I/O completion and GPU visibility before hashing, then retain buffers until
both storage and GPU consumers finish.
This test is separate from the earlier read-once retention result. Here, forcing a fresh read for every child causes 48 MiB of reads across four children. In the earlier test, retention kept one 48 MiB ancestor available and removed repeat reads. The equal 48 MiB totals describe different workloads.
Storage workload, hardware and correctness checks
The RTX 4090 system has a Ryzen 9 9950X3D and Samsung 990 PRO 4 TB SSD. The backing storage uses XFS regular files on the patched DMA-BUF-capable Linux 7.3-rc3 kernel. The GPU validation setup records the Python/PyTorch/CUDA runtime; OpenMP/MKL use two CPU threads. Both routes use a 64 MiB source memory pool, a 1 MiB metadata area, queue depth 32, maximum transfer size 128 KiB and the same 1 GiB locked-memory allowance. Fresh files are fully initialized and synced before use. Hardware caches can remain warm.
The 416 valid tokens use 4.875 MiB of state. The storage format pads each
of the four segments to a 256-token object, giving 12 MiB read per child.
Each object is 3 MiB:
256 tokens × 24 layers × 2 key/value planes × 2 heads × 64 elements × 2 BF16 bytes.
A child issues 96 native payload-read operations, or 384 across four children.
These are software read operations, not traced physical NVMe commands.
Before admitting timings, each route passes a separate model test in which the freed 64 MiB source pool is filled with invalid numbers. A successful load must therefore bring real data from storage; leftover GPU bytes cannot fake it. The two qualification runs and fourteen timed runs all match the reference's raw keys, values, next-token scores, generated tokens and recalculation choices. Maximum absolute key/value and score differences are 0.0.
The reproducer retains duplicate reference storage and numerical instrumentation. These checks make this a controlled transfer-path comparison, rather than a production memory-footprint or serving-performance result.
The frozen model configuration uses LMCacheConnectorV1 with our
KMesh extension and enable_prefix_caching=false. It does not
activate the earlier LMCacheMPConnector exact-prefix singleflight
gate. The storage manager uses prefetch_policy=retain and
prefetch_join_overlaps=false, so its optional joining of simultaneous
loads is also off. The measured LMCache source includes the earlier retention
fix. The runner's StorageObserver.cold() explicitly evicts the
source set before each child.
Model and implementation qualification details
Serial input tests pass 649 CPU and 112 CUDA cases; the host/GPU source-pool extension passes 661 CPU and 184 CUDA cases. Counts overlap. They check partial segments, packed key/value views, immutable source ownership, private working buffers and cleanup. Their model-layer transforms are synthetic; the actual Qwen model comparison is the separate result described above.
The model cache has per-layer shape
[blocks, 2 KV heads, 32 slots, 128 content], with K64 followed by
V64 in each head. The two-head axis is not a key/value axis. Restored keys
already include their destination rotation and must not be rotated again.
Serial tests pin LMCache
3f2078a8;
the host/GPU source-pool and NVMe profiles pin
fe15939ed14f680fdbbf6ebc0df2a3d97fd18266. Both use vLLM
9df1493cae0b98380a3c3ecb9b2d41776a6d8735. Use each profile's exact
source and runtime pins rather than a moving branch tip.
Reproduce the paired registered storage comparison
Select defconfig-kmesh-registered-storage-cuda, inspect
make kmesh-registered-plan and set the paths described in the
matched storage guide.
Use its pinned LMCache fe15939e and vLLM 9df1493c
sources, runtime and generated reference. Configure enough locked memory for
the host registrations, then run make kmesh-registered-storage-pair.
The default seven pairs alternate route order. Both routes must first pass
the invalid-data-filled source-pool checks described above; those checks are
called poisoned-arena qualifications in the guide.
The reproducer creates fresh regular files in the selected external capture directory. It does not format a device. Keep raw logs, tensors, journals and backing files outside public Git. Duplicate reference storage and numerical instrumentation remain active; this is a bounded path comparison.
Reproduce registered model repair and its failure controls
The registered replay guide lists source, runtime, model, trace and external capture paths. Generate the independent TokenDance reference using its own source pins, then keep a clean checkout of each registered profile's source. Both the new reference and its registered counterpart use the same checkout and checked current configuration.
make defconfig-kmesh-registered-inputs-cpu
make kmesh-contracts-plan
# Set the pinned source, matching Python and external output paths, then run.
make kmesh-contracts
make defconfig-kmesh-registered-inputs-cuda
make kmesh-native-plan
make kmesh-native
make defconfig-kmesh-registered-model-cuda
make kmesh-registered-plan
Follow the guide's reference-first workflow with
make kmesh-registered and
make kmesh-registered-verify, then run
make kmesh-registered-controls against the independently verified
ordinary baseline. Use fresh capture directories outside all source checkouts.
These commands qualify one separate cache process and one GPU worker.
Earlier storage-only qualifications
These earlier tests check moving saved segments without running model repair. The initial profile passes 341 CPU cases and 24 CUDA cases on the RTX 4090 runtime above. The CUDA set contains ten raw service lifetime controls and fourteen native span cases, covering both ZeroMQ and gRPC. These counts overlap the earlier profiles.
The interior-source extension also passes: 341 CPU cases and
36 CUDA cases at LMCache e23d4acd29420a0258a9666b98d9a10fdec12b53.
It saves a segment beginning at source token five in 24 synthetic layers, using
both token-major (NHD) and head-major (HND) layouts, and restores it at positions three and nine. Values
remain bitwise exact; independent key rotation and untouched destination slots
pass. If gathering the source fails, buffers remain reserved until pending work
finishes. An incomplete source is never made available for reuse. Each layer
view keeps its exporting allocation alive. This profile uses complete storage
chunks.
The worker registers its BF16 attention buffer and private position tables. To save a segment, the service holds the exact allocations, waits for source writes, copies keys and values into locked host RAM and confirms that every chunk was accepted before making the source available. Unique keys distinguish allocations. Buffers used by unfinished I/O stay reserved even if a software lock expires.
The test recycles the original GPU slots before restoration.
It stores sixteen synthetic tokens as two eight-token chunks, then poisons the
source GPU cache with invalid data. Restoration places them at token position
three in GPU blocks deliberately arranged out of order. Values match raw BF16 bits; keys match an
independent CPU RoPE calculation with rtol=0.012 and
atol=0.025. Untouched prefix and tail slots remain poisoned.
A second restore at the unchanged position passes from the same saved source,
whose checksums still match. Position adjustment uses a private GPU working
copy, preserving the shared stored bytes.
The paged view is [2, 16, 4, 2, 16]; the FP32 rotary table is
[64, 16]. The exporter allocation and host-RAM cache are each
64 MiB; the host allocation matches its allocator's registration unit. Source
writes are submitted behind 512 FP32 matrix multiplications on
[2048, 2048] inputs to challenge producer ordering. This synthetic
fixture measures correctness, not serving latency.
Repeating the same request returns its saved status without launching the GPU operation again. Wrong clients, changed handles and missing or corrupt sources fail before destination writes. Failed or outdated stores cannot become reusable sources. An injected error after GPU submission, combined with a refused completion wait, keeps the source and destination reserved until a later wait succeeds. Cleanup does not resubmit the operation. Device faults and packet loss are not injected by this profile.
Reproduce native span storage and physical cleanup
Use the prepared environment and binding-generation instructions in the
CPU ownership guide
and CUDA guide.
For the interior-source profile, pin LMCache
e23d4acd29420a0258a9666b98d9a10fdec12b53 and paired
vLLM source 9df1493cae0b98380a3c3ecb9b2d41776a6d8735.
The public component branches remain
LMCache
and vLLM
2026-10-23-feature-kmesh-mp-recovery. Select exact pins rather than
moving branch tips; regenerate that LMCache source's gRPC bindings.
# CPU ownership, host-RAM storage and buffer lifetime
make defconfig-kmesh-interior-spans-cpu
make kmesh-contracts-plan
KMESH_CONTRACTS_SOURCE=/path/to/pinned/LMCache \
KMESH_CONTRACTS_VLLM_SOURCE=/path/to/pinned/vllm \
KMESH_CONTRACTS_OUTPUT=/path/outside/checkouts/cpu-capture \
KMESH_CONTRACTS_PY=/path/to/prepared/python make kmesh-contracts
# Separate-process native store/restore and raw release controls
make defconfig-kmesh-interior-spans-cuda
make kmesh-native-plan
KMESH_NATIVE_SOURCE=/path/to/pinned/LMCache \
KMESH_NATIVE_OUTPUT=/path/outside/checkouts/cuda-capture \
KMESH_NATIVE_PY=/path/to/prepared/python make kmesh-native
Use fresh capture directories outside source checkouts. Every selected setup, body and teardown must pass. The helpers verify source and loaded schema hashes; the CUDA profile also pins native binaries and checks the complete exit log for unreleased exporter warnings. Saved-capture verification needs its producing helper revision. Raw receipts, logs and tensors remain outside public Git. Receipt consistency does not independently attest hardware execution. Earlier profiles retain their original pins, defconfigs and narrower scopes.
25. Testing layer-major execution across four related requests
We test a layer-major execution schedule for four related requests. Each child advances through one model layer before any child moves to the next. Bringing the children to the same model stage gives the runtime a place to coordinate work on their shared segments.
This experiment compares that schedule with finishing one child at a time. It checks model outputs and recovery after a failed child while each request keeps its own mutable state.
Layer-major execution
Label the four children A, B, C and D. Each must pass through the model's 24 layers. There are two execution orders:
| Order | What happens |
|---|---|
| One child at a time (serial) | Run A through layers 1–24, then B through layers 1–24, then C, then D. |
| One layer across the group (“layer-major”) | Run layer 1 for A, B, C and D. Then run layer 2 for A, B, C and D. Continue through layer 24. |
“Layer-major” describes that loop order. It does not describe how data is arranged in memory, and it does not mean combining the four children's math into one batched calculation. This implementation still runs each child's tensor operations separately on one GPU worker.
Prior work and the scope of this experiment
The direct precedent is TokenDance's KV Collector, described by Zhuohang Bian and coauthors in 2026. Section 4.2 describes coordinating related requests at each model layer and batching their position adjustment and difference calculations. Section 5 describes a separate retrieval and computation generator for each request, advanced together across layers. TokenDance uses CacheBlend's selective recomputation as its default backend.
We apply this existing design rather than introduce a new KMesh scheduling algorithm. Our current test applies it to saved state supplied by a separate cache process, with private child buffers and checked failure cleanup. Tensor calculations remain separate. The test establishes correct outputs and cleanup; a speed or memory-capacity benefit remains unmeasured.
Shared sources and private request state
The group first loads all four segments for all four children: sixteen placements in total. The original saved segments are shared and remain unchanged. Each child keeps its own GPU destination blocks and working buffers, because its surrounding text and repair calculations can differ. The service checks every member before making the group's restored inputs available to the model.
The saved sources in this group test live in LMCache's host-RAM cache tier. Some implementation files call it “CPU-L1”; that name means a software cache in ordinary system RAM, not the processor's tiny hardware L1 cache. A separate cache process supplies the data to one model worker. The SSD comparison ran children one at a time. Combining that loading path with grouped execution remains untested.
Measured comparison
On October 24, the in-process serial reference, the serial path using the separate cache process and this group path all produced bit-for-bit identical keys, values and next-token scores. All four children's generated tokens and all 96 per-layer recalculation choices also match. Each child restores the same 416 shared tokens within a 512-token prompt.
Recovery after one child fails
We deliberately fail child B after it finishes its first actual model layer. A, C and D finish with the serial reference's generated tokens and recalculation choices. B waits for its pending work to finish, discards all restored state for its prompt, and retries by recalculating the whole prompt without reuse. Its generated tokens match the ordinary recalculation reference. All shared source handles close with no pending work.
This failure test checks safe fallback and sibling isolation. The mixed repaired/recalculated run checks generated tokens and cleanup; the successful group run is the one with the complete raw-state and next-token-score comparison.
Group source and supporting safety tests
The group pins LMCache
b9b5687b
and vLLM 9df1493cae0b98380a3c3ecb9b2d41776a6d8735, with the runtime
recorded in the GPU validation setup. Its supporting
profiles pass 694 CPU and 208 CUDA cases,
overlapping earlier profiles. They test simultaneous inputs, private writeback,
early close and refusal to release memory while work remains pending, across
both memory-layout families and both request transports.
Group admission binds the exact ordered requests, resource versions, tokens and declared segments. Already adjusted keys cannot receive the position rotation twice. CPU coordination alone does not establish compatibility of state split across multiple GPUs.
Reproduce the registered group and member-failure control
Use the source pins in the group profile and follow the registered group guide. Run the CPU and native prerequisites before the model comparison:
make defconfig-kmesh-registered-groups-cpu
make kmesh-contracts-plan
# Set the pinned source, interpreter and external capture paths.
make kmesh-contracts
make defconfig-kmesh-registered-groups-cuda
make kmesh-native-plan
make kmesh-native
make defconfig-kmesh-registered-group-model-cuda
make kmesh-registered-plan
Capture and independently verify the same-source serial reference first.
Then run make kmesh-registered with registered serial execution and
with KMESH_REGISTERED_MODEL_EXECUTION=collective-lockstep, using
fresh external directories and make kmesh-registered-verify for each.
Finally run make kmesh-registered-group-failure against the verified
serial and ordinary references. Unknown physical completion must keep blocks
reserved; it cannot authorize fallback or destination reuse.