+
    –°³jÐ4  ã                   óª   € ^ RI t ^ RIHtHt ^ RIHt ^ RIHtHt ^ RI	t	^ RI
Ht . ROt ! R R4      t ! R	 R]4      t ! R
 R]4      t ! R R4      tR# )é    N)ÚABCÚabstractmethod)ÚTracebackType)ÚAnyÚ
NamedTupleÚJoinHookÚJoinableÚJoinc                   óH   a € ] tR t^t o RtV 3R lR ltV 3R lR ltRtV tR# )r   a¯  
This defines a join hook, which provides two entry points in the join context manager.

Entry points : a main hook, which is called repeatedly while there exists a non-joined
process, and a post-hook, which is called once all processes have joined.

To implement a join hook for the generic join context manager, define a
class that inherits from :class:`JoinHook` and override ``main_hook()`` and
``post_hook()`` as appropriate.
c                ó   <€ V ^8„  d   QhRR/# ©é   ÚreturnN© )ÚformatÚ__classdict__s   "€Úb/home/luca/screen-checking/.venv/lib/python3.14/site-packages/torch/distributed/algorithms/join.pyÚ__annotate__ÚJoinHook.__annotate__   s   ø€ ÷ ñ ˜4ñ ó    c                ó   € R# )zÆCall this hook while there exists a non-joined process to shadow collective communications in a training iteration.

Training iteration i.e., in one forward pass, backward pass, and optimizer step.
Nr   ©Úselfs   &r   Ú	main_hookÚJoinHook.main_hook   ó   ‚ r   c                ó$   <€ V ^8„  d   QhRS[ RR/# )r   Úis_last_joinerr   N©Úbool)r   r   s   "€r   r   r       s   ø€ ÷ 	ñ 	©ð 	°ñ 	r   c                ó   € R# )a  
Call hook after all processes have joined.

It is passed an additional ``bool`` argument ``is_last_joiner``, which indicates if the rank is one of the last to join.

Arguments:
    is_last_joiner (bool): ``True`` if the rank is one of the last to
        join; ``False`` otherwise.
Nr   )r   r   s   &&r   Ú	post_hookÚJoinHook.post_hook    r   r   r   N)	Ú__name__Ú
__module__Ú__qualname__Ú__firstlineno__Ú__doc__r   r"   Ú__static_attributes__Ú__classdictcell__©r   s   @r   r   r      s   ø‡ € ñ	÷ð ÷	ö 	r   c                   ó´   a a€ ] tR t^,t oRt]V3R lV 3R ll4       t]V3R lR l4       t]]V3R lR l4       4       t	]]V3R lR	 l4       4       t
R
tVtV ;t# )r	   aC  
This defines an abstract base class for joinable classes.

A joinable class
(inheriting from :class:`Joinable`) should implement :meth:`join_hook`,
which returns a :class:`JoinHook` instance, in addition to
:meth:`join_device` and :meth:`join_process_group` that return device and
process group information, respectively.
c                ó   <€ V ^8„  d   QhRR/# r   r   )r   r   s   "€r   r   ÚJoinable.__annotate__8   s   ø€ ÷ Iñ I˜$ñ Ir   c                óV   <€ \         SV `  4        \        P                  4       V n        R # ©N)ÚsuperÚ__init__Ú_JoinConfigÚconstruct_disabled_join_configÚ_join_config)r   Ú	__class__s   &€r   r2   ÚJoinable.__init__7   s   ø€ ä‰ÑÔÜ'×FÑFÓHˆÖr   c                ó    <€ V ^8„  d   QhRS[ /# ©r   r   )r   )r   r   s   "€r   r   r.   =   s   ø€ ÷ 
ñ 
¡Xñ 
r   c                ó   € R# )aV  
Return a :class:`JoinHook` instance for the given :class:`Joinable`.

Arguments:
    kwargs (dict): a :class:`dict` containing any keyword arguments
        to modify the behavior of the join hook at run time; all
        :class:`Joinable` instances sharing the same join context
        manager are forwarded the same value for ``kwargs``.
