Conversation
|
@0z5a Both numbers are reachable — §8.2's 7 is not conditional on choosing the replica per target. I recomposed it from If you are getting 8, I would guess the merge stops at the query/kv boundary. That rule is On the policy: agreed it should be a parameter. Lowest holder is not topology-neutral either |
Thanks, that clears up the distinction. The current merge is indeed stopping at the source-piece boundary, so the TP2 -> TP4 BigCode case stays at 8. That is carrying the map-level homogeneity constraint from §5 into the resolved transfer plan, where locations is no longer part of the descriptor. The update will separate those two rules:
With the existing lowest-holder policy, BigCode TP2 -> TP4 should therefore regress to 7 segments. I’ll also make replica-holder selection an explicit planner policy rather than baking lowest-holder into the geometry. A per-target policy can then exercise the 6-segment case separately, without treating that as the canonical/default plan. This also seems worth clarifying next to the composer rules in §8.2: P5 constrains the IR pieces, not already-resolved transfer segments. |
Conversion and restore both go through the full logical tensor: rebuild it from the shards, then extract the target's. When the two topologies are known, that round trip is unnecessary -- the two descriptions compose, and the copies they imply go straight from one shard to another. plan_transfer composes a source map and a target map into strided copies between named ranks of each, and refuses anything it cannot express rather than approximating it. A piece is accepted only when both of its stride vectors are the row-major strides of the tensor it addresses, which is what every builder in affine.py already emits and what makes each piece a box; a permutation, a scale, or a shard described with the wrong number of axes is refused by name. Two ranks are two namespaces, so a source rank and a target rank that share a number are not the same process, and the plan keeps both. Coverage is argued over pieces, never over elements, so nothing here is sized by the parameter: validate_coverage walks every element by design and is not called. Each rank's pieces must partition its shard by address -- being disjoint in the parameter does not make two pieces disjoint in the shard, and their element counts agree either way -- and each target region must be tiled by the intersections that reach it. Volume totals are checked last for exactly that reason: one gap and one overlap of equal size cancel in any sum, including a sum over the whole plan. Nothing moves. There is no transport here, no scale other than 1, no judgment about whether two parameters are the same parameter, and no claim of a shortest plan. Signed-off-by: 0z5a <dezhen.lu@student.uni-tuebingen.de>
Signed-off-by: 0z5a <dezhen.lu@student.uni-tuebingen.de>
Signed-off-by: 0z5a <dezhen.lu@student.uni-tuebingen.de>
Signed-off-by: 0z5a <dezhen.lu@student.uni-tuebingen.de>
f4e1e16 to
b8f0f3b
Compare
|
Verified against the new head. I rebuilt the maps with segmented_map at TP2 and TP4 rather than using your fixture, planned with plan_transfer, and executed the segments element for element against extract: lowest holder gives 7, a per-target selector gives 6, both write 768 with nothing uncovered. Your committed suite also passes here — 97, CPU. The spec text is right, and separating "resolved copies are not another homogeneous map" from P5 is the part I'd have got wrong if I'd written it alone. A folded copy having no single logical origin is the consequence I hadn't followed through. One thing to tighten: "a specified per-target holder choice yields 6" depends on which per-target policy. A selector that takes the highest holder still gives 7 — I tried it. Only a selector that picks the rank holding the target's own private rows reaches 6, because that is what puts the query read adjacent to the kv read in the source shard. Worth saying, since The selector hook is the right shape. It is the seam a cost model plugs into, which is the part I took on #8252. |
Signed-off-by: 0z5a <dezhen.lu@student.uni-tuebingen.de>
|
@Achyuthan-S Thanks, good catch. §8.2 and both draft PR descriptions now specify that the 6-segment fold requires choosing the holder of each target's private Q rows; choosing the highest KV holder still gives 7. I added planner and two-GPU execution regressions for 7/6/7. B1 passes 98 CPU tests, and B2 passes 12 cases per rank. |
Summary
Compose source and target affine maps into shard-to-shard copy descriptors without rebuilding the logical parameter. This PR remains metadata only and based on
master.Resolved copies now fold when both physical shard address mappings continue along an axis. Their descriptor no longer claims a single
logical_origin: a copy can span two distinct logical regions. The planner keeps every validated replica candidate until a target intersection is resolved. It uses the lowest holder by default and accepts a caller-suppliedreplica_selectorfor other choices. Invalid selections fail explicitly.The spec distinguishes homogeneous input map pieces from resolved copies. The regression suite is committed in
tests/unit/checkpoint/test_affine_transfer_plan.py.Review result
The 7/6/7 counts apply to this layout and these three holder policies. For targets 0 and 1, the private Q rows are on source 0; for targets 2 and 3, they are on source 1. Selecting that same source for the replicated KV block makes the query and KV reads adjacent, allowing the sixth segment. Selecting the highest-ranked KV holder for every target does not. The previous 8-segment plan was valid; this change compresses its copy schedule. The selector does not change the input map's
locationsor relax its homogeneity rule.On the 8× RTX 5090 host, Python 3.12.13 and torch 2.13.0+cu130, the B1 CPU suite passed: 98 passed (
PYTHONPATH=$PWD CUDA_VISIBLE_DEVICES="" DS_ACCELERATOR=cpu python -m pytest tests/unit/checkpoint/test_affine_transfer_plan.py -q). Tests cover exact address oracles, nonzero storage offsets and guard regions, replica offsets, invalid selectors, serialization, budgets, determinism and the no-materialization contract.The stacked B2 executor PR has two-GPU copy and model E2E results, including the direct-versus-rebuild speed table. B1 itself does not move data, so it makes no transport speed claim.
Scope
Scale 1 and matching logical shapes only. No checkpoint format change, topology search, CUDA graph, online weight update or optimizer coordinate transform. Refs #8230 and #8252.