a
    d%>                     @   s  d dl Z d dlZd dlmZmZ d dlmZmZmZm	Z	m
Z
mZmZmZmZ d dlmZ d dlmZ g dZedddZG d	d
 d
eZejeeeeej  edddZG dd deZejeeeedddZejeeeeej  edddZejeedddZejeeedddZedddfejeeeeeeej   eeeej   edddZej ej!he_"ej#he_$e j%eee
d  d!d"d#Z&ejeejd$d%d&Z'ejeejd'd(d)Z(d0ejeeeej eej) eeeejef d+d,d-Z*G d.d/ d/Z+dS )1    N)ABCabstractmethod)	AnyCallablecastDict	GeneratorOptionalSetTupleType)
_BatchNorm)always_wrap_policylambda_auto_wrap_policytransformer_auto_wrap_policysize_based_auto_wrap_policyenable_wrapwrapModuleWrapPolicyreturnc                  O   s   dS )z
    A simple recursive wrap policy that always returns ``True``. This means
    that every submodule is wrapped by the wrapper class in
    :func:`_recursive_wrap`.
    T )argskwargsr   r   d/var/www/html/stable-diffusion-webui/venv/lib/python3.9/site-packages/torch/distributed/fsdp/wrap.pyr      s    r   c                   @   s.   e Zd ZdZdd ZeeedddZdS )_FSDPPolicyzv
    This defines an abstract base class that represents an FSDP policy for
    constructing ``FlatParameter`` s.
    c                 C   s   d S Nr   selfr   r   r   __init__*   s    z_FSDPPolicy.__init__r   c                 C   s   d S r   r   r   r   r   r   policy-   s    z_FSDPPolicy.policyN)	__name__
__module____qualname____doc__r   propertyr   r   r    r   r   r   r   r   "   s
   r   )modulerecursenonwrapped_numelmodule_classesr   c                 C   s   |rdS t | t|S )a   
    This auto wrap policy wraps every module that is an instance of any type in
    ``module_classes`` as its own FSDP instance. The root module given by
    ``module`` is always wrapped as an FSDP instance regardless. Since the
    wrapping proceeds bottom up, each FSDP instance manages the parameters in
    its subtree excluding any already managed by a child FSDP instance.

    Args:
        module (nn.Module): Current module being considered.
        recurse (bool): If ``False``, then this function must decide whether
            ``module`` should be wrapped as an FSDP instance or not. If
            ``True``, then the function is still recursing down the module
            tree as a part of the DFS.
        nonwrapped_numel (int): Parameter numel not yet wrapped.
        module_classes (Set[Type[nn.Module]]): Set of module classes that are
            wrapped as FSDP instances.

    Returns:
        ``True`` if ``recurse=True``, and whether ``module`` should be wrapped
        if ``recurse=False``.
    T)
isinstancetuple)r&   r'   r(   r)   r   r   r   _module_wrap_policy3   s    r,   c                       sJ   e Zd ZdZeeej  dddZe	dd Z
ed fdd	Z  ZS )
r   z5This is a wrapper around :func:`_module_wrap_policy`.r)   c                 C   s   t jt|d| _t|| _d S )Nr-   )	functoolspartialr,   _policystr_module_classes_str)r   r)   r   r   r   r   V   s
    zModuleWrapPolicy.__init__c                 C   s   | j S r   )r0   r   r   r   r   r    ]   s    zModuleWrapPolicy.policyr   c                    s   t   d| j d S )N())super__repr__r2   r   	__class__r   r   r6   a   s    zModuleWrapPolicy.__repr__)r!   r"   r#   r$   r
   r   nnModuler   r%   r    r1   r6   __classcell__r   r   r7   r   r   S   s
   
