
    a,j~                    
   U d dl mZ d dlZd dlZd dlmZmZ d dlmZ d dl	m
Z
mZmZmZmZmZ d dlZd dlmZ d dlmZ d dlmZ d d	lmZmZ erd d
lmZ d dlmZ  ej        e          Z G d de          Z e!e!e"df         edz  f         Z#de$d<    G d de%          Z& edd           G d d                      Z' edd           G d de'                      Z(e'e(z  Z)de$d<    ed           G d d                      Z* edd           G d d                      Z+ edd           G d d                       Z,dkd&Z-dld*Z. G d+ d,          Z/ G d- d.e          Z0d/d0dmd3Z1d4 Z2	 dndod<Z3	 dndpd>Z4 ed           G d? d@                      Z5dqdBZ6eddCdrdI            Z7edsdM            Z7d/dCdtdOZ7dudvdPZ8e	 dwdxdS            Z9e	 dwdydU            Z9	 dudzdWZ9d/d/dXd{d`Z:dd/dXd|dcZ;d}djZ<dS )~    )annotationsN)	dataclassfield)Enum)castLiteraloverloadProtocolTYPE_CHECKING	TypeAlias)fx)_MeshLayout)DTensortree_flattentree_unflatten)
DeviceMesh)	Placementc                      e Zd ZdZd
dZd	S )GetMeshCallbackzGCallback to create/retrieve a DeviceMesh from its cache key components.mesh_dim_namestuple[str, ...]mesh_layout_MeshLayout | Nonereturnr   c                    d S N )selfr   r   s      c/var/www/html/banglarbhumi/venv/lib/python3.11/site-packages/torch/distributed/pipelining/_utils.py__call__zGetMeshCallback.__call__   s	     S    N)r   r   r   r   r   r   )__name__
__module____qualname____doc__r!   r   r"   r    r   r      s.        QQ     r"   r   .r   MeshCacheKeyc                      e Zd ZdZdS )PipeliningMetadataErrorz<Raised on metadata mismatches during pipeline communication.N)r#   r$   r%   r&   r   r"   r    r)   r)   ,   s        FFFFr"   r)   T)frozenslotsc                  d    e Zd ZU dZded<   ded<   ded<   ded	<   edd            ZddZddZdS )_TensorMetazTensor metadata for recv buffer allocation and validation.

    For plain tensors, these are the tensor's actual attributes.
    For DTensors, these are LOCAL shard attributes; global attributes
    are stored in :class:`_DTensorMeta`.
    
torch.Sizeshapetuple[int, ...]strideztorch.dtypedtypeboolrequires_gradtensortorch.Tensorr   c                    t          | t                    rt          d          t          | j        |                                 | j        | j                  S )a  Create metadata from a plain tensor.

        Args:
            tensor: A plain ``torch.Tensor`` (not DTensor).

        Returns:
            Metadata capturing shape, stride, dtype, and requires_grad.

        Raises:
            TypeError: If ``tensor`` is a DTensor.
        zJExpected plain tensor, got DTensor. Use _DTensorMeta.from_dtensor instead.r/   r1   r2   r4   )
isinstancer   r)   r-   r/   r1   r2   r4   r5   s    r    from_tensorz_TensorMeta.from_tensor>   s_     fg&& 	)\   ,==??, .	
 
 
 	
