
    Vh(              
          d dl Z d dlmZ d dlmZ d dlmZmZmZm	Z	 d dl
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  edd	
      Z ed      ZddZ e       Z e       Z G d d      Z eddd	      Z edej8                  eej8                           Z G d de	eeeef         Zefde e   deeeeef   ef   geeeef   eef   f   fdZ!dej8                  dee"e#ef      fdZ$y)    N)OrderedDict)wraps)CallableGenericOptionalProtocol)Concatenate	ParamSpecTypeVar)_State)_get_root_modules_TT)	covariant_Pc                 F    |  dt        t        j                                S )N_)struuiduuid4)strings    V/home/dcms/DCMS/lib/python3.12/site-packages/torch/distributed/_composable/contract.pygenerate_state_keyr      s    XQs4::<()**    c                       e Zd Zy)RegistryItemN)__name__
__module____qualname__ r   r   r   r      s    r   r   _TStater   )boundr   _Mc                   l    e Zd Zdej                  dej
                  defdZdej                  de
fdZy)_ContractFnargskwargsreturnc                      y Nr   )selfr%   r&   s      r   __call__z_ContractFn.__call__'       r   modulec                      y r)   r   )r*   r-   s     r   statez_ContractFn.state)   r,   r   N)r   r   r   r   r%   r&   r   r+   nnModuler    r/   r   r   r   r$   r$   &   s-    FbggFFrF6BII6'6r   r$   	state_clsr'   c                      t               dt        t        t        t        f   t        f   dt
        t        t        t        f   t        t        f   f fd       }|S )a%  
    Decorate a function as a composable distributed API, where the first
    argument of the function must be an :class:`nn.Module` instance or sequence
    of :class:`nn.Module` instances.

    The decorator verifies that the decorated function does not modify
    fully-qualified names (FQNs) for parameters, buffers, or modules. The
    decorated function can return different module instances than the input
    modules; the FQN invariant will be enforced following the input order.

    When a function ``func`` is decorated by ``@contract()``, a
    ``.state(module: nn.Module)`` method will be installed to the decorated
    function. Then you can retrieve and modify the state on a module by calling
    ``func.state(module)``.

    Example::
        >>> # xdoctest: +SKIP
        >>> import torch.nn as nn
        >>>
        >>> class MyModel(nn.Module):
        >>>     def __init__(self) -> None:
        >>>         super().__init__()
        >>>         self.l1 = nn.Linear(10, 10)
        >>>         self.l2 = nn.Linear(10, 10)
        >>>
        >>>     def forward(self, x):
        >>>         return self.l2(self.l1(x))
        >>>
        >>> @contract()
        >>> def my_feature(module: nn.Module) -> nn.Module:
        >>>     my_feature.state(module).some_state = "any value"
        >>>     return module
        >>>
        >>> model = MyModel()
        >>> my_feature(model.l1)
        >>> assert my_feature.state(model.l1).some_state == "any value"
        >>> my_feature(model.l2)
        >>> model(torch.randn(2, 10)).sum().backward()
    funcr'   c           	           t               dt        dt        j                  dt        j                  dt        f fd       }dt
        j                  dt        f fd}||_        |S )Nr-   r%   r&   r'   c                    | }t        | t        j                        r| g}nt        t	        |             }        }t               }g }g }g }	|D ]f  } t               }
t               }| j                  j                  t        |
      }t        |t              st        d|       | j                  j                  t        |      }t        |t              st        d|       |v sj                  |v rt        dj                   d|        |j                  |       |j                  j                  |       |j                  t        | j                                      |j                  t        | j!                                      |	j                  t        | j#                                      i  |g|i |}||}t        |t        j                        r|g}nt        t	        |            }g }g }g }|D ]z  } |j                  t        | j                                      |j                  t        | j!                                      |j                  t        | j#                                      | t%        |	      }t%        |      }||k7  rt        j                   d| d| d      dt        t&           d	t        t&           d
