o
    Zh(                  
   @   sX  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	d
ZedZdddZe Ze ZG dd dZeddd	dZedejeej ZG d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dZ!dejdee"e#ef  fddZ$dS )    N)OrderedDict)wraps)CallableGenericOptionalProtocol)Concatenate	ParamSpecTypeVar)_State)_get_root_modules_TT)	covariant_P__composable_api_state_keyc                 C   s   |  dt t  S )N_)struuiduuid4)string r   U/var/www/auris/lib/python3.10/site-packages/torch/distributed/_composable/contract.pygenerate_state_key   s   r   c                   @   s   e Zd ZdS )RegistryItemN)__name__
__module____qualname__r   r   r   r   r      s    r   _TStater   )boundr   _Mc                   @   s:   e Zd ZdejdejdefddZdej	de
fddZd	S )
_ContractFnargskwargsreturnc                 O      d S Nr   )selfr!   r"   r   r   r   __call__'       z_ContractFn.__call__modulec                 C   r$   r%   r   )r&   r)   r   r   r   state)   r(   z_ContractFn.stateN)r   r   r   r   r!   r"   r   r'   nnModuler   r*   r   r   r   r   r    &   s    r    	state_clsr#   c                    sD   t  dttttf tf dttttf ttf f fd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              	      sN   t  dtdtjdtjdtf fdd}dtjdtf fdd}||_|S )	Nr)   r!   r"   r#   c                    s  | }t | tjr| g}ntt| } }t }g }g }g }	|D ]j} t }
t }| jt	|
}t |t
s;td| | jt|}t |t
sNtd|  |v sW j|v rbtd j d|  | | | j| |t|   |t|   |	t|   q  |g|R i |}|d u r|}t |tjr|g}ntt|}g }g }g }|D ]} |t|   |t|   |t|   qt|	}t|}||krt j d| d| ddtt d	tt d
tfdd}t||D ]\}}|t| t| d q t||D ]\}}|t| t| d qt|	|D ]\}}|t| t| d q2|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                 S   sn   | |krd S t | t |}}|| }|| }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)r/   r0   r1   Zorig_fqn_setZnew_fqn_setZ	orig_onlyZnew_onlyr   r   r   	check_fqn   s(   z;contract.<locals>.inner.<locals>.wrapper.<locals>.check_fqnzChecking parameters: zChecking buffers: zChecking modules: )
isinstancer+   r,   r   listr   r   __dict__
setdefault	STATE_KEYdictAssertionErrorREGISTRY_KEYr   appendZnamed_parametersZnamed_buffersZnamed_modulesr3   r   zipkeys)r)   r!   r"   Z
inp_modulemodulesr*   Zregistry_itemZall_orig_named_paramsZall_orig_named_buffersZall_orig_named_modulesZdefault_all_stateZdefault_registryZ	all_stateregistryupdatedZupdated_modulesZall_new_named_paramsZall_new_named_buffersZall_new_named_modulesZnum_orig_modulesZnum_new_modulesr5   Zorig_named_paramsZnew_named_paramsZorig_named_buffersZnew_named_buffersZorig_named_modulesZnew_named_modules)r.   r-   r   r   wrapper_   s   







	z(contract.<locals>.inner.<locals>.wrapperc                    s   | j ti  S r%   )r8   r9   r:   getr)   r.   r   r   	get_state   s   z*contract.<locals>.inner.<locals>.get_state)	r   r   r   r!   r"   r+   r,   r   r*   )r.   rD   rH   r-   rG   r   inner[   s    zcontract.<locals>.inner)r   r   r   r   r   r    r   )r-   rJ   r   rI   r   contract,   s   / rK   r)   c                 C   s   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)getattrr=   rF   r   r   r   _get_registry   s   rM   )r   )%r   collectionsr   	functoolsr   typingr   r   r   r   Ztyping_extensionsr   r	   r
   ZtorchZtorch.nnr+   Z#torch.distributed._composable_stater   Ztorch.distributed.utilsr   r   r   r   r:   r=   r   r   r,   r7   r   r    typerK   r;   r   rM   r   r   r   r   <module>   s<   

 $G