r"   devicetorch.device | strc                Z    t          | |          }|                    | j                   |S )zReconstruct a tensor on ``device`` from this metadata.

        Args:
            device: Target device for the tensor.

        Returns:
            An empty strided tensor on ``device``.
        )_make_tensor_from_metarequires_grad_r4   )r   r<   ts      r    	to_tensorz_TensorMeta.to_tensorV   s/     #400	+,,,r"   other	list[str]c                X   | |k    rg S g }| j         |j         k    r%|                    d| j          d|j                     | j        |j        k    r%|                    d| j         d|j                    | j        |j        k    r%|                    d| j         d|j                    |S )zReturn field-by-field differences with ``other``.

        Args:
            other: Metadata to compare against.

        Returns:
            List of human-readable difference strings (empty if equal).
        zshape mismatch:  vs zstride mismatch: zdtype mismatch: )r/   appendr1   r2   r   rC   diffss      r    get_diffz_TensorMeta.get_diffc   s     5==I:$$LLIDJIIEKIIJJJ;%,&&LLLT[LLelLLMMM:$$LLIDJIIEKIIJJJ r"   N)r5   r6   r   r-   )r<   r=   r   r6   rC   r-   r   rD   )	r#   r$   r%   r&   __annotations__staticmethodr;   rB   rJ   r   r"   r    r-   r-   0   s           
 
 
 \
.        r"   r-   c                      e Zd ZU dZ ed           Zded<    ed          Zded	<    ed          Zd
ed<    ed          Z	ded<    ed          Z
ded<   ed d            Zed!d            Zd"dZd#dZdS )$_DTensorMetaa  DTensor metadata extending :class:`_TensorMeta` with distribution info.

    Inherited fields (shape, stride, etc.) are LOCAL shard attributes.
    Additional fields capture global shape and placement information
    needed to reconstruct a :class:`DTensor` via ``DTensor.from_local()``.

    The :class:`DeviceMesh` is **not** stored (not serializable for P2P);
    it is looked up from :class:`_MeshCache` using
    ``(mesh_dim_names, mesh_layout)`` as the key.
    c                 *    t          j        g           S r   )torchSizer   r"   r    <lambda>z_DTensorMeta.<lambda>   s    UZ^^ r"   )default_factoryr.   global_shaper   )defaultr0   global_strideztuple[Placement, ...]
placementsr   r   Nr   r   dtensorr   r   c                   | j         }t          | j        j        | j                                        | j        | j        | j        |                                 | j        j        |j	        rt          |j	                  nd|j        	  	        S )zCreate metadata from a DTensor.

        Args:
            dtensor: The DTensor to extract metadata from.

        Returns:
            Metadata capturing both local and global attributes.
        r   )	r/   r1   r2   r4   rU   rW   rX   r   r   )device_meshrO   _local_tensorr/   r1   r2   r4   _specrX   r   tuple_layout)rY   r[   s     r    from_dtensorz_DTensorMeta.from_dtensor   s     )'-(//11-!/ !..**}/5@5OWk0111UW#+
 
 
 	
r"   r'   c                    | j         | j        fS )z<Cache key ``(mesh_dim_names, mesh_layout)`` for mesh lookup.)r   r   r   s    r    mesh_cache_keyz_DTensorMeta.mesh_cache_key   s     #T%566r"   r<   r=   meshr   c                    t          | |          }t          t          t          j        ||| j        | j        | j        d                              | j                            S )zReconstruct a DTensor on ``device`` with placements.

        Args:
            device: Target device for the local tensor.
            mesh: The ``DeviceMesh`` to attach.

        Returns:
            A DTensor on ``device``.
        F)r[   rX   r/   r1   	run_check)	r?   r   r   
from_localrX   rU   rW   r@   r4   )r   r<   rd   local_tensors       r    
to_dtensorz_DTensorMeta.to_dtensor   sk     .dF;;  ?')   nT/00

 

 
	
r"   rC   r-   rD   c                   | |k    rg S t                               | |          }t          |t                    r
| j        |j        k    r%|                    d| j         d|j                    | j        |j        k    r%|                    d| j         d|j                    | j        |j        k    r%|                    d| j         d|j                    | j        |j        k    r%|                    d| j         d|j                    | j	        |j	        k    r%|                    d| j	         d|j	                    n|                    d           |S )zReturn field-by-field differences, including DTensor-specific fields.

        Args:
            other: Metadata to compare against.

        Returns:
            List of human-readable difference strings (empty if equal).
        zglobal_shape mismatch: rF   zglobal_stride mismatch: zplacements mismatch: zmesh_dim_names mismatch: zmesh_layout mismatch: z!type: _DTensorMeta vs _TensorMeta)
