feat(exact-prefix): add direct CUDA transfers for Fluxon Plan API - #5
Draft
yJader wants to merge 11 commits into
Draft
feat(exact-prefix): add direct CUDA transfers for Fluxon Plan API#5yJader wants to merge 11 commits into
yJader wants to merge 11 commits into
Conversation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
This PR replaces the legacy per-tensor Fluxon path used by exact-prefix reuse with a synchronous Plan-pointer data path that transfers LingBot KV and skeleton latents directly between CUDA tensors and Fluxon registered-host segments.
The new path:
local_fast_put_start()+ batched CUDA D2H copies +local_fast_put_commit();get_start()/get_transfer()+ batched CUDA H2D copies;put_tensor/get_tensorpath, CPU tensor staging, and:specsidecars from exact-prefix traffic;fluxon_pyonly through the configured Python environment and logs the loaded package/native-extension identity;WorldKVManager.evict_blob()entry point is called.Related Fluxon API work: Tele-AI/Fluxon#42.
Motivation
The previous Fluxon exact-prefix path operated one tensor at a time and materialized CPU-owned tensors around the DLPack interface:
That model had three problems for LingBot prefix reuse:
Fluxon's Plan API exposes writable or readable value pointers with explicit lifecycle methods. This PR uses those pointers as the boundary between CacheSeek's runtime layout logic and Fluxon's storage ownership.
Architecture
The main implementation is split across:
cacheseek/stores/cuda_transfer.py: injectable CUDA runtime facade andPointerCopydescriptors;cacheseek/stores/fluxon.py: Fluxon bytes adapter plus thin wrappers for the Plan API;cacheseek/stores/tier.py: synchronousPlanTensorTierStore;cacheseek/reuse/exact_prefix/manager.py:materialize_path()capability dispatch;cacheseek/reuse/exact_prefix/telefuser_lingbot.py: direct ring-copy descriptors, private latent targets, and layout isolation;examples/exact_prefix_reuse/e2e_telefuser_lingbot.py: Fluxon example selection now usesPlanTensorTierStore.Write path
LingBotWorldKVBinding.on_chunk_finalized()now passes detached CUDA views for the finalized chunk instead of cloning them to CPU.The binding keeps the backend split explicit: the Fluxon Plan path receives those CUDA views, while LocalDisk and other generic tensor stores receive detached, caller-owned CPU clones. This preserves the generic adapter's copy-before-overwrite contract and keeps CUDA tensors away from
LocalDiskTensorStore.put_tensor().numpy().For each skeleton latent or KV chunk,
PlanTensorTierStore:{locator}:L{layer}:k/vkeys;nbytes, because onelocal_fast_put_start(keys, value_len)applies a single value size to every key in that Plan;on_ready()only after every commit succeeds.BlobHandle.readytherefore remains false until all KV values are committed. A failure before a Plan is committed callsput_abort()for every live uncommitted Plan. If a CUDA batch was only partially submitted, its stream is synchronized before those aborts begin.Although the manager method is still named
put_async(), the Fluxon Plan implementation is intentionally synchronous. Itsflush()method is a no-op; LocalDisk retains the existing asynchronous generic tensor adapter.Read path
The hit path restores private skeleton latents before mutating the KV ring:
For skeletons, the binding allocates private GPU targets using the current runtime shape, dtype, and device.
materialize_skeletons()fetches all latent keys in one Plan request and copies them in one H2D batch. A missing latent cancels the handle and leaves runtime-visible restore state untouched.For KV,
WorldKVManager.materialize()detects the store'smaterialize_path()capability and passes the completesink + recent-windowpath toPlanTensorTierStore.KV keys are ordered chunk-major:
Each chunk is one atomic group:
The current implementation consumes only a complete requested window. A partial transferable prefix is cancelled and treated as a cache miss because it is not necessarily equivalent to the
sink + recent-windowpath of a shallower trie node._RingKVWindow.build_seed_copies()translates each Fluxon chunk pointer into contiguous copy runs in the physical TeleFuser ring, including rolled layouts with sink frames. KV indices are updated only after the H2D batch synchronizes successfully. Read views are then released infinally.Fluxon Plan and CUDA lifetimes
Both
get_transfer()andlocal_fast_put_start()return a pointer to a smallu64table:FluxonKVStore.decode_plan_ptr()validates the address, magic, and pointer count before exposing any value pointer.Lifecycle rules enforced by the adapter:
get_transfer()orcancel_get_transfer();cudaMemcpyAsync()submission;cudaMemcpyAsync()fails after earlier copies were submitted, the stream is synchronized before any Plan is aborted or its views are released;release_views()runs;BlobHandle.readyand runtime resume indices are never published before their corresponding transfer/commit succeeds.Before the first transfer,
wait_local_segments_ready()returns Fluxon owner mappings. The CUDA facade registers both write and read mappings, handles read-only fallback and already-registered results, and deduplicates registrations by(ptr, len, generation).Layout isolation
Plan values contain raw tensor bytes and no shape/dtype metadata. The read path derives byte lengths and offsets from the active runtime and validates them against
BlobHandle.nbytes/n_layers.The exact-prefix namespace fingerprint now includes:
Changing the storage format or runtime layout therefore creates a different namespace. Legacy DLPack/CPU-Plan values and incompatible layouts become cold misses instead of being reinterpreted.
Compatibility and scope
PlanTensorTierStore.KVStore.put/get(bytes).FluxonKVStore.put/get/remove/list_keysremain available.TensorKVStore,TensorStoreTierStore, andLocalDiskTensorStoreremain available for generic tensor backends.get_layer()/seed_layer()fallback; generic writeback explicitly stages owned CPU tensors.WorldKVManager.evict_blob(node)now removes the node's{locator}:L{layer}:k/vPlan values while retaining its lightweight skeleton.FluxonKVStoreuses normal Python package resolution and never scans parent directories or modifiessys.path.PYTHONPATH.fluxon_pyversion/path and each loadedfluxon_pyo3extension path/SHA256.cuda-bindings>=12.6dependency is isolated in thefluxonoptional extra.cudaandfluxonpytest markers.Correctness coverage
The unit and fake Fluxon/CUDA tests cover:
sys.pathmutation;Tests
Run on the reviewed CacheSeek worktree:
Results:
asyncio_modewas unknown because the active pytest environment did not loadpytest-asyncio);Real-device validation from the recorded benchmark stack:
The A/B/C/D correctness gate verifies:
Performance evidence
The recorded benchmark used an NVIDIA H100 80 GB, LingBot-World-Fast, 37 output frames, three chunks, a two-chunk fork prefix, fixed seed, and an independent fresh 64 GiB Fluxon service for each sample.
Median of three samples:
Instrumented transfer results:
get_tensorpathput_tensorpathThe full-hit and prefix-hit results show the read/materialization benefit. The cold first-write result is a known regression: a fresh service currently pays roughly 50–60 seconds of one-time registered-host segment setup. D2H copy itself accounted for only about 0.23 seconds of the first 10.71 GiB write.
These figures are indicative rather than release claims: the tested Fluxon revision, upstream PR head, TeleFuser revision, allocator settings, and closed-SDK binary were not all identical. See the validation notes below.
Known limitations and follow-ups
PlanTensorTierStore.free()now lets an explicitWorldKVManager.evict_blob(node)call reclaim that node's Fluxon K/V values without deleting its skeleton. CacheSeek still has no automatic capacity accounting or LRU victim selection, so a workload that continuously writes without explicitly evicting eligible nodes can still exhaust a 64 GiB owner and makelocal_fast_put_start()time out.