Ë
    M²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,	 	 	 	 	 	 d<d!„Z-	 	 	 	 d=d"„Z. G d#„ d$«      Z/ G d%„ d&e«      Z0d'd(œd>d)„Z1d*„ Z2	 d?	 	 	 	 	 	 	 d@d+„Z3	 d?	 	 	 	 	 	 	 dAd,„Z4 ed¬«       G d-„ d.«      «       Z5dBd/„Z6edd0œ	 	 	 	 	 dCd1„«       Z7e	 	 	 	 	 	 dDd2„«       Z7d'd0œ	 	 	 	 	 dEd3„Z7dFdGd4„Z8e	 dH	 	 	 	 	 dId5„«       Z9e	 dH	 	 	 	 	 dJd6„«       Z9	 dF	 	 	 	 	 dKd7„Z9d'd'd8œ	 	 	 	 	 	 	 	 	 	 	 dLd9„Z:dd'd8œ	 	 	 	 	 	 	 	 	 	 	 dMd:„Z;	 	 	 	 	 	 	 	 	 	 dNd;„Z<y)Oé    )Ú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y)ÚGetMeshCallbackzGCallback to create/retrieve a DeviceMesh from its cache key components.c                 ó   — y ©N© )ÚselfÚmesh_dim_namesÚmesh_layouts      úb/var/www/html/ia-enhanced/venv/lib/python3.12/site-packages/torch/distributed/pipelining/_utils.pyÚ__call__zGetMeshCallback.__call__   s   € ð ó    N)r   útuple[str, ...]r   ú_MeshLayout | NoneÚreturnr   )Ú__name__Ú
__module__Ú__qualname__Ú__doc__r   r   r   r   r   r      s&   „ ÙQðà'ðð (ðð 
ô	r   r   .r   ÚMeshCacheKeyc                  ó   — e Zd ZdZy)ÚPipeliningMetadataErrorz<Raised on metadata mismatches during pipeline communication.N)r"   r#   r$   r%   r   r   r   r(   r(   ,   s   „ ÚFr   r(   T)ÚfrozenÚslotsc                  ó\   — 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y)Ú_TensorMetazðTensor 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_gradc                ó®   — t        | t        «      rt        d«      ‚t        | j                  | 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.   r0   r1   r3   )Ú
isinstancer   r(   r,   r.   r0   r1   r3   ©Útensors    r   Úfrom_tensorz_TensorMeta.from_tensor>   sM   € ô �fœgÔ&Ü)Ø\óð ô Ø—,‘,Ø—=‘=“?Ø—,‘,Ø ×.Ñ.ô	
ð 	
r   c                óT   — t        | |«      }|j                  | j                  «       |S )zÅReconstruct 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_r3   )r   ÚdeviceÚts      r   Ú	to_tensorz_TensorMeta.to_tensorV   s)   € ô # 4¨Ó0ˆØ	×Ñ˜×+Ñ+Ô,Øˆr   c                ó°  — | |k(  rg S g }| j                   |j                   k7  r+|j                  d| j                   › d|j                   › �«       | j                  |j                  k7  r+|j                  d| j                  › d|j                  › �«       | j                  |j                  k7  r+|j                  d| j                  › d|j                  › �«       |S )zÓReturn 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.   Úappendr0   r1   ©r   ÚotherÚdiffss      r   Úget_diffz_TensorMeta.get_diffc   s²   € ð �5Š=ØˆIàˆØ�:‰:˜Ÿ™Ò$Ø�L‰LÐ+¨D¯J©J¨<°t¸E¿K¹K¸=ÐIÔJØ�;‰;˜%Ÿ,™,Ò&Ø�L‰LÐ,¨T¯[©[¨M¸¸e¿l¹l¸^ÐLÔMØ�:‰:˜Ÿ™Ò$Ø�L‰LÐ+¨D¯J©J¨<°t¸E¿K¹K¸=ÐIÔJð ˆr   N)r8   útorch.Tensorr!   r,   )r=   útorch.device | strr!   rG   ©rD   r,   r!   ú	list[str])	r"   r#   r$   r%   Ú__annotations__Ústaticmethodr9   r?   rF   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y)Ú_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   € ¼U¿Z¹ZÈ»^€ r   )Údefault_factoryr-   Úglobal_shaper   )Údefaultr/   Úglobal_strideztuple[Placement, ...]Ú
placementsr   r   Nr    r   c                óp  — | j                   }t        | j                  j                  | j                  j	                  «       | j
                  | j                  | j                  | j	                  «       | j                  j                  |j                  rt        |j                  «      nd|j                  ¬«	      S )zÅCreate metadata from a DTensor.

        Args:
            dtensor: The DTensor to extract metadata from.

        Returns:
            Metadata capturing both local and global attributes.
        r   )	r.   r0   r1   r3   rT   rV   rW   r   r   )Údevice_meshrN   Ú_local_tensorr.   r0   r1   r3   Ú_specrW   r   ÚtupleÚ_layout)ÚdtensorrY   s     r   Úfrom_dtensorz_DTensorMeta.from_dtensor—   s�   € ð ×)Ñ)ˆäà×'Ñ'×-Ñ-Ø×(Ñ(×/Ñ/Ó1Ø—-‘-Ø!×/Ñ/à Ÿ™Ø!Ÿ.™.Ó*à—}‘}×/Ñ/à5@×5OÒ5O”�k×0Ñ0Ô1ÐUWà#×+Ñ+ô