r-   rJ   r9   rO   rU   rG   rW   rX   r   r   rH   s      r    rJ   z_DTensorMeta.get_diff   s    5==I
 $$T511 e\** 	> E$666Yd.?YYUEWYY   !U%888\t/A\\uGZ\\   %"222SDOSSAQSS   "e&:::_0C__I]__   5#444VT-=VV5CTVV   LL<===r"   )rY   r   r   rO   )r   r'   )r<   r=   rd   r   r   r   rK   )r#   r$   r%   r&   r   rU   rL   rW   rX   r   r   rM   r`   propertyrc   ri   rJ   r   r"   r    rO   rO   {   sF        	 	  %u5K5KLLLLLLLL%*U2%6%6%6M6666 ).) ) )J    
 ',eB&7&7&7N7777&+e' ' 'K     
 
 
 \
8 7 7 7 X7
 
 
 
2* * * * * *r"   rO   
TensorMeta)r+   c                  d    e Zd ZU dZdZded<   dZded<   dZded<   dZded<   ddZ	ddZ
ddZdS )
_StageMetazPConsolidated tensor metadata for a pipeline stage's forward and backward passes.Ntuple[TensorMeta, ...] | Noneinputsoutputs$tuple[TensorMeta | None, ...] | Noneinput_gradsoutput_gradsr   r3   c                d    t          d | j        | j        | j        | j        fD                       S )z)Check if any metadata field is populated.c              3     K   | ]}|d uV  	d S r   r   ).0vs     r    	<genexpr>z%_StageMeta.has_any.<locals>.<genexpr>  s:       
 
 TM
 
 
 
 
 
r"   )anyrp   rq   rs   rt   rb   s    r    has_anyz_StageMeta.has_any  sC     
 
k4<1A4CTU
 
 
 
 
 	
r"   c                d    | j         | j        fD ] }|rt          d |D                       r dS !dS )z3Check if any input/output metadata is DTensor type.c              3  D   K   | ]}|t          |t                    V  d S r   )r9   rO   rw   ms     r    ry   z*_StageMeta.has_dtensors.<locals>.<genexpr>  s1      MMQ1MZ<88MMMMMMr"   TF)rp   rq   rz   )r   metass     r    has_dtensorsz_StageMeta.has_dtensors  sM    k4<0 	 	E MM%MMMMM ttur"   c                &    | j         duo| j        duS )z-Check if forward metadata is fully populated.N)rp   rq   rb   s    r    is_complete_for_forwardz"_StageMeta.is_complete_for_forward  s    {$&C4<t+CCr"   )r   r3   )r#   r$   r%   r&   rp   rL   rq   rs   rt   r{   r   r   r   r"   r    rn   rn     s         ZZ,0F0000-1G11118<K<<<<9=L====
 
 
 
   D D D D D Dr"   rn   c                      e Zd ZU dZded<   dS )_StageForwardMetazLForward metadata transmitted from stage *i* to stage *i+1* during inference.tuple[TensorMeta, ...]forward_metasNr#   r$   r%   r&   rL   r   r"   r    r   r   !  s$         VV))))))r"   r   c                      e Zd ZU dZded<   dS )_StageBackwardMetau   Backward metadata transmitted from stage *i* to stage *i-1* during inference.

    Gradient placements may differ from forward activations
    (e.g., ``Replicate`` → ``Partial``).
    tuple[TensorMeta | None, ...]backward_metasNr   r   r"   r    r   r   (  s4               r"   r   metar<   r=   r   r6   c                P    t          j        | j        | j        | j        |          S )zCreate a tensor from metadata.

    Args:
        meta: Metadata with shape, stride, and dtype.
        device: Target device for the tensor.

    Returns:
        Empty tensor preserving the exact memory layout.
    )sizer1   r2   r<   )rQ   empty_stridedr/   r1   r2   )r   r<   s     r    r?   r?   5  s0     Z{j	   r"   tensor_metasr   tuple[_TensorMeta | None, ...]c                4    t          d | D                       S )zDerive gradient metadata from tensor metadata.

    Returns metadata with the same shape/stride/dtype but ``requires_grad=False``.
    Entries where the source has ``requires_grad=False`` become ``None``.
    c              3  l   K   | ]/}|j         r"t          |j        |j        |j        d           ndV  0dS )Fr8   N)r4   r-   r/   r1   r2   r~   s     r    ry   z%_derive_grad_metas.<locals>.<genexpr>R  s_          ?	!'!(!'QVWWWW     r"   )r^   )r   s    r    _derive_grad_metasr   J  s4        	     r"   c                  D    e Zd ZdZdddZddZddZddZddZddZ	dS )
