
    sh,'                     n    S SK r S SKrS SKJrJr  S SKrS SKJr  S SKJ	r	J
r
  S SKJr  S/r " S S5      rg)    N)CallableOptional)register_multi_grad_hook)register_module_forward_hook register_module_forward_pre_hook)tree_flatten
ModTrackerc            
           \ rS rSr% Sr\\   \S'    S rS r	\
S 5       rS r    SS	\\   S
\\   S\\   S\\   4S jjrS rS rS rS rS rS rS rS rSrg)r	      a  
``ModTracker`` is a context manager that tracks the nn.Module hierarchy during execution
so that other system can query which Module is currently being executed (or its backward is being
executed).

You can access the ``parents`` attribute on this context manager to get the set of all the
Modules currently being executed via their fqn (fully qualified name, also used as the key within
the state_dict).
You can access the ``is_bw`` attribute to know if you are currently running in backward or not.

Note that ``parents`` is never empty and always contains the "Global" key. The ``is_bw`` flag
will remain ``True`` after the forward until another Module is executed. If you need it to be
more accurate, please submit an issue requesting this. Adding a map from fqn to the module instance
is possible but not done yet, please submit an issue requesting this if you need it.

Example usage

.. code-block:: python

    mod = torch.nn.Linear(2, 2)

    with ModTracker() as tracker:
        # Access anything during the forward pass
        def my_linear(m1, m2, bias):
            print(f"Current modules: {tracker.parents}")
            return torch.mm(m1, m2.t()) + bias

        torch.nn.functional.linear = my_linear

        mod(torch.rand(2, 2))