ð 	
r   c                ó2   — | 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Ñ%5Ð6Ð6r   c                óÚ   — t        | |«      }t        t        t        j                  ||| j                  | j
                  | j                  d¬«      j                  | j                  «      «      S )zëReconstruct 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)rY   rW   r.   r0   Ú	run_check)	r;   r   r   Ú
from_localrW   rT   rV   r<   r3   )r   r=   ÚmeshÚlocal_tensors       r   Ú
to_dtensorz_DTensorMeta.to_dtensor¹   sd   € ô .¨d°FÓ;ˆô ÜÜ×ÑØØ ØŸ?™?Ø×'Ñ'Ø×)Ñ)Øô÷ ‰n˜T×/Ñ/Ó0ó

ð 
	
r   c                ó0  — | |k(  rg S t         j                  | |«      }t        |t        «      �rV| j                  |j                  k7  r+|j                  d| j                  › d|j                  › �«       | j                  |j                  k7  r+|j                  d| j                  › d|j                  › �«       | j                  |j                  k7  r+|j                  d| j                  › d|j                  › �«       | j                  |j                  k7  r+|j                  d| j                  › d|j                  › �«       | j                  |j                  k7  r+|j                  d| j                  › d|j                  › �«       |S |j                  d«       |S )zçReturn 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: rA   zglobal_stride mismatch: zplacements mismatch: zmesh_dim_names mismatch: zmesh_layout mismatch: z!type: _DTensorMeta vs _TensorMeta)
r,   rF   r6   rN   rT   rB   rV   rW   r   r   rC   s      r   rF   z_DTensorMeta.get_diffÒ   s…  € ð �5Š=ØˆIô
 ×$Ñ$ T¨5Ó1ˆô �eœ\Õ*Ø× Ñ  E×$6Ñ$6Ò6Ø—‘Ø-¨d×.?Ñ.?Ð-@ÀÀU×EWÑEWÐDXÐYôð ×!Ñ! U×%8Ñ%8Ò8Ø—‘Ø.¨t×/AÑ/AÐ.BÀ$Àu×GZÑGZÐF[Ð\ôð �‰ %×"2Ñ"2Ò2Ø—‘Ø+¨D¯O©OÐ+<¸DÀ×AQÑAQÐ@RÐSôð ×"Ñ" e×&:Ñ&:Ò:Ø—‘Ø/°×0CÑ0CÐ/DÀDÈ×I]ÑI]ÐH^Ð_ôð ×Ñ 5×#4Ñ#4Ò4Ø—‘Ø,¨T×-=Ñ-=Ð,>¸dÀ5×CTÑCTÐBUÐVôð ˆð �L‰LÐ<Ô=àˆr   )r^   r   r!   rN   )r!   r&   )r=   rH   rf   r   r!   r   rI   )r"   r#   r$   r%   r   rT   rK   rV   rW   r   r   rL   r_   Úpropertyrb   rh   rF   r   r   r   rN   rN   {   s—   … ñ	ñ  %Ñ5KÔL€L�*ÓLÙ%*°2Ô%6€M�?Ó6ñ ).Øô)€JÐ%ó ñ
 ',°BÔ&7€N�OÓ7Ù&+Øô'€KÐ#ó ð ò