Nr   )r   Úkwargss   &,r   Ú	join_hookÚJoinable.join_hook<   s   € ñ 	r   c                ó4   <€ V ^8„  d   QhRS[ P                  /# r9   )ÚtorchÚdevice)r   r   s   "€r   r   r.   K   s   ø€ ÷ ñ ™UŸ\™\ñ r   c                ó   € R# )zeReturn the device from which to perform collective communications needed by the join context manager.Nr   r   s   &r   Újoin_deviceÚJoinable.join_deviceI   ó   € ñ 	r   c                ó    <€ V ^8„  d   QhRS[ /# r9   )r   )r   r   s   "€r   r   r.   Q   s   ø€ ÷ ñ ¡Cñ r   c                ó   € R# )zfReturns the process group for the collective communications needed by the join context manager itself.Nr   r   s   &r   Újoin_process_groupÚJoinable.join_process_groupO   rD   r   )r5   )r$   r%   r&   r'   r(   r   r2   r<   ÚpropertyrB   rG   r)   r*   Ú__classcell__)r6   r   s   @@r   r	   r	   ,   sw   ù‡ € ñð ÷Iò Ió ðIð ÷
ó ð
ð Ø÷ó ó ðð Ø÷ó ó ÷ð r   c                   ó@   a € ] tR t^Vt o Rt]R 4       tV 3R ltRtV t	R# )r3   zdThis includes all fields needed from a :class:`Joinable` instance for the join context manager side.c                 ó   € \        RRRR7      # )z”Return a :class:`_JoinConfig` instance indicating that join-related logic should be disabled.

e.g. if the caller is not in a join context manager.
F©ÚenableÚthrow_on_early_terminationÚis_first_joinable)r3   r   r   r   r4   Ú*_JoinConfig.construct_disabled_join_config]   s   € ô Ø°UÈeô
ð 	
r   c                ó>   <€ V ^8„  d   Qh/ S[ ;R&   S[ ;R&   S[ ;R&   # )r   rN   rO   rP   r   )r   r   s   "€r   r   Ú_JoinConfig.__annotate__V   s+   ø‡ ‚ ñ �Lñ ñ !%Ñ$ñ	 ñ
 Ñò r   r   N)
r$   r%   r&   r'   r(   Ústaticmethodr4   Ú__annotate_func__r)   r*   r+   s   @r   r3   r3   V   s#   ø‡ € Ùoð ñ
ó ð
÷ ƒ r   r3   c                   óž   a € ] tR t^ht o RtRV 3R lR lltV 3R lR ltV 3R lR ltR tV 3R	 lR
 lt	R t
R t]V 3R lR l4       tRtV tR# )r
   a
  
This class defines the generic join context manager, which allows custom hooks to be called after a process joins.

These hooks should shadow the
collective communications of non-joined processes to prevent hanging and
erroring and to ensure algorithmic correctness. Refer to :class:`JoinHook`
for details about the hook definition.

.. warning::
    The context manager requires each participating :class:`Joinable` to
    call the method :meth:`notify_join_context()` before its own per-
    iteration collective communications to ensure correctness.

.. warning::
    The context manager requires that all ``process_group`` attributes in
    the :class:`JoinHook` objects are the same. If there are multiple
    :class:`JoinHook` objects, then the ``device`` of the first is used.
    The process group and device information is used for checking for non-
    joined processes and for notifying processes to throw an exception if
    ``throw_on_early_termination`` is enabled, both of which using an all-
    reduce.

Arguments:
    joinables (List[Joinable]): a list of the participating
        :class:`Joinable` s; their hooks are iterated over in the given
        order.

    enable (bool): a flag enabling uneven input detection; setting to
        ``False`` disables the context manager's functionality and should
        only be set when the user knows the inputs will not be uneven
        (default: ``True``).

    throw_on_early_termination (bool): a flag controlling whether to throw an
        exception upon detecting uneven inputs (default: ``False``).

Example::

    >>> import os
    >>> import torch
    >>> import torch.distributed as dist
    >>> import torch.multiprocessing as mp
    >>> # xdoctest: +SKIP
    >>> import torch.nn.parallel.DistributedDataParallel as DDP
    >>> import torch.distributed.optim.ZeroRedundancyOptimizer as ZeRO
    >>> from torch.distributed.algorithms.join import Join
    >>>
    >>> # On each spawned worker
    >>> def worker(rank):
    >>>     dist.init_process_group("nccl", rank=rank, world_size=2)
    >>>     model = DDP(torch.nn.Linear(1, 1).to(rank), device_ids=[rank])
    >>>     optim = ZeRO(model.parameters(), torch.optim.Adam, lr=0.01)
    >>>     # Rank 1 gets one more input than rank 0
    >>>     inputs = [torch.tensor([1.]).to(rank) for _ in range(10 + rank)]
    >>>     with Join([model, optim]):
    >>>         for input in inputs:
    >>>             loss = model(input).sum()
    >>>             loss.backward()
    >>>             optim.step()
    >>>     # All ranks reach here without hanging/erroring