t&        fd}t)        ||      D ]=  \  }} |t	        |j+                               t	        |j+                               d       ? t)        ||      D ]=  \  }} |t	        |j+                               t	        |j+                               d       ? t)        |	|      D ]=  \  }} |t	        |j+                               t	        |j+                               d       ? |S )Nz-Distributed composable API states corrupted: z/Distributed composable API registry corrupted: zOEach distinct composable distributed API can only be applied to a module once. z3 has already been applied to the following module:
zB should return the same number of modules as input modulesInputs: z modules
Outputs: z modules	orig_fqnsnew_fqns	check_keyc                     | |k(  ry t        |       t        |      }}||z
  }||z
  }t        |      st        |      rt        | d| d|       t        | d| d|       )NzVComposable distributed API implementations cannot modify FQNs.
FQNs only in original: z
FQNs only in new: z[Composable distributed API implementations cannot modify the order of FQNs.
Original FQNs: z
New FQNs: )setlenRuntimeError)r7   r8   r9   orig_fqn_setnew_fqn_set	orig_onlynew_onlys          r   	check_fqnz;contract.<locals>.inner.<locals>.wrapper.<locals>.check_fqn   s    (,/	NCMk(;6	&5y>S]&$+22; =--5J8  '$+**3 5%%-J	0 r   zChecking parameters: zChecking buffers: zChecking modules: )
isinstancer0   r1   r   listr   r   __dict__
setdefault	STATE_KEYdictAssertionErrorREGISTRY_KEYr   appendnamed_parametersnamed_buffersnamed_modulesr<   r   zipkeys)r-   r%   r&   
inp_modulemodulesr/   registry_itemall_orig_named_paramsall_orig_named_buffersall_orig_named_modulesdefault_all_statedefault_registry	all_stateregistryupdatedupdated_modulesall_new_named_paramsall_new_named_buffersall_new_named_modulesnum_orig_modulesnum_new_modulesrB   orig_named_paramsnew_named_paramsorig_named_buffersnew_named_buffersorig_named_modulesnew_named_modulesr4   r2   s                               r   wrapperz(contract.<locals>.inner.<locals>.wrapper_   s     J&")),!(
 ,DL9KE(NM
 DF!DF"AC"! S<GM!<GM 4:OO4N4N05	 ")T2(G	{S  5;OO4N4N "25 "(D1(I(T  9$(A(((, 7..4X7 
 $$T51##DMM=A%,,[9P9P9R-ST&--k&:N:N:P.QR&--k&:N:N:P.QR9S< :777G$'299-#*)"3D4D"EBD CE!@B!) R$++K8O8O8Q,RS%,,[9M9M9O-PQ%,,[9M9M9O-PQR
  ##9:!"78O?2$}}o &/0 1  /0: T#Y $s) PS . 8;%';8 3!#3 *//12)..01+ :=&(=: 5"$5 +0023*//12( :=&(=: 5"$5 +0023*//12( Nr   c                 b    | j                   j                  t        i       j                        S r)   )rE   rF   rG   get)r-   r4   s    r   	get_statez*contract.<locals>.inner.<locals>.get_state   s+    ??-- c$ir   )	r   r"   r   r%   r&   r0   r1   r   r/   )r4   rh   rk   r2   s   `  r   innerzcontract.<locals>.inner[   ss     
tC	C	77C	 iiC	 	C	 
C	J	bii 	F 	 "r   )r   r   r	   r"   r   r$   r    )r2   rl   s   ` r   contractrm   ,   sa    ^ 9Q{2r6*B./Q	[R("g5	6Q Qf Lr   r-   c                 $    t        | t        d      S )z
    Get an ``OrderedDict`` of composable APIs that have been applied to the
    ``module``, indexed by the API name. If no API has been applied, then this
    returns ``None``.
    N)getattrrJ   )r-   s    r   _get_registryrp      s     6<..r   )__composable_api_state_key)%r   collectionsr   	functoolsr   typingr   r   r   r   typing_extensionsr	   r
   r   torchtorch.nnr0   #torch.distributed._composable_stater   torch.distributed.utilsr   r   r   r   rG   rJ   r   r    r1   rD   r"   r$   typerm   rH   r   rp   r   r   r   <module>r{      s$    #  8 8 = =   6 5 TT"t_+  	!#	 	 )8t
<T299d299o.7(GBGO4 7  &CG}Ck"b&!2%&'BF#R013CL/")) /c<6G1H(I /r   