o
    ߗid%                     @   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
mZmZ d dlZd dl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dee fddZdejde	eeef  fddZdS )    N)OrderedDictwraps)CallableDictListOptionalSequenceTypeUnion)_State)_get_root_modules__composable_api_state_keyc                 C   s   |  dt t  S )N_)struuiduuid4)string r   d/home/ubuntu/transcripts/venv/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   	state_clsc                    s   t   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()
    c                    s\   t  dttjttj f dttj f fdd}dtjdtt f fdd}||_|S )Nmodulereturnc                    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   r   r    orig_fqn_setnew_fqn_set	orig_onlynew_onlyr   r   r   	check_fqn   s(   z;contract.<locals>.inner.<locals>.wrapper.<locals>.check_fqnzChecking parameters: zChecking buffers: zChecking modules: )
isinstancennModuler   listr   r   __dict__
setdefault	STATE_KEYdictAssertionErrorREGISTRY_KEYr   appendnamed_parametersnamed_buffersnamed_modulesr"   r   r   zipkeys)r   argskwargs
inp_modulemodulesstate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_modulesr(   orig_named_paramsnew_named_paramsorig_named_buffersnew_named_buffersorig_named_modulesnew_named_modules)funcr   r   r   wrapperI   s   







	z(contract.<locals>.inner.<locals>.wrapperc                    s   | j ti  S )N)r-   r.   r/   getr   rS   r   r   	get_state   s   z*contract.<locals>.inner.<locals>.get_state)r   r   r*   r+   r	   r   r   r=   )rS   rT   rX   r   rW   r   innerG   s    zcontract.<locals>.innerr   )r   rZ   r   rY   r   contract   s   * r[   r   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)getattrr2   rV   r   r   r   _get_registry   s   r]   )r   )r   collectionsr   	functoolsr   typingr   r   r   r   r	   r
   r   torchtorch.nnr*   #torch.distributed._composable_stater   torch.distributed.utilsr   r   r/   r2   r   r[   r+   r   r]   r   r   r   r   <module>   s   $
 $>