U
    ©Ê¹j›  ã                   @   s¬   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	m
Z
 d dlmZ d dlmZ ddd„Zeƒ Zeƒ ZG d	d
„ d
ƒZefe
e dœdd„Zejeeef dœdd„ZdS )é    N)ÚOrderedDict©Úwraps)ÚCallableÚDictÚListÚOptionalÚType)Ú_StateÚ__composable_api_state_keyc                 C   s   | › dt t ¡ ƒ› �S )NÚ_)ÚstrÚuuidÚuuid4)Ústring© r   úe/var/www/html/bwave/python/venv/lib/python3.8/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   ©Ú	state_clsc                    s   t ˆ ƒ‡ fdd„ƒ}|S )aJ  
    Decorate a function as a composable distributed API, where the first
    argument of the function must be an :class:`nn.Module` instance. The
    decorator verifies that the wrapped function does not modify parameter,
    buffer or sub-module fully-qualified names (FQN).

    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):
        >>>         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()
    c                    sJ   t ˆ ƒtjttj dœ‡ ‡fdd„ƒ}tjtt dœ‡ fdd„}||_|S )N©ÚmoduleÚreturnc                    s˜  t ƒ }| j t|¡}t|tƒs&tdƒ‚t ƒ }| j t|¡}t|tƒsLtdƒ‚ˆ |kr^ˆ j|ksttdˆ j› d| › �ƒ‚| ˆ ˆƒ ¡ | ˆ jt	ƒ ¡ t |  
¡ ƒ}t | jdd�ƒ}t | jdd�ƒ}	ˆ | f|ž|Ž}
|
d krÚ| }
t |
 
¡ ƒ}t |
jdd�ƒ}t |
jdd�ƒ}t|
tjƒ�s&tdt|
ƒ› �ƒ‚tt tt tdœd	d
„}|t| ¡ ƒt| ¡ ƒdƒ |t| ¡ ƒt| ¡ ƒdƒ |t|	 ¡ ƒt| ¡ ƒdƒ |
S )Nz+Distributed composable API states corruptedz-Distributed composable API registry corruptedzOEach distinct composable distributed API can only be applied to a module once. z3 has already been applied to the following module.
F)Zremove_duplicatezPOutput of composable distributed APIs must be either None or nn.Module, but got )Ú	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.
Only in original FQNs: z,
Only in new FQNs: z[Composable distributed API implementations cannot modify the order of FQNs.
Original FQNs: z
New FQNs: )ÚsetÚlenÚRuntimeError)r   r   r   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Check parameters, zCheck buffer, zCheck modules, )r   Ú__dict__Ú
setdefaultÚ	STATE_KEYÚ
isinstanceÚdictÚAssertionErrorÚREGISTRY_KEYr   r   Znamed_parametersZnamed_buffersZnamed_modulesÚnnÚModuleÚtyper   r   ÚlistÚkeys)r   ÚargsÚkwargsZdefault_all_stateZ	all_stateÚdefault_registryÚregistryZorig_named_paramsZorig_named_buffersZorig_named_modulesÚupdatedZnew_named_paramsZnew_named_buffersZnew_named_modulesr#   )Úfuncr   r   r   ÚwrapperB   s€     ÿ ÿþ ÿ ÿþÿ
ÿ
ÿ
ÿ
ÿÿ

ý

ý

ýz(contract.<locals>.inner.<locals>.wrapperc                    s   | j  ti ¡ ˆ ¡S )N)r$   r%   r&   Úget)r   ©r5   r   r   Ú	get_state­   s    þüz*contract.<locals>.inner.<locals>.get_state)r   r+   r,   r   r
   Ústate)r5   r6   r9   r   r8   r   Úinner@   s
     jzcontract.<locals>.innerr   )r   r;   r   r   r   Úcontract   s    &xr<   r   c                 C   s2   t | tdƒ}|dkr*tƒ }t| t|ƒ |S |S dS )zz
    Get an ``OrderedDict`` of composable APIs that have been applied to the
    ``module``, indexed by the API name.
    N)Úgetattrr*   r   Úsetattr)r   r3   r2   r   r   r   Ú_get_registry¼   s    r?   )r   )r   Úcollectionsr   Ú	functoolsr   Útypingr   r   r   r   r	   Ztorch.nnr+   Z#torch.distributed._composable_stater
   r   r&   r*   r   r<   r,   r   r?   r   r   r   r   Ú<module>   s   
 #