parentsc                     S1U l         0 U l        [        R                  " 5       U l        [        R
                  " 5       U l        SU l        / U l        S U l	        S U l
        S U l        S U l        g NGlobalF)r   _active_module_cntweakrefWeakKeyDictionary_known_modulesWeakSet_seen_modules_has_callback_post_bw_callbacks_to_enqueue_user_pre_fw_hook_user_post_fw_hook_user_pre_bw_hook_user_post_bw_hookselfs    x/Users/tiagomarins/Projetos/claudeai/copy_bank/venv/lib/python3.13/site-packages/torch/distributed/_tools/mod_tracker.py__init__ModTracker.__init__9   sc     z"$9@9R9R9T.5oo.?"=?*!%"&!%"&    c                 |  ^  T R                   (       a  g [        T R                  5       H6  n[        R                  R
                  R                  R                  U5        M8     T R                  R                  5         U 4S jn[        R                  R
                  R                  R                  U5        ST l         g )Nc                  $   > S1T l         ST l        g r   )r   r   r   s   r   callback7ModTracker._maybe_set_engine_callback.<locals>.callbackN   s    $:DL!&Dr!   T)	r   reversedr   torchautogradVariable_execution_enginequeue_callbackclear)r   post_bw_callbackr$   s   `  r   _maybe_set_engine_callback%ModTracker._maybe_set_engine_callbackE   s     ()K)K LNN##55DDEUV !M**002	' 	11@@J!r!   c                 D    [         R                  R                  5       S:g  $ )zP
A boolean marking if this is currently running during the backward pass or not
)r'   _C_current_graph_task_idr   s    r   is_bwModTracker.is_bwU   s    
 xx..0B66r!   c                 :    U R                   R                  US5      $ )z_
Return the fqn for the given module if it is known to the ``ModTracker``, otherwise ``None``.
N)r   get)r   mods     r   get_known_fqnModTracker.get_known_fqn\   s     ""&&sD11r!   Npre_fw_hookpost_fw_hookpre_bw_hookpost_bw_hookc                     S nU" XR                   S5      U l         U" X R                  S5      U l        U" X0R                  S5      U l        U" X@R                  S5      U l        g)a  
Registers user-specified hooks to be called before/after the forward/backward pass for each
module tracked by the ``ModTracker``. One or more can be ``None``.
Args:
    pre_fw_hook (Callable, optional): A hook to be called before the forward pass for the
        module. It should have the following signature:
        pre_fw_hook (module, input) -> None
    post_fw_hook (Callable, optional): A hook to be called after the forward pass for the
        module. It should have the following signature:
        post_fw_hook (module, input, output) -> None
    pre_bw_hook (Callable, optional): A multi-grad hook to be called on all the outputs of
        the module that require gradients. It should have the following signature:
        pre_bw_hook (module, grad_output) -> None
    post_bw_hook (Callable, optional): A multi-grad hook to be called on all the inputs of
        the module that require gradients. It should have the following signature:
        post_bw_hook (module, grad_input) -> None
Raises:
    AssertionError: If a new hook is provided when one is already registered.
Note:
    If the module is not alive during the backward pass, the pre_bw_hook and post_bw_hook will
    will receive None as the module argument.
    The module fqn will be present in the ``parents`` attribute when each of the hooks is called.
    Hooks are intended to be used as markers only not to modify the inputs/outputs.
c                 0    U b  Ub  [        SU S35      eU $ )Nz	Only one zq can be registered at a time Clear the existing hook by calling ``clear_user_hooks`` before registering a new one)AssertionError)hook	user_hook	hook_names      r   set_hook0ModTracker.register_user_hooks.<locals>.set_hook   s4    I$9$	{ +l m  Kr!   r;   r<   r=   r>   Nr   r   r   r   )r   r;   r<   r=   r>   rE   s         r   register_user_hooksModTracker.register_user_hooksb   sp    @	 "*//"
 #+11>#
 "*//"
 #+11>#
r!   c                 <    SU l         SU l        SU l        SU l        g)zI
Clears the user specified hooks registered with ``register_user_hooks``
NrG   r   s    r   clear_user_hooksModTracker.clear_user_hooks   s$     "&"&!%"&r!   c                 V   XR                   ;  a"  [        U5      R                  U R                   U'   U R                   U   nXR                  ;  aY  UR	                  5        H*  u  p4U SU 3U R                   U'   U R                  U5        M,     U R                  R                  U5        U$ )N.)r   type__name__r   named_children_get_mod_nameadd)r   r8   mod_namenamesubmods        r   rR   ModTracker._get_mod_name   s    )))'+Cy'9'9D$&&s+((( # 2 2 419
!D6.B##F+""6* !5 ""3'r!   c                     ^ ^^^ UUU U4S jnU$ )Nc                    > T(       a  TR                  5         TTR                  ;   a7  TR                  (       d&  SS jnU[        l        [        R
                  " S5        TTR                  ;  a+  STR                  T'   TR                  R                  T5        OTR                  T==   S-  ss'   TR                  b   T(       a  TR                  T" 5       U 5        g g g )Nc                 2    U SU SUR                    SU  S3$ )N:z: z 
)rP   )msgcategoryfilenamelinenolines        r   custom_formatwarningCModTracker._get_append_fn.<locals>.fn.<locals>.custom_formatwarning   s(    &Zq83D3D2ERuCPPr!   zbThe module hierarchy tracking maybe be messed up. Please file a bug to PyTorch, if it is the case.   N)	r.   r   r4   warningsformatwarningwarnr   rS   r   )argsra   r4   rU   r   w_mods     r   fn%ModTracker._get_append_fn.<locals>.fn   s    //1t||#DJJQ *>&H 4<<'01''-  &''-2-%%1e&&uw5 7<1r!    r   ri   rU   r4   rj   s   ```` r   _get_append_fnModTracker._get_append_fn   s    	6 	6, 	r!   c                     ^ ^^^ UUU U4S jnU$ )Nc                  B  > TR                   b  T(       a  TR                  T" 5       U 5        TTR                  ;   aG  TR                  T==   S-  ss'   TR                  T   S:X  a  TR                  R                  T5        g g TR                  (       d  [        S5      eg )Nrc   r   z?The Module hierarchy tracking is wrong. Report a bug to PyTorch)r   r   r   remover4   RuntimeError)rh   r4   rU   r   ri   s    r   rj   "ModTracker._get_pop_fn.<locals>.fn   s    &&2u''6t||#''-2-**40A5LL''- 6ZZ #U   r!   rl   rm   s   ```` r   _get_pop_fnModTracker._get_pop_fn   s    	 	 	r!   c                 ,   U R                  U5      n[        R                  " U5      nU R                  XCS5      " 5         U R                  b  U R	                  X5        [        U5      u  pVU Vs/ s H9  n[        U[        R                  5      (       d  M$  UR                  (       d  M7  UPM;     nnU R                  (       dO  U(       a  [        XR                  XCS5      5        g U R                  R                  U R                  XCS5      5        g g s  snf )NFT)rR   r   refrn   r   r   
isinstancer'   Tensorrequires_gradr4   r   ru   r   append)	r   r8   inputrU   ri   rh   _atensorss	            r   _fw_pre_hookModTracker._fw_pre_hook   s    !!#&C E/1!!-""3.u%"VdjELL&A1aoo1dVzz(2B2B5PT2UV2299$$U$7	  Ws   .#DD(Dc                    U R                  U5      n[        R                  " U5      nU R                  b  U R                  XU5        U R	                  XTS5      " 5         [        U5      u  pgU Vs/ s H9  n[        U[        R                  5      (       d  M$  UR                  (       d  M7  UPM;     n	nU R                  (       d#  U	(       a  [        XR                  XTS5      SS9  g g g s  snf )NFTany)mode)rR   r   rx   r   ru   r   ry   r'   rz   r{   r4   r   rn   )
r   r8   r}   outputrU   ri   rh   r~   r   r   s
             r   _fw_post_hookModTracker._fw_post_hook   s    !!#&C "".##C7e,.v&"VdjELL&A1aoo1dVzzg$,,U$?e &z Ws   /#C&C&)C&c                 l    [        U R                  5      U l        [        U R                  SS9U l        U $ )NT)always_call)r   r   _fw_pre_handler   r   _fw_post_handler   s    r   	__enter__ModTracker.__enter__   s4    >t?P?PQ;D 
 r!   c                 l    U R                   R                  5         U R                  R                  5         g rd   )r   rr   r   )r   rh   s     r   __exit__ModTracker.__exit__   s&    ""$##%r!   )r   r   r   r   r   r   r   r   r   r   r   r   )NNNN)rP   
__module____qualname____firstlineno____doc__setstr__annotations__r   r.   propertyr4   r9   r   r   rH   rK   rR   rn   ru   r   r   r   r   __static_attributes__rl   r!   r   r	   r	      s    B X
'"  7 72 +/+/*.+/3
h'3
 x(3
 h'	3

 x(3
j'	2" &r!   )re   r   typingr   r   r'   torch.autograd.graphr   torch.nn.modules.moduler   r   torch.utils._pytreer   __all__r	   rl   r!   r   <module>r      s3      %  9 - .i& i&r!   