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
22- import numpy as np
2322import torch
2423from torch import Tensor
2524
26- if TYPE_CHECKING :
27- from tensordict ._ucxx import TensorDictPipe
28-
2925_has_ucxx = importlib .util .find_spec ("ucxx" ) is not None
3026
3127
@@ -194,8 +190,9 @@ def sharded(
194190
195191
196192def _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).
193+ """Return the slice for ``chunk_idx`` when splitting into chunks.
194+
195+ Uses ``torch.chunk`` semantics (last chunk may be smaller).
199196 """
200197 chunk_size = (total_size + num_chunks - 1 ) // num_chunks
201198 start = chunk_idx * chunk_size
@@ -313,9 +310,9 @@ def _deduplicate_src_specs(
313310 if not has_replica :
314311 return src_specs
315312
316- seen : dict [tuple [slice , ...], _ShardSpec ] = {}
313+ seen : dict [tuple [tuple [ int , int ] , ...], _ShardSpec ] = {}
317314 for spec in src_specs :
318- key = spec .slices
315+ key = tuple (( s . start , s . stop ) for s in spec .slices )
319316 if key not in seen or spec .rank < seen [key ].rank :
320317 seen [key ] = spec
321318 return list (seen .values ())
@@ -356,9 +353,7 @@ def _compute_transfer_plan(
356353 )
357354
358355 # Deduplicate replicated src specs
359- src_specs_dedup = _deduplicate_src_specs (
360- src_specs , src_placements , src_mesh_shape
361- )
356+ src_specs_dedup = _deduplicate_src_specs (src_specs , src_placements , src_mesh_shape )
362357
363358 plan = _TransferPlan (global_shape = global_shape )
364359
@@ -422,9 +417,7 @@ def execute_transfer_plan(
422417
423418 if dst_buffer is not None :
424419 for transfer in recvs :
425- chunk_shape = tuple (
426- s .stop - s .start for s in transfer .global_slices
427- )
420+ chunk_shape = tuple (s .stop - s .start for s in transfer .global_slices )
428421 buf = torch .empty (
429422 chunk_shape , dtype = dst_buffer .dtype , device = dst_buffer .device
430423 )
@@ -486,7 +479,7 @@ def recv_object(self, src: int) -> Any:
486479 length = int (length_t .item ())
487480 data_t = torch .empty (length , dtype = torch .uint8 , device = "cuda" )
488481 dist .recv (data_t , src = src , group = self .group )
489- return json .loads (bytes (data_t .cpu ().numpy ()))
482+ return json .loads (bytes (data_t .cpu ().tolist ()))
490483
491484
492485class _UCXXBackend :
@@ -510,10 +503,10 @@ class _UCXXBackend:
510503 def __init__ (self , endpoint ):
511504 self ._endpoint = endpoint
512505
513- def _tensor_to_numpy (self , t : Tensor ) -> np . ndarray :
514- return np . frombuffer (
515- t . contiguous (). view ( torch . uint8 ). numpy (), dtype = np . uint8
516- )
506+ def _tensor_to_numpy (self , t : Tensor ):
507+ import numpy as np
508+
509+ return np . frombuffer ( t . contiguous (). view ( torch . uint8 ). numpy (), dtype = np . uint8 )
517510
518511 def send_tensor (self , tensor : Tensor , dst : int , * , tag : int = 0 ) -> None :
519512 import asyncio
@@ -550,12 +543,16 @@ def recv_object(self, src: int) -> Any:
550543 return asyncio .run (self ._arecv_object ())
551544
552545 async def _asend_object (self , obj : Any ) -> None :
546+ import numpy as np
547+
553548 data = json .dumps (obj ).encode ("utf-8" )
554549 length = struct .pack ("<Q" , len (data ))
555550 await self ._endpoint .send (np .frombuffer (length , dtype = np .uint8 ))
556551 await self ._endpoint .send (np .frombuffer (data , dtype = np .uint8 ).copy ())
557552
558553 async def _arecv_object (self ) -> Any :
554+ import numpy as np
555+
559556 len_buf = np .empty (8 , dtype = np .uint8 )
560557 await self ._endpoint .recv (len_buf )
561558 length = struct .unpack ("<Q" , len_buf .tobytes ())[0 ]
@@ -642,9 +639,9 @@ class ParameterPlan:
642639
643640
644641class ModelTransferPlan :
645- """Precomputed plan for transferring an entire model's parameters
646- between two differently-sharded meshes.
642+ """Precomputed plan for transferring an entire model's parameters.
647643
644+ Transfers between two differently-sharded meshes.
648645 Designed for LLM post-training: compute once at setup, execute
649646 every training iteration with near-zero overhead.
650647
@@ -662,7 +659,9 @@ class ModelTransferPlan:
662659 )
663660 """
664661
665- def __init__ (self , param_plans : list [ParameterPlan ], batches : list [list [ParameterPlan ]]):
662+ def __init__ (
663+ self , param_plans : list [ParameterPlan ], batches : list [list [ParameterPlan ]]
664+ ):
666665 self ._param_plans = param_plans
667666 self ._batches = batches
668667
@@ -803,7 +802,6 @@ def execute(
803802 if src_tensor is not None and pp .transform is not None :
804803 src_tensor = pp .transform (src_tensor )
805804
806- sends = pp .plan .sends_for_rank (rank )
807805 recvs = pp .plan .recvs_for_rank (rank )
808806
809807 # Allocate dst buffer if this rank receives data
@@ -832,9 +830,7 @@ def execute(
832830 return result
833831
834832 @staticmethod
835- def _rank_coords_for (
836- rank : int , desc : ShardingDescriptor
837- ) -> tuple [int , ...]:
833+ def _rank_coords_for (rank : int , desc : ShardingDescriptor ) -> tuple [int , ...]:
838834 """Find the mesh coordinates for *rank* in the descriptor's mesh."""
839835 if desc .rank_map is not None :
840836 for coords , r in desc .rank_map .items ():
@@ -889,7 +885,9 @@ def summary(self) -> str:
889885 if n_optimal :
890886 lines .append (f" Strategy C (optimal P2P): { n_optimal } params" )
891887 if n_materialize :
892- lines .append (f" Strategy A (materialize): { n_materialize } params (have transforms)" )
888+ lines .append (
889+ f" Strategy A (materialize): { n_materialize } params (have transforms)"
890+ )
893891 if n_direct :
894892 lines .append (f" Direct copy: { n_direct } params (same sharding)" )
895893 lines .append (f" Total transfer: { self .total_bytes / 1024 ** 2 :.1f} MB (float32)" )
0 commit comments