_MeshCachezCache for :class:`DeviceMesh` objects keyed by ``(mesh_dim_names, mesh_layout)``.

    Assumes all pipeline stages share the same rank tensor (true for
    TorchTitan-style frameworks where meshes derive from a common world).
    Nget_mesh_cbGetMeshCallback | Noner   Nonec                "    i | _         || _        d S r   )_cache_get_mesh_cb)r   r   s     r    __init__z_MeshCache.__init__a  s    68'r"   keyr'   r   c                    || j         v r| j         |         S |\  }}| j        t          d| d| d          |                     ||          }|t          d| d| d          || j         |<   |S )a  Return a cached mesh, or create one via the callback.

        Args:
            key: Cache key ``(mesh_dim_names, mesh_layout)``.

        Returns:
            The ``DeviceMesh``.

        Raises:
            PipeliningMetadataError: If not cached and no callback provided.
        Nz+Mesh not found in cache for mesh_dim_names=z, mesh_layout=z`, and no get_mesh callback provided. Provide a get_mesh callback or use DTensors in static mode.z>Mesh lookup failed: callback returned None for mesh_dim_names=z6. Ensure all stages use meshes from the same universe.)r   r   r)   )r   r   r   r   rd   s        r    get_meshz_MeshCache.get_meshe  s     $+;s##&)#$)On O O*O O O     ==<)H"0H H@KH H H  
  Cr"   rd   c                    || j         |<   dS )zAdd a mesh to the cache.Nr   )r   r   rd   s      r    putz_MeshCache.put  s    Cr"   tensorstuple[torch.Tensor | None, ...]c                    |D ]Y}t          |t                    rB|j        }|j        rt	          |j                  nd}|j        }||f}|| j        vr
|| j        |<   ZdS )zJExtract and cache meshes from any :class:`DTensor` instances in *tensors*.r   N)r9   r   r[   r   r^   r_   r   )r   r   r5   rd   	dim_namesr   r   s          r    update_from_tensorsz_MeshCache.update_from_tensors  s~     	, 	,F&'** ,):>:MUE$"5666SU	"l +.dk))'+DK$	, 	,r"   r3   c                    || j         v S r   r   )r   r   s     r    __contains__z_MeshCache.__contains__  s    dk!!r"   intc                *    t          | j                  S r   )lenr   rb   s    r    __len__z_MeshCache.__len__  s    4;r"   r   )r   r   r   r   )r   r'   r   r   )r   r'   rd   r   r   r   )r   r   r   r   )r   r'   r   r3   )r   r   )
r#   r$   r%   r&   r   r   r   r   r   r   r   r"   r    r   r   Z  s         ( ( ( ( (       D       	, 	, 	, 	," " " "           r"   r   c                  2    e Zd ZdZdZdZedd	            Zd
S )InferenceModea  Pipeline-level metadata inference mode, determined collectively across all PP ranks.

    The mode is set by the schedule (not individual stages) because
    ``has_backward`` is only known at schedule creation time and all
    stages must agree to avoid P2P hangs.

    .. attribute:: STATIC

        All stages have sufficient metadata; runtime inference is skipped.

    .. attribute:: DYNAMIC

        At least one stage requires runtime metadata inference.
    staticdynamicr   rn   stage_has_backwardr3   r   c                    |                                 sdS |                                sdS |sdS |j        |j        dS dS )a'  Determine whether dynamic metadata inference is needed for a stage.

        Args:
            meta: Stage metadata from user-provided args.
            stage_has_backward: Whether a backward pass will be performed.

        Returns:
            ``True`` if dynamic inference is needed.
        TF)r   r   rs   rt   )clsr   r   s      r    needs_dynamiczInferenceMode.needs_dynamic  sf     ++-- 	4   "" 	5 " 	5 #t'8'@4 ur"   N)r   rn   r   r3   r   r3   )r#   r$   r%   r&   STATICDYNAMICclassmethodr   r   r"   r    r   r     sH          FG   [  r"   r   Fdetachr   r3   c               n    t          |           \  }}|r d |D             }t          ||          }||fS |S )a;  Flatten ``args`` into a list, optionally detaching tensors.

    Args:
        args: Nested arguments to flatten.
        detach: If ``True``, detach tensors while preserving ``requires_grad``.

    Returns:
        ``(new_args, flat_detached_args)`` when ``detach=True``;
        ``flat_args`` list otherwise.
    c                    g | ]J}t          |t          j                  r,|                                                    |j                  n|KS r   )r9   rQ   Tensorr   r@   r4   )rw   as     r    
<listcomp>z flatten_args.<locals>.<listcomp>  s[     
 
 
  !U\**AHHJJ%%ao666
 
 
r"   r   )argsr   	flat_argstreespecflat_detachednew_argss         r    flatten_argsr     s`     't,,Ix '
 
 	
 
 
 "-::&&r"   c                $    t          | d          S )zHFlatten and detach. Deprecated: use ``flatten_args(args, detach=True)``.Tr   )r   )r   s    r    flatten_args_detachr     s    T****r"   looppp_sizer   