ó ð
ð8 ò7ó ð7ó
ô2*r   rN   Ú
TensorMeta)r*   c                  ób   — 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y)Ú
_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_gradsc                ó~   — t        d„ | j                  | j                  | j                  | j                  fD «       «      S )z)Check if any metadata field is populated.c              3  ó$   K  — | ]  }|d u–— Œ
 y ­wr   r   )Ú.0Úvs     r   ú	<genexpr>z%_StageMeta.has_any.<locals>.<genexpr>  s   è ø€ ò 
àð �TŒMñ
ùs   ‚)Úanyro   rp   rr   rs   ra   s    r   Úhas_anyz_StageMeta.has_any  s9   € äñ 
à—k‘k 4§<¡<°×1AÑ1AÀ4×CTÑCTÐUô
ó 
ð 	
r   c                ól   — | j                   | j                  fD ]  }|sŒt        d„ |D «       «      sŒ y y)z3Check if any input/output metadata is DTensor type.c              3  óB   K  — | ]  }|sŒt        |t        «      –— Œ y ­wr   )r6   rN   ©rv   Úms     r   rx   z*_StageMeta.has_dtensors.<locals>.<genexpr>  s   è ø€ ÒM¸QÊ1œZ¨¬<×8ÑMùs   ‚ŠTF)ro   rp   ry   )r   Úmetass     r   Úhas_dtensorsz_StageMeta.has_dtensors  s6   € à—k‘k 4§<¡<Ð0ò 	ˆEÚœÑMÀ%ÔMÕMÙð	ð r   c                ó>   — | j                   duxr | j                  duS )z-Check if forward metadata is fully populated.N)ro   rp   ra   s    r   Úis_complete_for_forwardz"_StageMeta.is_complete_for_forward  s   € à�{‰{ $Ð&ÒC¨4¯<©<¸tÐ+CÐCr   )r!   r2   )r"   r#   r$   r%   ro   rK   rp   rr   rs   rz   r€   r‚   r   r   r   rm   rm     sA   … áZà,0€FÐ)Ó0Ø-1€GÐ*Ó1Ø8<€KÐ5Ó<Ø9=€LÐ6Ó=ó
óôDr   rm   c                  ó   — e Zd ZU dZded<   y)Ú_StageForwardMetazLForward metadata transmitted from stage *i* to stage *i+1* during inference.útuple[TensorMeta, ...]Úforward_metasN©r"   r#   r$   r%   rK   r   r   r   r„   r„   !  s   … áVà)Ô)r   r„   c                  ó   — e Zd ZU dZded<   y)Ú_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‰   (  s   … ñðô r   r‰   c                óp   — t        j                  | j                  | j                  | j                  |¬«      S )zÙCreate 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.
    )Úsizer0   r1   r=   )rP   Úempty_stridedr.   r0   r1   )Úmetar=   s     r   r;   r;   5  s/   € ô ×ÑØ�Z‰ZØ�{‰{Ø�j‰jØô	ð r   c                ó&   — t        d„ | D «       «      S )zÑDerive 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  ó’   K  — | ]?  }|j                   r-t        |j                  |j                  |j                  d ¬«      nd–— ŒA y­w)Fr5   N)r3   r,   r.   r0   r1   r}   s     r   rx   z%_derive_grad_metas.<locals>.<genexpr>R  sC   è ø€ ò ð ð �?Š?ô 	˜!Ÿ'™'¨!¯(©(¸!¿'¹'ÐQVÕWàó	ñùs   ‚AA)r\   )Útensor_metass    r   Ú_derive_grad_metasr“   J  s    € ô ñ ð ô	ó ð r   c                  óB   — 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	y)Ú