c                ó<   <€ V ^8„  d   QhRS[ S[,          RS[RS[/# )r   Ú	joinablesrN   rO   )Úlistr	   r    )r   r   s   "€r   r   ÚJoin.__annotate__¦   s-   ø€ ÷ "ñ "á™•>ð"ñ ð"ñ %)ñ	"r   c                ó
  € \        V4      ^ 8X  d   \        R4      hWn        V P                   Uu. uF  qUP                  ! R/ VB NK  	  upV n        W n        W0n        V P                  4        V P                  4        R# u upi )r   z7The join context manager requires at least one joinableNr   )	ÚlenÚ
ValueErrorÚ
_joinablesr<   Ú_join_hooksÚ_enableÚ_throw_on_early_terminationÚ_set_joinable_configsÚ_extract_dist_info)r   rX   rN   rO   r;   Újoinables   &&&&, r   r2   ÚJoin.__init__¦   sw   € ô ˆy‹>˜QÔÜÐVÓWÐWØ#Œà9=¿ºó
Ù9H¨X×ÒÑ( Ô(¹ñ
ˆÔð ŒØ+EÔ(Ø×"Ñ"Ô$Ø×ÑÖ!ùò
s   °B c                ó   <€ V ^8„  d   QhRR/# r   r   )r   r   s   "€r   r   rZ   ¸   s   ø€ ÷ &ñ & tñ &r   c                óÂ   € \        V P                  4      ^ 8:  d   \        hRpV P                   F,  p\        V P                  V P
                  VR7      Vn        RpK.  	  R# )zESet the :class:`_JoinConfig` of each participating :class:`Joinable`.TrM   FN)r\   r^   ÚAssertionErrorr3   r`   ra   r5   )r   rP   rd   s   &  r   rb   ÚJoin._set_joinable_configs¸   sU   € äˆt�‰Ó 1Ô$Ü Ð Ø ÐØŸœˆHÜ$/Ø—|‘|Ø+/×+KÑ+KØ"3ô%ˆHÔ!ð
 !&Òó (r   c                ó   <€ V ^8„  d   QhRR/# r   r   )r   r   s   "€r   r   rZ   Å   s   ø€ ÷ ñ  Dñ r   c                ó  € RpRpV P                    FA  pVf   VP                  pMWP                  8w  d   \        R4      hVe   K5  VP                  pKC  	  Wn        \
        P                  ! V P                  4      V n        W n        R# )as  
Extract the process group and device information from the joinables.

If there are multiple joinables, then the context manager uses the
first specified device.

Preconditions:
    ``self._joinables`` is not ``None`` and is non-empty.

Raises:
    ValueError
        If there are multiple conflicting ``process_group`` attributes
        among the ``Joinable`` objects.
Nz7Using join context manager with multiple process groups)	r^   rG   r]   rB   Ú_process_groupÚdistÚget_rankÚ_rankÚ_device)r   Úprocess_groupr@   rd   s   &   r   rc   ÚJoin._extract_dist_infoÅ   s~   € ð ˆØˆàŸœˆHØÒ$Ø (× ;Ñ ;‘Ø×"=Ñ"=Ô=Ü ØMóð ð Œ~Ø!×-Ñ-’ñ (ð ,ÔÜ—]’] 4×#6Ñ#6Ó7ˆŒ
ØŽr   c                ó   € R # r0   r   r   s   &r   Ú	__enter__ÚJoin.__enter__ä   s   € ™r   c                óf   <€ V ^8„  d   QhRS[ S[,          R,          RS[R,          RS[R,          /# )r   ÚtypeNÚvalueÚ	traceback)rw   ÚBaseExceptionr   )r   r   s   "€r   r   rZ   æ   s=   ø€ ÷ 30ñ 30á‘=Õ! DÕ(ð30ñ ˜tÕ#ð30ñ ! 4Õ'ñ	30r   c           	     ó  € V P                   '       d	   V'       d   R# RpRp^ pRp\        P                  ! R4       V'       g    Wg8”  d-   \        P                  ! RV RV P                   RV R	2^R
7       V P                  4       pV^ 8X  d   RpKU  V P                  '       d   V P                  4        V P                   F  p	V	P                  4        K  	  RpV^,          pK§  V P                   F  p	V	P                  V4       K  	  R# )zŸ
Repeatedly runs the main hooks until all processes join; then, runs the post-hooks.

Raises:
    RuntimeError
        If ``throw_on_early_termination=True``.
NFTiè  Úoncez+Detected uneven input skew of greater than z. This means that rank z has at least zz fewer inputs than other currently-active ranks. This level of skew could lead to performance degradation during training.)Ú
stacklevel)r`   ÚwarningsÚsimplefilterÚwarnro   Ú_get_num_nonjoined_procsra   Ú_notify_procs_to_terminater_   r   r"   )
r   rw   rx   ry   Úall_procs_joinedr   ÚiÚWARN_THRESHOLDÚnum_nonjoined_procsr<   s
   &&&&      r   Ú__exit__ÚJoin.__exit__æ   sû   € ð �|�|ˆ|ŸtÙà ÐØˆàˆØˆÜ×Ò˜fÔ%ç"ØÔ!Ü—’ØAØ%Ð&Ð&=Ø—z‘z�l .°Ð0@ð A3ð3ð  !õð #'×"?Ñ"?Ó"AÐØ" aÔ'Ø#'Ò à×3×3Ð3Ø×3Ñ3Ô5ð "&×!1Ô!1�IØ×'Ñ'Ö)ñ "2ð "'�Ø�Q•’ð ×)Ô)ˆIØ×Ñ Ö/ó *r   c                ó¨   € \         P                  ! ^V P                  R7      p\        P                  ! WP
                  R7       VP                  4       # )zaReturn the number of non-joined processes by shadowing an all-reduce in the non-joined processes.©r@   ©Úgroup)r?   Úzerosrp   rm   Ú
all_reducerl   Úitem)r   r†   s   & r   r�   ÚJoin._get_num_nonjoined_procs  s9   € ä#Ÿkšk¨!°D·L±LÔAÐÜ�ŠÐ+×3FÑ3FÕGØ"×'Ñ'Ó)Ð)r   c                óº   € \         P                  ! ^V P                  R7      p\        P                  ! WP
                  R7       \        RV P                   R24      h)z¡Schedule an all-reduce to notify non-joined processes to terminate.

Also raise a ``RuntimeError`` indicating that the current process has exhausted its inputs.
rŠ   r‹   zRank z exhausted all inputs.)r?   Úonesrp   rm   rŽ   rl   ÚRuntimeErrorro   )r   r’   s   & r   r‚   ÚJoin._notify_procs_to_terminate!  sC   € ô
 �zŠz˜! D§L¡LÔ1ˆÜ�Š˜×$7Ñ$7Õ8Ü˜U 4§:¡: ,Ð.DÐEÓFÐFr   c                ó    <€ V ^8„  d   QhRS[ /# )r   rd   )r	   )r   r   s   "€r   r   rZ   +  s   ø€ ÷ 5ñ 5¡hñ 5r   c                ó  € \        V R4      '       g   \        R\        V 4       R24      hV P                  pVP                  '       d   VP
                  '       g   R# V P                  pV P                  p\        P                  ! ^VR7      p\        P                  ! WCRR7      pVP                  '       dS   \        P                  ! ^VR7      p\        P                  ! WcR7       VP                  4       pV'       d   \        R	4      hV# )
a¸  
Notifies the join context manager that the calling process has not yet joined.

Then, if ``throw_on_early_termination=True``, checks if uneven inputs have been detected
(i.e. if one process has already joined) and throws an exception if so.

This method should be called from a :class:`Joinable` object before
its per-iteration collective communications. For example, this should
be called at the beginning of the forward pass in
:class:`DistributedDataParallel`.

Only the first :class:`Joinable` object passed into the context
manager performs the collective communications in this method, and
for the others, this method is vacuous.

Arguments:
    joinable (Joinable): the :class:`Joinable` object calling this
        method.

Returns:
    An async work handle for the all-reduce meant to notify the context
    manager that the process has not yet joined if ``joinable`` is the
    first one passed into the context manager; ``None`` otherwise.
r5   zCheck that the z/ constructor calls the ``Joinable`` constructorNrŠ   T)rŒ   Úasync_opr‹   zLDetected at least one rank that exhausted inputs. Throwing across all ranks.)Úhasattrrh   rw   r5   rP   rN   rB   rG   r?   r’   rm   rŽ   rO   r�   r�   r“   )rd   Újoin_configr@   rq   r’   Úworkr�   Úshould_throws   &       r   Únotify_join_contextÚJoin.notify_join_context*  sâ   € ô4 �x ×0Ò0Ü Ø!¤$ x£.Ð!1ð 2+ð +óð ð
 ×+Ñ+ˆà×,×,Ð,°K×4F×4FÐ4FÙà×%Ñ%ˆØ ×3Ñ3ˆô �zŠz˜! FÔ+ˆÜ�Š˜tÀ4ÔHˆà×1×1Ð1ä—K’K ¨&Ô1ˆEÜ�OŠO˜EÕ7Ø Ÿ:™:›<ˆLßÜ"ð1óð ð ˆr   )rp   r`   r_   r^   rl   ro   ra   N)TF)r$   r%   r&   r'   r(   r2   rb   rc   rt   r‡   r�   r‚   rT   rœ   r)   r*   r+   s   @r   r
   r
   h   sX   ø‡ € ñ;÷z"ò "÷$&ð &÷ð ò> ÷30ð 30òj*òGð ÷5ó ö5r   )r   r	   r
   )r~   Úabcr   r   Útypesr   Útypingr   r   r?   Útorch.distributedÚdistributedrm   Ú__all__r   r	   r3   r
   r   r   r   Ú<module>r¤      sM   ðã ß #Ý ß "ã Ý  ò +€÷ñ ô<'ˆsô 'ôT
�*ô 
÷$xó xr   