Repository navigation
Stage pool reshard transfers in place on a full host mirror - #1489
Closed
jcc-google wants to merge 2 commits into
Closed
jcc-google wants to merge 2 commits into
jcc-google wants to merge 2 commits into
Conversation
jcc-google
force-pushed
the
jcc/fix-pool-reshard-recv-staging-validate
branch
from
November 5, 2026 19:25
1947322 to
dd47701
Compare
jcc-google
added a commit
to sgl-project/sglang-torchtpu
that referenced
this pull request
Nov 5, 2026
…gression (#1970) tpu-sync-torch 0.0.1.dev20261029204745 includes google/tpu-sync#1391, which leases a staging slot per pool on pool-reshard receives even with full host mirrors. Incoming pushes are then addressed into the leased buffer but bounds-checked against the pool's own buffer, so every PP->TP Raiden pipeline transfer fails with 'Chunk out of bounds' followed by 'explicit-destination push ... has no registered plan on this pool-mode worker'. The fix is google/tpu-sync#1489. Until a nightly with that fix exists, pin 0.0.1.dev20261029081917, the newest nightly before #1391. That wheel predates num_staging_layers (google/tpu-sync#1402), so RaidenKVManager now passes num_staging_layers only when the installed KVCacheManager accepts it and otherwise keeps full host mirrors (as with SGLANG_TPU_RAIDEN_STAGING_LAYERS=0). Signed-off-by: Jincheng Chen <chenjincheng@google.com>
jcc-google
force-pushed
the
jcc/fix-pool-reshard-recv-staging-validate
branch
from
November 5, 2026 21:10
dd47701 to
0f895ed
Compare
Since google#1391, ReshardReceiveSession leases a StagingLayerManager slot for every pool even when the manager keeps one host buffer per storage (no num_staging_layers). GetBlockChunks then addresses the pool at the leased buffer, while ValidateChunks checks it against the pool's own storage buffer. Pushes land in any order, so the leased slot usually differs from pool.storage_index and the push fails with 'Chunk out of bounds' at a multiple of the buffer size. The receive session then drains, and later pushes of the transfer fail with 'no registered plan on this pool-mode worker'. On a full host mirror, size the slot manager to zero and return kNotFound from AcquireStagingSlot, as TransferReceiveSession already does. GetBlockChunks and H2dPoolBlocks then address the pool's own storage. Bounded host layers keep leasing as before. Signed-off-by: Jincheng Chen <chenjincheng@google.com>
ReshardSendSession has the same issue as the receive side: it leases a StagingLayerManager slot per pool on a full host mirror, so D2H lands in the leased buffer while the push is addressed and validated against the pool's own storage. On a full host mirror, size the slot manager to zero and return kNotFound from AcquireStagingSlot and LookupStagingSlot, as TransferSendSession already does. ExecutePushPipeline treats kNotFound as staging in place. Bounded host layers keep leasing as before. Signed-off-by: Jincheng Chen <chenjincheng@google.com>
jcc-google
force-pushed
the
jcc/fix-pool-reshard-recv-staging-validate
branch
from
November 5, 2026 21:34
0f895ed to
6d869e3
Compare
jcc-google
marked this pull request as ready for review
November 5, 2026 22:09
Contributor
Author
|
Superseded by the internal CL, now landed on main as 47e9f20 ("Stage explicit-pool reshard transfers in place on a full host mirror"), rebased on top of the UUID-resolved validation fix (9dfd755c / d0f471b0). Closing. |
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
Pool reshard sessions (
ReshardReceiveSessionandReshardSendSession) stop leasingStagingLayerManagerhost-buffer slots when the manager already has a full host mirror (num_host_layers() == num_layers(), i.e. nonum_staging_layers). Transfers then stage and validate in place against each pool's own host storage, matching the existing layer-path sessions while keeping bounded host-layer staging unchanged.Commits (review one at a time)
1f08788Address pool reshard receives in place on a full host mirror.ReshardReceiveSessionstops leasingStagingLayerManagerslots when every storage has its own host buffer. Fixes thesgl-project/sglang-torchtpuPP->TP failure (regression from Support bounded host layer staging for pool reshard receives #1391).6d869e3Stage pool reshard sends in place on a full host mirror. The symmetric fix forReshardSendSession(regression from Support bounded host layer staging for pool reshard sends #1392).The bounded-host-layers
ValidateChunksgap on explicit pools is split out to #1494; it is independent of this full-host-mirror regression.Problem
Pool reshard transfers into a manager without
num_staging_layers(every storage has its own host buffer) fail on the receiver with:The chunk offset from the block array base is an exact multiple of the host buffer size (
1x,2x,88xobserved). The failed push finishes theReshardReceiveSession(Incoming push failed), so subsequent pushes of the same transfer fail withReceive session ... is draining,No transfer chunks found for block N, andexplicit-destination push ... has no registered plan on this pool-mode worker, while the sender seesConnection reset by peer.Observed in
sgl-project/sglang-torchtpuPP8 prefill -> TP8 decode (SGLANG_RAIDEN_PIPELINE_TRANSFER=1, Muse Spark).tpu-sync-torch0.0.1.dev20261029081917and earlier pass;0.0.1.dev20261029204745and later fail.Root cause
951b49b, receive) and Support bounded host layer staging for pool reshard sends #1392 (3d98f15, send) route pool-reshard transfers throughStagingLayerManagerunconditionally, leasing a host-buffer slot for every pool even on a full host mirror (num_host_layers() == num_layers()).GetHostPointer(slot) + base_offset_bytes, whereas transportValidateChunkschecks incoming chunks againstGetBlockArrayHostPointer(pool)(GetHostPointer(pool.storage_index) + base_offset_bytes).slotusually differs frompool.storage_index, placing the chunk in a different host buffer and failing bounds validation.TransferReceiveSessionandTransferSendSessionalready size their slot manager to0and returnkNotFound("no bounded host staging") on a full host mirror; the reshard sessions missed that guard.Fix
ReshardReceiveSessionandReshardSendSession, sizestaging_layer_manager_toHostLayersBounded() ? base->num_host_layers() : 0and returnkNotFoundfromAcquireStagingSlot(andLookupStagingSloton send) when!HostLayersBounded().kNotFoundashost_layer_idx = std::nullopt, soGetBlockChunks,D2hPoolBlocks, andH2dPoolBlocksaddresspool.storage_indexin place.num_host_layers() < num_layers()) from Support bounded host layer staging for pool reshard receives #1391 and Support bounded host layer staging for pool reshard sends #1392 is unchanged.Tests
ReshardReceiveSessionTest.FullHostMirrorAddressesPoolsInPlace: pool 1 (storage 1) arrives first; verifies its chunks lie inside the span accepted byValidateChunksand H2D reads each pool's own storage.ReshardSendSessionTest.FullHostMirrorStagesPoolsInPlace: loopback push where pool order != storage order; passes transportValidateChunksand delivers each pool's bytes in place.ReshardSendSessionTest.StagingSlotReleasedAfterLastPeerPush: configured with bounded host layers (num_staging_layers), where slot leasing applies;kv_cache_manager_with_transfer_pool_reshard_testhelper acceptskNotFoundon a full mirror.ml-buildcontainer,clang-18)://tpu_sync/kv_cache:reshard_receive_session_test,reshard_send_session_test,pool_staging_test, andkv_cache_manager_with_transfer_pool_reshard_testall pass at both1f08788and6d869e3individually.Chunk out of boundson the send loopback test;{pool 1 -> buffer 0, pool 0 -> buffer 1}mismatch on the receive test).tpu-sync-torchwheel below.End-to-end validation
Setup:
sgl-project/sglang-torchtpuMuse Spark (816B NVFP4 + DFlash2), PP8 prefill -> TP8 decode withSGLANG_RAIDEN_PIPELINE_TRANSFER=1(pool reshard),tpu7x2x2x1 per side (main7e580f5936+sgl-project/sglang-torchtpu#1950). Load: random ISL 1024 / OSL 256, 32 prompts, concurrency 4.tpu-sync-torch0.0.1.dev202610280819340.0.1.dev20261029081917(before951b49b)0.0.1.dev20261029204745(9f5270b,sgl-project/sglang-torchtpu#1869pin; rolled back insgl-project/sglang-torchtpu#1970)Chunk out of boundson decode0.0.1.dev202610300819079f5270b+ this fix (backport)Chunk out of bounds/no registered plan/Incoming push failed/Connection reset)50b50d3+ fix)Additional checks with the patched wheel:
sgl-project/sglang-torchtpuPP8 P/D nightly suite (test_tpu_muse_spark_pd_singlehost_pp8_dflash.py): server config, KV offload reload, SWA passkey (cold & warm), GSM8K 0.975 (floor 0.88), DFlash accept length 4.72 (floor 4.0) — all PASS.num_staging_layers=[3, 5]of[21, 46]layers): 32/32 complete, accept length 6.01, 0 Raiden errors — PASS.Receive-only backport onto
9f5270b(which predates send-side #1392): https://github.com/jcc-google/tpu-sync/tree/jcc/pool-reshard-staging-fix-on-9f5270b