_MeshCachezæCache 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).
    Nc                ó    — i | _         || _        y r   )Ú_cacheÚ_get_mesh_cb)r   Úget_mesh_cbs     r   Ú__init__z_MeshCache.__init__a  s   € Ø68ˆŒØ'ˆÕr   c                óð   — || j                   v r| j                   |   S |\  }}| j                  €t        d|› d|› d�«      ‚| j                  ||«      }|€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.
        z+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   Úkeyr   r   rf   s        r   Úget_meshz_MeshCache.get_meshe  sº   € ð �$—+‘+ÑØ—;‘;˜sÑ#Ð#à&)Ñ#ˆ˜à×ÑÐ$Ü)Ø=¸nÐ=Mð NØ*˜mð ,NðOóð ð × Ñ  °Ó=ˆØˆ<Ü)ð"Ø"0Ð!1°À¸}ð MGðHóð ð
  ˆ�‰�CÑØˆr   c                ó"   — || j                   |<   y)zAdd a mesh to the cache.N©r—   )r   rœ   rf   s      r   Úputz_MeshCache.put‡  s   € àˆ�‰�CÒr   c                óî   — |D ]p  }t        |t        «      sŒ|j                  }|j                  rt	        |j                  «      nd}|j
                  }||f}|| j                  vsŒb|| j                  |<   Œr y)zJExtract and cache meshes from any :class:`DTensor` instances in *tensors*.r   N)r6   r   rY   r   r\   r]   r—   )r   Útensorsr8   rf   Ú	dim_namesr   rœ   s          r   Úupdate_from_tensorsz_MeshCache.update_from_tensors‹  sn   € àò 	,ˆFÜ˜&¤'Õ*Ø×)Ñ)�Ø:>×:MÒ:MœE $×"5Ñ"5Ô6ÐSU�	Ø"Ÿl™l�Ø  +Ð.�Ø˜dŸk™kÒ)Ø'+�D—K‘K Ò$ñ	,r   c                ó   — || j                   v S r   rŸ   )r   rœ   s     r   Ú__contains__z_MeshCache.__contains__–  s   € Ø�d—k‘kÐ!Ð!r   c                ó,   — t        | j                  «      S r   )Úlenr—   ra   s    r   Ú__len__z_MeshCache.__len__™  s   € Ü�4—;‘;ÓÐr   r   )r™   zGetMeshCallback | Noner!   ÚNone)rœ   r&   r!   r   )rœ   r&   rf   r   r!   rª   )r¢   útuple[torch.Tensor | None, ...]r!   rª   )rœ   r&   r!   r2   )r!   Úint)