num_stagesstylestrdict[int, int]c                8   i }|dk    rt          |          D ]
}|| z  ||<   nv|dk    r]|| z  dk    rt          d| d|  d          d}t          |          D ]+}|||<   |dz   | z  dk    r|| z  dz  dk    r|dz  }&|dz  },nt          d	| d
          |S )z
    Compute the stage id to rank mapping for either a looped or V-style schedule.

    Most commonly num_stages == pp_size * 2, but this function can be used to
    compute the mapping for any number of stages per rank.
    r   rx   r   znum_stages z% must be evenly divisible by pp_size z for V schedules      zStyle z is not supported.)range
ValueError)r   r   r   mappingstage_index
rank_indexs         r    generate_stage_to_rank_mappingr     s    G ,, 	9 	9K#.#8GK  	9	#1$$hjhhwhhh   
 ,, 	  	 K#-GK a7*a//w&!+q00a

a

	  ;%;;;<<<Nr"   dict[int, list[int]]c                    t          | ||          }i }|                                D ])\  }}||vrg ||<   ||                             |           *|                                D ]}|                                 |S )a  
    Compute the rank to stage id mapping for either a looped or V-style schedule.

    This function inverts the stage_to_rank_mapping to get which stages are assigned to each rank.

    Returns a dictionary mapping rank -> list of stage indices assigned to that rank.
    )r   itemsrG   valuessort)r   r   r   stage_to_rankrank_to_stagesstage_idrankstagess           r    generate_rank_to_stage_mappingr     s     37JNNM ,.N'--// . .$~%%#%N4 t##H---- !''))  r"   c                  2    e Zd ZU dZded<   ded<   ded<   dS )	PipeInfoz>
    Captures information for a pipeline (`Pipe` object).
    zfx.Graphgraphr   r   r3   has_loss_and_backwardNr   r   r"   r    r   r   6  s<           OOOOOOr"   r   r5   c                    t          | t                    rt                              |           S t                              |           S )a  Extract metadata from a tensor.

    Handles both plain Tensor and DTensor correctly: DTensors are
    dispatched to ``_DTensorMeta.from_dtensor`` which captures local
    shard attributes plus global shape/placement info, while plain
    tensors use ``_TensorMeta.from_tensor``.

    Args:
        tensor: A plain tensor or DTensor.

    Returns:
        ``_TensorMeta`` for plain tensors, ``_DTensorMeta`` for DTensors.
    )r9   r   rO   r`   r-   r;   r:   s    r    extract_tensor_metar   F  s>     &'"" /((000&&v...r"   )
allow_noner   tuple[torch.Tensor, ...] | Noner   Literal[False]ro   c                   d S r   r   r   r   s     r    extract_tensor_metasr   Z  s	    
 %(Cr"   &tuple[torch.Tensor | None, ...] | NoneLiteral[True]rr   c                   d S r   r   r   s     r    r   r   b  s	    
 ,/3r"   Atuple[torch.Tensor | None, ...] | tuple[torch.Tensor, ...] | Nonec                  | dS g }d}| D ]V}t          |t          j                  r#|                    t	          |                     ?d}|                    d           W|s|rt          d          t          |          S )a  Extract metadata from a tuple of tensors.

    Args:
        tensors: Tuple of tensors (may include ``None`` when ``allow_none=True``).
        allow_none: If ``True``, preserve ``None`` elements (for gradients).

    Returns:
        Tuple of ``TensorMeta``, or ``None`` if ``tensors`` is ``None``.

    Raises:
        PipeliningMetadataError: If ``None`` found and ``allow_none=False``.
    NFTz_None values are not allowed in tensor metadata tuples. Use allow_none=True for optional values.)r9   rQ   r   rG   r   r)   r^   )r   r   metas_with_nonehas_nonerA   s        r    r   r   j  s    " t/1OH ) )a&& 	)""#6q#9#9::::H""4(((( 
( 
%7
 
 	
 !!!r"   c                    |r|                                  n| }t          |t                    r|                                S |S )u  Convert a DTensor to its local shard, or return a plain tensor as-is.

    When ``detach=True``, the tensor is detached before conversion —
    this applies to both DTensors and plain tensors.

    Args:
        tensor: A tensor that may be a DTensor.
        detach: If ``True``, detach before ``to_local()`` to avoid
            redistribution during backward.

    Returns:
        The local tensor component.
    )r   r9   r   to_local)r5   r   maybe_detached_tensors      r    to_local_if_dtensorr     sF     06AFMMOOO6'11 0$--///  r"   r   Ctorch.Tensor | tuple[torch.Tensor, ...] | list[torch.Tensor] | Nonec                    d S r   r   r   r   s     r    validate_and_normalize_to_tupler     s	     '*cr"   Qtorch.Tensor | tuple[torch.Tensor | None, ...] | list[torch.Tensor | None] | Nonec                    d S r   r   r   s     r    r   r     s	     .1Sr"   torch.Tensor | tuple[torch.Tensor, ...] | tuple[torch.Tensor | None, ...] | list[torch.Tensor] | list[torch.Tensor | None] | Nonec           	        | dS t          | t          j                  r| fS t          | t          t          f          rt          |           D ]_\  }}||st          d| d          t          |t          j                  s(t          d| dt          |          j         d          `t          | t                    rt          |           n| S t          dt          |           j         d          )a  Normalize ``args`` to a tuple and validate that all elements are tensors.

    Args:
        args: A single tensor, tuple/list of tensors, or ``None``.
        allow_none: If ``True``, permit ``None`` elements (for gradients).

    Returns:
        Tuple of tensors, or ``None`` if ``args`` is ``None``.

    Raises:
        PipeliningMetadataError: On non-tensor values
            (or ``None`` when ``allow_none=False``).
    Nz
