1717import json
1818import struct
1919from dataclasses import dataclass , field
20- from typing import Any , Callable , Protocol , runtime_checkable , Sequence , TYPE_CHECKING
20+ from typing import Any , Callable , Protocol , runtime_checkable , Sequence
2121
2222import numpy as np
2323import torch
2424from torch import Tensor
2525
26- if TYPE_CHECKING :
27- from tensordict ._ucxx import TensorDictPipe
28-
2926_has_ucxx = importlib .util .find_spec ("ucxx" ) is not None
3027
3128
@@ -194,8 +191,9 @@ def sharded(
194191
195192
196193def _chunk_slice (total_size : int , num_chunks : int , chunk_idx : int ) -> slice :
197- """Return the slice for ``chunk_idx`` when splitting *total_size* into
198- *num_chunks* using ``torch.chunk`` semantics (last chunk may be smaller).
194+ """Return the slice for ``chunk_idx`` when splitting into chunks.
195+
196+ Uses ``torch.chunk`` semantics (last chunk may be smaller).
199197 """
200198 chunk_size = (total_size + num_chunks - 1 ) // num_chunks
201199 start = chunk_idx * chunk_size
@@ -313,9 +311,9 @@ def _deduplicate_src_specs(
313311 if not has_replica :
314312 return src_specs
315313
316- seen : dict [tuple [slice , ...], _ShardSpec ] = {}
314+ seen : dict [tuple [tuple [ int , int ] , ...], _ShardSpec ] = {}
317315 for spec in src_specs :
318- key = spec .slices
316+ key = tuple (( s . start , s . stop ) for s in spec .slices )
319317 if key not in seen or spec .rank < seen [key ].rank :
320318 seen [key ] = spec
321319 return list (seen .values ())
@@ -356,9 +354,7 @@ def _compute_transfer_plan(
356354 )
357355
358356 # Deduplicate replicated src specs
359- src_specs_dedup = _deduplicate_src_specs (
360- src_specs , src_placements , src_mesh_shape
361- )
357+ src_specs_dedup = _deduplicate_src_specs (src_specs , src_placements , src_mesh_shape )
362358
363359 plan = _TransferPlan (global_shape = global_shape )
364360
@@ -422,9 +418,7 @@ def execute_transfer_plan(
422418
423419 if dst_buffer is not None :
424420 for transfer in recvs :
425- chunk_shape = tuple (
426- s .stop - s .start for s in transfer .global_slices
427- )
421+ chunk_shape = tuple (s .stop - s .start for s in transfer .global_slices )
428422 buf = torch .empty (
429423 chunk_shape , dtype = dst_buffer .dtype , device = dst_buffer .device
430424 )
@@ -496,9 +490,7 @@ def __init__(self, endpoint):
496490 self ._endpoint = endpoint
497491
498492 def _tensor_to_numpy (self , t : Tensor ) -> np .ndarray :
499- return np .frombuffer (
500- t .contiguous ().view (torch .uint8 ).numpy (), dtype = np .uint8
501- )
493+ return np .frombuffer (t .contiguous ().view (torch .uint8 ).numpy (), dtype = np .uint8 )
502494
503495 def send_tensor (self , tensor : Tensor , dst : int , * , tag : int = 0 ) -> None :
504496 import asyncio
@@ -627,9 +619,9 @@ class ParameterPlan:
627619
628620
629621class ModelTransferPlan :
630- """Precomputed plan for transferring an entire model's parameters
631- between two differently-sharded meshes.
622+ """Precomputed plan for transferring an entire model's parameters.
632623
624+ Transfers between two differently-sharded meshes.
633625 Designed for LLM post-training: compute once at setup, execute
634626 every training iteration with near-zero overhead.
635627
@@ -647,7 +639,9 @@ class ModelTransferPlan:
647639 )
648640 """
649641
650- def __init__ (self , param_plans : list [ParameterPlan ], batches : list [list [ParameterPlan ]]):
642+ def __init__ (
643+ self , param_plans : list [ParameterPlan ], batches : list [list [ParameterPlan ]]
644+ ):
651645 self ._param_plans = param_plans
652646 self ._batches = batches
653647
@@ -784,7 +778,6 @@ def execute(
784778 if src_tensor is not None and pp .transform is not None :
785779 src_tensor = pp .transform (src_tensor )
786780
787- sends = pp .plan .sends_for_rank (rank )
788781 recvs = pp .plan .recvs_for_rank (rank )
789782
790783 # Allocate dst buffer if this rank receives data
@@ -810,9 +803,7 @@ def execute(
810803 return result
811804
812805 @staticmethod
813- def _rank_coords_for (
814- rank : int , desc : ShardingDescriptor
815- ) -> tuple [int , ...]:
806+ def _rank_coords_for (rank : int , desc : ShardingDescriptor ) -> tuple [int , ...]:
816807 """Find the mesh coordinates for *rank* in the descriptor's mesh."""
817808 if desc .rank_map is not None :
818809 for coords , r in desc .rank_map .items ():
@@ -867,7 +858,9 @@ def summary(self) -> str:
867858 if n_optimal :
868859 lines .append (f" Strategy C (optimal P2P): { n_optimal } params" )
869860 if n_materialize :
870- lines .append (f" Strategy A (materialize): { n_materialize } params (have transforms)" )
861+ lines .append (
862+ f" Strategy A (materialize): { n_materialize } params (have transforms)"
863+ )
871864 if n_direct :
872865 lines .append (f" Direct copy: { n_direct } params (same sharding)" )
873866 lines .append (f" Total transfer: { self .total_bytes / 1024 ** 2 :.1f} MB (float32)" )
0 commit comments