r"   r#   r$   r%   rš   r�   r    r¤   r¦   r©   r   r   r   r•   r•   Z  s&   „ ñô(ó óD ó	,ó"ô r   r•   c                  ó*   — e Zd ZdZdZdZedd„«       Zy)Ú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Údynamicc                ó€   — |j                  «       sy|j                  «       sy|sy|j                  �|j                  €yy)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€   rr   rs   )Úclsr�   Ústage_has_backwards      r   Úneeds_dynamiczInferenceMode.needs_dynamicµ  sM   € ð ×+Ñ+Ô-Øð × Ñ Ô"Øñ "Øð ×ÑÐ# t×'8Ñ'8Ð'@Øð r   N)r�   rm   r³   r2   r!   r2   )r"   r#   r$   r%   ÚSTATICÚDYNAMICÚclassmethodr´   r   r   r   r®   r®   ¢  s%   „ ñð €FØ€Gàòó ñr   r®   F©Údetachc               óô   — t        | «      \  }}|rb|D �cg c]G  }t        |t        j                  «      r)|j	                  «       j                  |j                  «      n|‘ŒI }}t        ||«      }||fS |S c c}w )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.
    )r   r6   rP   ÚTensorr¹   r<   r3   r   )Úargsr¹   Ú	flat_argsÚtreespecÚaÚflat_detachedÚnew_argss          r   Úflatten_argsrÂ   Ú  sˆ   € ô ' tÓ,Ñ€Iˆxáð
 ö	
ð ô ˜!œUŸ\™\Ô*ð �H‰H‹J×%Ñ% a§o¡oÔ6àñð
ˆð 
ô " -°Ó:ˆØ˜Ð&Ð&àÐùò
s   •AA5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   c                ó  — i }|dk(  rt        |«      D ]
  }|| z  ||<   Œ |S |dk(  rU|| z  dk7  rt        d|› d| › d�«      ‚d}t        |«      D ])  }|||<   |dz   | z  dk(  rŒ|| z  dz  dk(  r|dz  }Œ%|dz  }Œ+ |S t        d	|› d
�«      ‚)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.
    Úlooprw   r   znum_stages z% must be evenly divisible by pp_size z for V schedulesé   é   zStyle z is not supported.)ÚrangeÚ
ValueError)Úpp_sizeÚ
num_stagesÚstyleÚmappingÚstage_indexÚ
rank_indexs         r   Úgenerate_stage_to_rank_mappingrÑ   ú  sì   € ð €GØ�‚Ü  Ó,ò 	9ˆKØ#.°Ñ#8ˆG�KÒ ð	9ð( €Nð% 
�#ŠØ˜Ñ 1Ò$ÜØ˜j˜\Ð)NÈwÈiÐWgÐhóð ð ˆ
Ü  Ó,ò 	 ˆKØ#-ˆG�KÑ à˜a‘ 7Ñ*¨aÒ/ØØ˜wÑ&¨!Ñ+¨qÒ0Ø˜a‘‘
à˜a‘‘
ð	 ð €Nô ˜6 % Ð(:Ð;Ó<Ð<r   c                óØ   — t        | ||«      }i }|j                  «       D ]"  \  }}||vrg ||<   ||   j                  |«       Œ$ |j                  «       D ]  }|j	                  «        Œ |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Ñ   ÚitemsrB   ÚvaluesÚsort)rË   rÌ   rÍ   Ústage_to_rankÚrank_to_stagesÚstage_idÚrankÚstagess           r   Úgenerate_rank_to_stage_mappingrÛ     s…   € ô 3°7¸JÈÓN€Mð ,.€NØ'×-Ñ-Ó/ò .‰ˆ�$Ø�~Ñ%Ø#%ˆN˜4Ñ Ø�tÑ×#Ñ# HÕ-ð.ð !×'Ñ'Ó)ò ˆØ�‰�ðð Ðr   c                  ó0   — e Zd ZU dZded<   ded<   ded<   y)	ÚPipeInfoz>
    Captures information for a pipeline (`Pipe` object).
    zfx.GraphÚgraphr¬   rÌ   r2   Úhas_loss_and_backwardNr‡   r   r   r   rÝ   rÝ   6  s   … ñð ƒOØƒOØÔr   rÝ   c                óv   — t        | t        «      rt        j                  | «      S t        j                  | «      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.
    )r6   r   rN   r_   r,   r9   r7   s    r   Úextract_tensor_metará   F  s0   € ô �&œ'Ô"Ü×(Ñ(¨Ó0Ð0ä×&Ñ& vÓ.Ð.r   )Ú