r   )r&   r'   r(   	lambda_fnr   c                 C   s   |rdS || S )aU  
    A convenient auto wrap policy to wrap submodules based on an arbitrary user
    function. If `lambda_fn(submodule) == True``, the submodule will be wrapped as
    a `wrapper_cls` unit.

    Return if a module should be wrapped during auto wrapping.

    The first three parameters are required by :func:`_recursive_wrap`.

    Args:
        module (nn.Module): Current module being considered.
        recurse (bool): If ``False``, then this function must decide whether
            ``module`` should be wrapped as an FSDP instance or not. If
            ``True``, then the function is still recursing down the module
            tree as a part of the DFS.
        nonwrapped_numel (int): Parameter numel not yet wrapped.

        lambda_fn (Callable[[nn.Module], bool]): If this returns ``True``, then
            this module will be wrapped.
    Tr   )r&   r'   r(   r<   r   r   r   r   e   s    r   )r&   r'   r(   transformer_layer_clsr   c                 C   s   t | |||S )a-  
    See :func:`_module_wrap_policy`, where ``transformer_layer_cls`` is the
    same as ``module_classes``. Note that shared parameters must be wrapped in
    the same FSDP instance, so this auto wrap policy can help wrap shared
    embeddings into the same FSDP instance for transformer models.
    )r,   )r&   r'   r(   r=   r   r   r   r      s    r   )r&   r'   r   c                 O   s   |rdS t | tS dS )zQ
    A policy that wraps ``BatchNorm`` instances in their own FSDP instance.
    TN)r*   r   )r&   r'   r   r   r   r   r   _wrap_batchnorm_individually   s    	r>   )r&   r'   r(   r   c                    s   t  fdd|D S )zv
    A policy that wraps ``module`` if any policy in the passed in iterable of
    ``policies`` returns ``True``.
    c                 3   s   | ]}| V  qd S r   r   ).0r    r&   r(   r'   r   r   	<genexpr>       z_or_policy.<locals>.<genexpr>)any)r&   r'   r(   Zpoliciesr   r@   r   
_or_policy   s    
rD   g    חA)r&   r'   r(   min_num_paramsforce_leaf_modulesexclude_wrap_modulesr   c                 C   s`   |du rt jn|}|du r t jn|}|}||k}|rH|oFt| t| S |oZt| t| S dS )a  
    A size-based auto wrap policy.

    Args:
        module (nn.Module): Current module being considered.
        recurse (bool): If ``False``, then this function must decide whether
            ``module`` should be wrapped as an FSDP instance or not. If
            ``True``, then the function is still recursing down the module
            tree as a part of the DFS.
        nonwrapped_numel (int): Parameter numel not yet wrapped.

        min_num_params (int): Customizable policy input that controls the size
            threshold over which a module is ready to be wrapped. This is in
            units of numel.
        force_leaf_modules (Set[Type[nn.Module]]): Set of module types to keep
            as leaves, i.e. their children will never be wrapped.
        exclude_wrap_modules (Set[Type[nn.Module]]): Set of module types to be
            excluded in wrapping.

    Returns:
        Whether ``module`` should be wrapped.
    N)r   FORCE_LEAF_MODULESEXCLUDE_WRAP_MODULESr*   r+   )r&   r'   r(   rE   rF   rG   Zmin_nonwrapped_numelZis_larger   r   r   r      s    !r   )NNN)wrapper_clswrapper_kwargsr   c                 k   sH   i d| i|}t f i | dV  W d   n1 s:0    Y  dS )a  
    Context manager to wrap modules using a wrapper.

    Useful for when you'd like to apply the same configuration arguments to all
    child modules that you wrap. A particularly important use case is wrapping
    large layers so that they get sharded (in-place) during initialization, to
    avoid running out of system memory. Large layers can indicate that they
    should be sharded via the ``wrap`` annotation and this context manager can
    provide the exact configuration for these nested instances.

    Usage::

        with enable_wrap(wrapper_cls, **params):
            # Wraps layer in FSDP by default if within context
            self.l1 = wrap(torch.nn.Linear(5, 5))

    Args:
        wrapper_cls:
            Class that `wrap` annotation will `wrap` modules with, such as
            `FullyShardedDataParallel`.
        **wrapper_kwargs:
            Configuration settings that will be passed to all ``wrap``
            instances inside the context
    rJ   N)_ConfigAutoWrap)rJ   rK   r   r   r   r   r      s    r   )r&   wrap_overridesr   c                 K   s:   t jr6t jdusJ i t j|}t| t jfi |S | S )a  
    Annotate that a module should be wrapped. Annotated modules will only be
    wrapped if inside of an :func:`enable_wrap` context manager. This allows
    a module to be initialized both with and without a wrapper without code
    change.

    The class that this function wraps the passed in ``nn.Module`` with is the
    passed in ``wrapper_cls`` argument into ``enable_wrap``. Both
    ``enable_wrap`` and ``wrap`` can take in kwargs specifying how to construct
    the ``wrapper_cls`` instance. In the case of duplicate kwargs in
    ``enable_wrap`` and ``wrap``, the argument passed into ``wrap`` will be
    respected.

    Usage::

        with enable_wrap(wrapper_cls=FSDP, **fsdp_config):
            # Wraps layer in FSDP by default if within context
            self.l1 = wrap(torch.nn.Linear(5, 5))

    Args:
        module (nn.Module): module to wrap (if in :func:`enable_wrap` context)
        **wrap_overrides: configuration overrides that will take priority over
            the values provided by the :func:`enable_wrap` context
    N)rL   in_autowrap_contextrJ   r   _wrap)r&   rM   r   r   r   r     s    r   )r&   rJ   r   c                 K   sD   |d usJ t | dr4i || j}|| fi |S || fi |S )N_wrap_overrides)hasattrrP   )r&   rJ   r   Z	overridesr   r   r   rO   3  s
    
