a
    h(                     @   sT  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e e eeeeef ef geeeef eef f dddZ!ejee"e#ef  d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   T/var/www/auris/lib/python3.9/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                   @   s4   e Zd ZejejedddZej	e
dddZdS )_ContractFn)argskwargsreturnc                 O   s   d S Nr   )selfr!   r"   r   r   r   __call__'       z_ContractFn.__call__moduler#   c                 C   s   d S 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                    sB   t  ttttf tf ttttf ttf d 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                    sF   t  ttjtjtd fdd}tjtd fdd}||_|S )N)r)   r!   r"   r#   c                    s  | }t | tjr| g}ntt| } }t }g }g }g }	|D ]} t }
t }| jt	|
}t |t
svtd| | jt|}t |t
std|  |v s j|v rtd j d|  | | | j| |t|   |t|   |	t|   q@ |g|R i |}|d u r:|}t |tjrP|g}ntt|}g }g }g }|D ]<} |t|   |t|   |t|   qlt|	}t|}||krt j d| d| dtt tt tdd	d
}t||D ]&\}}|t| t| d qt||D ]&\}}|t| t| d q6t|	|D ]&\}}|t| t| d qh|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   st   | |krd S t | t | }}|| }|| }t|s>t|rXt| d| d| nt| d| d| d S )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>.wrapperr(   c                    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>   s8   
 G