allow_nonec                ó   — y r   r   ©r¢   râ   s     r   Úextract_tensor_metasrå   Z  s   € ð
 %(r   c                ó   — y r   r   rä   s     r   rå   rå   b  s   € ð
 ,/r   c               óâ   — | €yg }d}| D ]J  }t        |t        j                  «      r|j                  t	        |«      «       Œ8d}|j                  d«       ŒL |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.)r6   rP   r»   rB   rá   r(   r\   )r¢   râ   Úmetas_with_noneÚhas_noner>   s        r   rå   rå   j  s€   € ð" €Øà/1€OØ€HØò )ˆÜ�aœŸ™Ô&Ø×"Ñ"Ô#6°qÓ#9Õ:àˆHØ×"Ñ" 4Õ(ð)ñ ™(Ü%ð7ó
ð 	
ô �Ó!Ð!r   c                ón   — |r| j                  «       n| }t        |t        «      r|j                  «       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¹   r6   r   Úto_local)r8   r¹   Úmaybe_detached_tensors      r   Úto_local_if_dtensorrí   Ž  s4   € ñ 06˜FŸM™MœO¸6ÐÜÐ'¬Ô1Ø$×-Ñ-Ó/Ð/Ø Ð r   c                 ó   — y r   r   ©r¼   râ   s     r   Úvalidate_and_normalize_to_tuplerð   ¢  s   € ð '*r   c                 ó   — y r   r   rï   s     r   rð   rð   ©  s   € ð .1r   c           	     ó¸  — | €yt        | t        j                  «      r| fS t        | t        t        f«      rƒt        | «      D ]X  \  }}|€|st        d|› d�«      ‚Œt        |t        j                  «      rŒ5t        d|› dt        |«      j                  › d�«      ‚ t        | t        «      rt        | «      S | 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 ú.)	r6   rP   r»   r\   ÚlistÚ	enumerater(   Útyper"   )r¼   râ   ÚiÚargs       r   rð   rð   ³  só   € ð, €|ØÜ	�Dœ%Ÿ,™,Ô	'ØˆwˆÜ	�Dœ5¤$˜-Ô	(Ü “oò 	‰FˆAˆsØˆ{Ù!Ü1Ø$ Q Cð (Vð Wóð ð Ü˜c¤5§<¡<Õ0Ü-Ø    ;¬t°C«y×/AÑ/AÐ.Bð CXð Yóð ð	ô )¨¬tÔ4Œu�T‹{Ð>¸$Ð>ä%ØJÌ4ÐPTË:×K^ÑK^ÐJ_Ð_`Ðaó
ð 	
r   ©Úraise_on_mismatchÚwarn_on_mismatchc               ó*  — t        |t        j                  «      rt        |«      }n|}t	        |«      t	        |«      urmdt	        |«      j
                  › dt	        |«      j
                  › �g}|rt        | › d|d   › �«      ‚|r%t        j                  | › d|d   › d�t        d¬«       |S |j                  |«      }|rT|rt        | › dd	j                  |«      › �«      ‚|r1t        j                  | › d
d	j                  |«      › 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. )r6   rP   r»   rá   rö   r"   r(   ÚwarningsÚwarnÚUserWarningrF   Újoin)ÚdescÚexpectedÚactualrú   rû   Úactual_metaÚ	type_diffrE   s           r   Úvalidate_metadatar
  è  s0  € ô> �&œ%Ÿ,™,Ô'Ü)¨&Ó1‰àˆô ˆHƒ~œT +Ó.Ñ.àœd 8›n×5Ñ5Ð6°f¼TÀ+Ó=N×=WÑ=WÐ<XÐYð