rO   F)r&   auto_wrap_policyrJ   ignored_modulesignored_paramsonly_wrap_childrenr   r   c              	      s4  |dusJ d|dus J d|   D ]>\}}||v r:q(zt|tt|rPJ W q( tyd   Y q(0 q(t fdd|  D }	|dusJ || d|	dr,d}
|  D ]D\}}||v rqtf |||| d	|\}}t	| || |
|7 }
q|	|
 }|s$|| d
|dr$t
| |fi ||	fS | |
fS | dfS )a  
    Wraps submodules of ``module`` for which ``auto_wrap_policy`` returns
    ``True`` with ``wrapper_cls``.

    Args:
        module (nn.Module): Module to recursively wrap.
        auto_wrap_policy (Callable): A callable representing a policy that
            determines which modules to recursively wrap with ``wrapper_cls``.
        ignored_modules (Set[torch.nn.Module]): Modules to ignore when
            wrapping.
        ignored_params (Set[torch.nn.Parameter]): Parameters to ignore when
            wrapping; these should be the parameters contained in the modules
            in ``ignored_modules``.
    Returns:
        (nn.Module, int):
            ``module`` after wrapping and the numel recursively wrapped.
    NzMust specify auto_wrap_policy.zMust specify wrapper_clsc                 3   s   | ]}| vr|  V  qd S r   )Znumel)r?   prT   r   r   rA   g  s   z"_recursive_wrap.<locals>.<genexpr>T)r&   r'   r(   r   )r&   rR   rJ   rS   rT   F)Znamed_modulesr*   r   type	TypeErrorsum
parametersZnamed_children_recursive_wrapsetattrrO   )r&   rR   rJ   rS   rT   rU   r   _childr(   Ztotal_wrapped_numelnameZwrapped_childZnum_wrapped_params	remainderr   rW   r   r\   @  sH    

r\   c                   @   s   e Zd ZU dZdZeed< dZee	 ed< i Z
eeef ed< eeef ddd	Zeedd
ddZeddddZddddZeeeddddZdS )rL   z
    Helper class to wrap modules based on default config args via a context manager.
    See :func:`enable_wrap` for more information.
    FrN   NrJ   r   r   c                 K   s
   || _ d S r   rb   )r   r   r   r   r   r     s    z_ConfigAutoWrap.__init__)r   r   c                 C   sH   t jrtddt _d|  v s(J dtt| d t _| d= | t _d S )Nz]You are already within an autowrap context and we currently do not supported nested autowrap.TrJ   z9Expected to pass in wrapper_cls arg into _ConfigAutoWrap.)rL   rN   NotImplementedErrorkeysr   r   rJ   r   rb   r   r   r   enable_autowrap_context  s    
z'_ConfigAutoWrap.enable_autowrap_contextr   c                   C   s   dt _d t _i t _d S )NF)rL   rN   rJ   r   r   r   r   r   disable_autowrap_context  s    z(_ConfigAutoWrap.disable_autowrap_contextc                 C   s   |  | j d S r   )re   r   r   r   r   r   	__enter__  s    z_ConfigAutoWrap.__enter__)exc_typeexc_valexc_tbr   c                 C   s   |    d S r   )rf   )r   rh   ri   rj   r   r   r   __exit__  s    z_ConfigAutoWrap.__exit__)r!   r"   r#   r$   rN   bool__annotations__rJ   r	   r   r   r   r1   r   r   staticmethodre   rf   rg   rk   r   r   r   r   rL     s   
rL   )F),
contextlibr.   abcr   r   typingr   r   r   r   r   r	   r
   r   r   Ztorch.nnr9   Ztorch.nn.modules.batchnormr   __all__rl   r   r   r:   intr,   r   r   r   r>   rD   r   Z
ModuleListZ
ModuleDictrI   ZMultiheadAttentionrH   contextmanagerr   r   rO   	Parameterr\   rL   r   r   r   r   <module>   s   ,	 
7
#% J