Stage arg[zF] is None. Stage args must be tensors. Use kwargs for optional values.z] has type zC. All stage args must be tensors. Use kwargs for non-tensor inputs.z<Stage args must be a tensor, tuple, or list of tensors, got .)	r9   rQ   r   r^   list	enumerater)   typer#   )r   r   iargs       r    r   r     s=   , |t	D%,	'	' 
w	D5$-	(	( 
oo 	 	FAs{! 1WQ W W W   c5<00 -Y Y YtCyy/A Y Y Y   )t44>uT{{{$>%a4PT::K^aaa
 
 	
r"   raise_on_mismatchwarn_on_mismatchdescexpectedactualtorch.Tensor | TensorMetar
  r  rD   c               r   t          |t          j                  rt          |          }n|}t	          |          t	          |          urudt	          |          j         dt	          |          j         g}|rt          |  d|d                    |r(t          j        |  d|d          dt          d           |S |
                    |          }|r`|r't          |  dd	                    |                     |r5t          j        |  d
d	                    |           dt          d           |S )al  
    Compare expected metadata against actual tensor or metadata.

    This is the unified validation/comparison function that uses get_diff() from
    metadata classes. Works with both plain tensors and DTensors.

    For plain tensors: compares shape/stride/dtype/requires_grad.
    For DTensors: compares all properties including global shape and placements.

    Args:
        desc: Description for error/warning messages.
        expected: Expected tensor metadata (_TensorMeta or _DTensorMeta).
        actual: Actual tensor or metadata to compare against.
        raise_on_mismatch: If True, raise PipeliningMetadataError on mismatch.
        warn_on_mismatch: If True, issue a warning on mismatch.

    Returns:
        List of differences (empty if metadata matches).

    Raises:
        PipeliningMetadataError: If raise_on_mismatch=True and differences exist.
    ztype: expected , got : r   z: Metadata type mismatch. z.. Using dynamically inferred metadata instead.r   
stacklevelz; z: Metadata mismatch. )r9   rQ   r   r   r  r#   r)   warningswarnUserWarningrJ   join)r  r  r  r
  r  actual_meta	type_diffrI   s           r    validate_metadatar    s   > &%,'' )&11 H~~T+....Yd8nn5YYT+=N=N=WYY
	  	E)T*C*CYq\*C*CDDD 	M @ @9Q< @ @ @	     k**E 	 	I)T*G*GTYYu5E5E*G*GHHH 	M @ @dii.>.> @ @ @	    Lr"   r   ,tuple[torch.Tensor | TensorMeta | None, ...]c               j   t          |          t          |          k    rV|  dt          |           dt          |           }|rt          |          |rt          j        |t          d           |gS g }t          t          ||d                    D ]\  }\  }}	||	||	Z|  d| d	|d
nd d|	d
nd }|rt          |          |rt          j        |t          d           |                    |           kt          |  d| d||	||          }
|	                    |
           |S )a2  Validate metadata for a tuple of tensors element-wise.

    Args:
        desc: Description prefix for error/warning messages.
        expected: Tuple of expected metadata (may include ``None`` for grads).
        actual: Tuple of actual tensors or metadata to compare against.
        raise_on_mismatch: If ``True``, raise on the first mismatch.
        warn_on_mismatch: If ``True``, issue warnings for mismatches.

    Returns:
        Aggregated list of difference strings.

    Raises:
        PipeliningMetadataError: If lengths differ or on mismatch.
    z: expected z tensors, got r   r  TstrictN[z]: expected r   metadatar  ]r	  )
r   r)   r  r  r  r  ziprG   r  extend)r  r  r  r
  r  msg	all_diffsr  expactrI   s              r    validate_tensors_metadatar)  -  s   . 8}}F##LL#h--LLs6{{LL 	/)#... 	:M#{q9999uI"3x#E#E#EFF    :C;3;;#+ ? ?! ? ?3;J ? ?!$vv*? ?  ! 3-c222 >c;1====S!!!!NNaNNN/-
 
 
 	r"   r   tuple[torch.Tensor, ...]gradsr   is_inputr   c                   |rdnd}| d}| d}t          |          t          |          k    r9t          d|  d| dt          |           d| dt          |           d	          t          t          ||d
                    D ]\  }\  }}	|j        s6|	4t          d|  d| d| d| d| dt          |	          j         d          |j        r.|	,t          j        d|  d| d| d| d| dt          d           t          |t                    rR|j        rK|	It          |	t                    s4t          d|  d| d| d| d| dt          |	          j         d          dS )u/  
    Validate the args↔grads contract for static mode.

    Enforces four rules for each (arg, grad) pair:
      1. len(args) must equal len(grads).
      2. If arg.requires_grad is False, grad must be None.
      3. If arg.requires_grad is True and grad is None, emit a warning
         (this is legal at pipeline boundaries but may indicate a bug).
      4. If arg is a DTensor with requires_grad=True and grad is not None,
         grad must also be a DTensor.

    Args:
        stage_index: The stage index for error messages.
        args: Tuple of forward tensors.
        grads: Tuple of gradient tensors (can include None).
        is_input: True for input_args/input_grads, False for output_args/output_grads.

    Raises:
        PipeliningMetadataError: If any hard rule (1, 2, or 4) is violated.
    inputoutput_args_gradszStage r  z	 length (z) does not match zo). Each forward tensor must have a corresponding gradient entry (use None for tensors that don't require grad).Tr  Nr   z] has requires_grad=False, but z] is not None (zE). Non-differentiable tensors must have None as their gradient entry.z] has requires_grad=True, but zT] is None. This is legal at pipeline boundaries but may indicate a missing gradient.r   r  z,] is a DTensor with requires_grad=True, but z] is za, expected DTensor or None. DTensor gradients may have different placements than forward tensors.)r   r)   r  r#  r4   r  r#   r  r  r  r9   r   )
r   r   r+  r,  kind	args_name
grads_namer  r  grads
             r    'validate_static_arg_grad_correspondencer6  f  s   4 ,77HDIJ 4yyCJJ%\[ \ \J \ \U \ \\ \#&t99\ \ \
 
 	
 $CeD$A$A$ABB  ;C  	T%5)V V V	 V VA V V!V V$%V V6:4jj6IV V V    	M8 8 8	 8 8A 8 8!8 8$%8 8 8     sG$$
	!
	  tW-- ! *Y Y Y	 Y YA Y Y!Y Y$%Y Y,0JJ,?Y Y Y  5 r"   )r   r-   r<   r=   r   r6   )r   r   r   r   )r   r3   )r   )r   r   r   r   r   r   r   r   )r   r   r   r   r   r   r   r   )r5   r6   r   rl   )r   r   r   r   r   ro   )r   r   r   r   r   rr   )r   r   r   r3   r   rr   )F)r5   r6   r   r3   r   r6   ).)r   r   r   r   r   r   )r   r   r   r   r   r   )r   r  r   r3   r   r   )r  r   r  rl   r  r  r
  r3   r  r3   r   rD   )r  r   r  r   r  r  r
  r3   r  r3   r   rD   )
r   r   r   r*  r+  r   r,  r3   r   r   )=
__future__r   loggingr  dataclassesr   r   enumr   typingr   r   r	   r
   r   r   rQ   r   torch.distributed._mesh_layoutr   torch.distributed.tensorr   torch.utils._pytreer   r   torch.distributed.device_meshr   (torch.distributed.tensor.placement_typesr   	getLoggerr#   loggerr   r^   r   r'   rL   RuntimeErrorr)   r-   rO   rl   rn   r   r   r?   r   r   r   r   r   r   r   r   r   r   r   r   r  r)  r6  r   r"   r    <module>rD     s   # " " " " " "   ( ( ( ( ( ( ( (       N N N N N N N N N N N N N N N N        6 6 6 6 6 6 , , , , , , < < < < < < < <  C888888BBBBBB 
	8	$	$    h     c3ht1C CD D D D DG G G G Gl G G G $d###G G G G G G G $#GT $d###@ @ @ @ @; @ @ $#@H $l2
 2 2 2 2
 D D D D D D D D6 $d###* * * * * * * $#* $d###	 	 	 	 	 	 	 $#	   *    @  @  @  @  @  @  @  @ P0 0 0 0 0D 0 0 0p */      6+ + + 17    F 17    4                / / / /( 
 "%( ( ( ( ( 
( 
/ / / 
/ !" !" !" !" !" !"H! ! ! ! !( 
 "%* * * * 
* 
 !$1 1 1 1 
1  -
 -
 -
 -
 -
t $"B B B B B BT #"6 6 6 6 6 6rD D D D D Dr"   