ˆ	ñ Ü)¨T¨F°"°Y¸q±\°NÐ*CÓDÐDÙÜ�M‰MØ�&Ð2°9¸Q±<°.ð A?ð @äØõ	ð Ðð ×Ñ˜kÓ*€EáÙÜ)¨T¨F°"°T·Y±Y¸uÓ5EÐ4FÐ*GÓHÐHÙÜ�M‰MØ�&Ð-¨d¯i©i¸Ó.>Ð-?ð @?ð @äØõ	ð €Lr   c               ó  — t        |«      t        |«      k7  rJ| › dt        |«      › dt        |«      › �}|rt        |«      ‚|rt        j                  |t        d¬«       |gS g }t        t        ||d¬«      «      D ]Š  \  }\  }}	|€|	€Œ|�|	€R| › d|› d|€d	nd
› d|	€d	nd
› �}|rt        |«      ‚|rt        j                  |t        d¬«       |j                  |«       Œdt        | › d|› d�||	||¬«      }
|j                  |
«       ŒŒ |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©Ústrictú[z]: expected rª   Úmetadatarý   ú]rù   )
r¨   r(   r  r  r  rõ   ÚziprB   r
  Úextend)r  r  r  rú   rû   ÚmsgÚ	all_diffsr÷   ÚexpÚactrE   s              r   Úvalidate_tensors_metadatar  -  s>  € ô. ˆ8ƒ}œ˜F›Ò#Ø��k¤# h£- °¼sÀ6»{¸mÐLˆÙÜ)¨#Ó.Ð.ÙÜ�M‰M˜#œ{°qÕ9Øˆuˆà€IÜ"¤3 x°ÀÔ#EÓFò  ‰ˆ‰:ˆC�Øˆ;˜3˜;ØØˆ;˜#˜+à�&˜˜!˜˜L°3°;©ÀJÐ(Oð PØ!$ ‘v°*Ð=ð?ð ñ !Ü-¨cÓ2Ð2ÙÜ—‘˜c¤;¸1Õ=Ø×Ñ˜SÔ!ØÜ!Øˆf�A�a�S˜ˆNØØØ/Ø-ô
ˆð 	×Ñ˜Õð+ ð, Ðr   c                ó¦  — |rdnd}|› d�}|› d�}t        |«      t        |«      k7  r-t        d| › d|› dt        |«      › d|› dt        |«      › d	�«      ‚t        t        ||d
¬«      «      D ]ã  \  }\  }}	|j                  s3|	�1t        d| › d|› d|› d|› d|› dt        |	«      j                  › d�«      ‚|j                  r.|	€,t        j                  d| › d|› d|› d|› d|› d�t        d¬«       t        |t        «      sŒ“|j                  sŒ |	€Œ£t        |	t        «      rŒ´t        d| › d|› d|› d|› d|› dt        |	«      j                  › d�«      ‚ y)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  r3   rö   r"   r  r  r  r6   r   )
rÏ   r¼   ÚgradsÚis_inputÚkindÚ	args_nameÚ
grads_namer÷   rø   Úgrads
             r   Ú'validate_static_arg_grad_correspondencer#  f  s½  € ñ4 ‰7 H€DØ�&˜�€IØ�6˜�€Jô ˆ4ƒy”C˜“JÒÜ%Ø�[�M  J <¨y¼¸U»¸ÐDUØˆk˜¤3 t£9 +ð .[ð\ó
