mirror of
https://github.com/kvcache-ai/Mooncake.git
synced 2026-11-05 01:17:55 +00:00
[GH-ISSUE #4408] [Bug][TENT] CPU-only TCP initiators cannot access a remote CUDA buffer #1108
Labels
No labels
ascend
auto-closed
bug
bug
CI/Build
Common
documentation
enhancement
feature request
good first issue
help wanted
high priority
MetaX
nightly-failure
pull-request
PyTorch Backend
question
RFC
Roadmap
stale
Store
Tests
Transfer Engine
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
kvcache-ai/Mooncake#1108
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Originally created by @feichai0017 on GitHub (Sep 30, 2026).
Original GitHub issue: https://github.com/kvcache-ai/Mooncake/issues/4408
A TENT client built with
USE_CUDA=OFFcannot READ or WRITE a registered CUDA buffer on a CUDA-enabled peer using standard TCP. Both peers initialize TCP, andopenSegment/getSegmentInfosucceed, but even a one-byte request fails before payload transfer with task status 6 andUnable to find registered buffer for request.Reproduced at
719735896c86b56fabec6cf3e825fb2ea640597a(v0.3.13.post1) andc3fa13ecaf1038df933dcb784ff8ffe026381100, using nativemooncake::tent::TransferEngine, not the classic TE compatibility layer.Upstream-only reproduction
The failure also reproduces with unmodified upstream tebench using
--backend=tent --xport_type=tcp --tent_transport_hint=tcp: a CPU-only DRAM initiator accesses a CUDA-enabled VRAM target, with P2P metadata, one thread, 4 KiB blocks, batch 1 and--check_consistency=true. Both sides report only TCP. The initiator exits 1 before producing a statistics row, while the bounded target exits cleanly.check_consistencyuses mixed WRITE/READ, so this result is not labeled as an isolated operation test. No external transfer harness, OrbitKV library, wrapper, or Manager executes in this reproduction.For the submitted regression, build the real upstream
tent_tcp_transport_testin CPU-only mode and run:With the production capability assignment unchanged, the real TCP transport and selector return UNSPEC instead of TCP for host/peer-CUDA. This is a selection-metadata test; it neither creates a fake GPU nor substitutes for hardware transfer validation.
Smaller native API reproducer and controls
On one CUDA-capable Linux host, run two processes linked against separate builds of the same revision:
USE_TENT=ON, USE_CUDA=OFFfor the initiator andUSE_TENT=ON, USE_CUDA=ONfor the target. Use real CUDA allocations; no CUDA stub is involved.cudaMalloc, initialize all bytes, and register the allocation as globally readable/writable.getSegmentInfo.host_base + 64, remote addressremote_base + 64, length 1, explicit TCP transport hint. Keep both registrations and allocations alive throughout submission/polling.Observed controls:
All GPU tests use real allocation and device/host copies with byte verification. The failing tests perform no early free, unregister or cancellation. These failures concern route selection, not observed data corruption.
Fixed-build control
Moving only the local-host/peer-GPU capability outside the local-device gate makes the native regression and upstream tebench reproduction pass with the CUDA target unchanged. Additional physical-host native API validation passed 14 separate READ/WRITE cases over 1 byte–64 MiB with three changing-data rounds and guards, plus four host controls. Two deliberate GPU-destination corruptions were detected. This confirms the upstream capability restriction; it is not evidence about RDMA or direct GPU networking.
Cause
Capabilities::dram_to_gpumeans local DRAM / peer GPU, regardless of the request opcode. However,TcpTransport::installenables it only when the local platform loader is not CPU. The selector therefore rejects the CPU-only initiator's local-host/remote-CUDA pair.For standard TCP, the remote endpoint performs the device copy; the CPU-only initiator only copies its own host memory. The local CUDA requirement appears unnecessary for this pair. Local-GPU capabilities should retain their local-device requirements. The generic
UNSPECdiagnostic also conflates capability rejection with a missing registration.Related work checked: #4082 covers same-build CUDA peers; #3973 fixes implicit CUDA contexts; RFC #2863 discusses capability semantics. None supplies this mixed-build route fix. Official issue and open/all PR searches found no exact duplicate on 2026-09-30.
AI assistance: OpenAI Codex assisted with reproduction, source inspection, duplicate search, and this report.
Complete upstream tebench reproduction commands
Use separate CPU-only and CUDA-enabled builds of the same Mooncake revision. No application wrapper or custom transfer harness is needed. The failure was reproduced at
c3fa13ecaf1038df933dcb784ff8ffe026381100; the patch changes only the CPU endpoint. Keep the CUDA target binary unchanged for the before/after comparison.For a same-host run, build both on a machine with a working CUDA GPU. For physical-host validation, build/run each endpoint on its own machine and replace loopback with that machine's real interface address. Runtime dependencies must be installed normally. Set these values in the appropriate endpoint's shell:
The explicit build-library directories avoid conflating this transfer test with the separate tebench build-RPATH issue. Keep library directories separate between endpoints. For IPv6, leave configuration IPs unbracketed and bracket only the target endpoint.
Create one configuration per endpoint. On separate hosts, create
tcp-cpu.jsonon the CPU endpoint andtcp-gpu.jsonon the CUDA endpoint with the corresponding IP set above:Start the CUDA target in one terminal. It owns a bounded 60-second lifetime; wait for its actual segment/listener log before starting the client in the other terminal.
Run the CPU-only initiator while the target is alive:
On the unpatched CPU build, the initiator exits 1 without a result row and logs
Unable to find registered buffer for request. With the CPU capability fix and the same unchanged CUDA target, it exits 0, produces a positive result row, and passes consistency checking. The target exits cleanly when its bounded lifetime ends. Both logs must show actual TCP transport and the requested ports. These are mixed WRITE/READ correctness checks; the observed timing is not a performance claim. Separate READ/WRITE, one-byte, changing-data and guard validation were performed with a native API harness as supplementary evidence.@github-actions[bot] commented on GitHub (Sep 30, 2026):
Thanks for opening this issue, @feichai0017!
132118805A maintainer will triage this when possible. To help us respond faster, please include:
Useful links: Documentation · Contributing guide