ð 	
ô $¤C¨¨e¸DÔ$AÓBò ‰ˆ‰;ˆC�à× Ò  TÐ%5Ü)Ø˜˜ R¨	 {°!°A°3ð 7Ø!�l ! A 3 o´d¸4³j×6IÑ6IÐ5Jð KUðVóð ð ×Ò  Ü�M‰MØ˜˜ R¨	 {°!°A°3ð 7Ø!�l ! A 3ð '7ð8ô Øõô �sœGÕ$Ø×!Ó!ØÑ Ü˜t¤WÕ-ä)Ø˜˜ R¨	 {°!°A°3ð 7Ø!�l ! A 3 e¬D°«J×,?Ñ,?Ð+@ð AXðYóð ñ5r   )r�   r,   r=   rH   r!   rG   )r’   r…   r!   ztuple[_TensorMeta | None, ...])r¹   r2   )rÆ   )rË   r¬   rÌ   r¬   rÍ   Ústrr!   zdict[int, int])rË   r¬   rÌ   r¬   rÍ   r$  r!   zdict[int, list[int]])r8   rG   r!   rk   )r¢   útuple[torch.Tensor, ...] | Nonerâ   úLiteral[False]r!   rn   )r¢   ú&tuple[torch.Tensor | None, ...] | Nonerâ   úLiteral[True]r!   rq   )r¢   úAtuple[torch.Tensor | None, ...] | tuple[torch.Tensor, ...] | Nonerâ   r2   r!   rq   )F)r8   rG   r¹   r2   r!   rG   ).)r¼   zCtorch.Tensor | tuple[torch.Tensor, ...] | list[torch.Tensor] | Nonerâ   r&  r!   r%  )r¼   zQtorch.Tensor | tuple[torch.Tensor | None, ...] | list[torch.Tensor | None] | Nonerâ   r(  r!   r'  )r¼   z�torch.Tensor | tuple[torch.Tensor, ...] | tuple[torch.Tensor | None, ...] | list[torch.Tensor] | list[torch.Tensor | None] | Nonerâ   r2   r!   r)  )r  r$  r  rk   r  ztorch.Tensor | TensorMetarú   r2   rû   r2   r!   rJ   )r  r$  r  rŠ   r  z,tuple[torch.Tensor | TensorMeta | None, ...]rú   r2   rû   r2   r!   rJ   )
rÏ   r¬   r¼   ztuple[torch.Tensor, ...]r  r«   r  r2   r!   rª   )=Ú
__future__r   Úloggingr  Údataclassesr   r   Úenumr   Útypingr   r   r	   r
   r   r   rP   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&   rK   ÚRuntimeErrorr(   r,   rN   rk   rm   r„   r‰   r;   r“   r•   r®   rÂ   rÄ   rÑ   rÛ   rÝ   rá   rå   rí   rð   r
  r  r#  r   r   r   ú<module>r7     s	  ðö #ã Û ß (Ý ß N× Nã Ý Ý 6Ý ,ß <ñ Ý8ÝBð 
ˆ×	Ñ	˜8Ó	$€ô�hô ð    c¨3 h¡°¸tÑ1CÐ CÑD€ˆiÓ DôG˜lô Gñ �$˜dÔ#÷Gð Gó $ðGñT �$˜dÔ#ô@�;ó @ó $ð@ðH $ lÑ2€
ˆIÓ 2ñ
 �Ô÷Dð Dó ðDñ6 �$˜dÔ#÷*ð *ó $ð*ñ �$˜dÔ#÷	ð 	ó $ð	ðØ
ðàðð óð*Ø(ðà#ó÷ @ ñ @ ôP0�Dô 0ðp */õ ò6+ð 17ðØðØ!ðØ*-ðàóðF 17ðØðØ!ðØ*-ðàóñ4 �Ô÷ ð  ó ð ó/ð( 
ð "%ñ(Ø,ð(ð ð(ð #ò	(ó 
ð(ð 
ð/Ø3ð/ð ð/ð *ò	/ó 
ð/ð ñ!"ØNð!"ð ð!"ð *ó	!"ôH!ð( 
ð "%ð*Ø
Mð*àð*ð %ò*ó 
ð*ð 
ð !$ð1ðð1ð
 ð1ð ,ò1ó 
ð1ð  ð-
ðð-
ð ð-
ð Gó-
ðt $Ø"ñBØ
ðBàðBð &ðBð
 ðBð ðBð óBðT #Ø"ñ6Ø
ð6à+ð6ð 9ð6ð
 ð6ð ð6ð ó6ðrDØðDà
"ðDð +ðDð ð	Dð
 
ôDr   