a
    d#                     @   sh   d dl Z d dlmZ d dlZd dlZd dlmZ g dZG dd dZdd Z	d	d
 Z
G dd dZdS )    N)OrderedDict)Any)RemovableHandleunserializable_hookwarn_if_has_hooksBackwardHookc                   @   s   e Zd ZU dZeed< dZeed< ddeedddd	Zdd
ddZ	dd Z
dd
ddZd d
ddZeeeddddZdS )r   a&  
    A handle which provides the capability to remove a hook.

    Args:
        hooks_dict (dict): A dictionary of hooks, indexed by hook ``id``.
        extra_dict (dict): An additional dictionary whose keys will be deleted
            when the same keys are removed from ``hooks_dict``.
    idr   next_idN)
extra_dict)
hooks_dictr
   returnc                C   s>   t || _tj| _t jd7  _|d ur4t |nd | _d S )N   )weakrefrefhooks_dict_refr   r	   r   extra_dict_refselfr   r
    r   Z/var/www/html/stable-diffusion-webui/venv/lib/python3.9/site-packages/torch/utils/hooks.py__init__   s    zRemovableHandle.__init__)r   c                 C   sR   |   }|d ur"| j|v r"|| j= | jd urN|  }|d urN| j|v rN|| j= d S N)r   r   r   r   r   r   r   remove!   s    
zRemovableHandle.removec                 C   s,   | j d u r|  | jfS |  | j|   fS r   )r   r   r   r   r   r   r   __getstate__+   s    zRemovableHandle.__getstate__c                 C   s   |d d u rt t | _nt |d | _|d | _ttj| jd t_t|dk rZd nt |d d u rpt n|d | _	d S )Nr   r         )
r   r   r   r   r   maxr   r	   lenr   )r   stater   r   r   __setstate__2   s    

zRemovableHandle.__setstate__c                 C   s   | S r   r   r   r   r   r   	__enter__A   s    zRemovableHandle.__enter__)typevaluetbr   c                 C   s   |    d S r   )r   )r   r"   r#   r$   r   r   r   __exit__D   s    zRemovableHandle.__exit__)__name__
__module____qualname____doc__int__annotations__r	   r   r   r   r   r    r!   r%   r   r   r   r   r   	   s   
	
r   c                 C   s
   d| _ | S )z
    Decorator which marks a function as an unserializable hook.
    This suppresses warnings that would otherwise arise if you attempt
    to serialize a tensor that has a hook.
    T)__torch_unserializable__)fr   r   r   r   H   s    r   c                 C   s>   | j r:| j D ],}| j | }t|dstdt| qd S )Nr,   zbackward hook {} on tensor will not be serialized.  If this is expected, you can decorate the function with @torch.utils.hooks.unserializable_hook to suppress this warning)Z_backward_hookshasattrwarningswarnformatrepr)Ztensorkhookr   r   r   r   R   s    


r   c                   @   sH   e Zd ZdZdd Zdd Zdd Zdd	 Zd
d Zdd Z	dd Z
dS )r   a  
    A wrapper class to implement nn.Module backward hooks.
    It handles:
      - Ignoring non-Tensor inputs and replacing them by None before calling the user hook
      - Generating the proper Node to capture a set of Tensor's gradients
      - Linking the gradients captures for the outputs with the gradients captured for the input
      - Calling the user hook once both output and input gradients are available
    c                 C   s4   || _ || _|| _d | _d| _d | _d| _d | _d S )N)
user_hooksuser_pre_hooksmodulegrad_outputs	n_outputsoutput_tensors_indexn_inputsinput_tensors_index)r   r8   r6   r7   r   r   r   r   f   s    zBackwardHook.__init__c                 C   s.   d g| }t ||D ]\}}|||< qt|S r   )ziptuple)r   indicesvaluessizeresidxvalr   r   r   _pack_with_noneq   s    

zBackwardHook._pack_with_nonec                 C   s$   g }|D ]}| ||  qt|S r   )appendr?   )r   r@   rA   rC   rD   r   r   r   _unpack_nonex   s    zBackwardHook._unpack_nonec                    s    fdd}| | d S )Nc                    s    j d u rd S   j|  j} jD ]J}| j| j }|d u rDq&t|t|krltdt|t||}q&d  _  	 j|S )NzOBackward hook returned an invalid number of grad_input, got {}, but expected {})
r9   rF   r=   r<   r6   r8   r   RuntimeErrorr1   rH   )Z
grad_input_rC   r4   outr   r   r   r4      s    

z)BackwardHook._set_user_hook.<locals>.hookregister_hook)r   grad_fnr4   r   r   r   _set_user_hook   s    zBackwardHook._set_user_hookc                 C   s   g }g }d}t |D ]2\}}t|tjr|| || ||jO }q|rTt s\|d fS tjjj	j
j| }t|dkrtddd |D }	t|	dkrtd||	d  t|}
t||D ]\}}||
|< qt|
|fS )NFr   zCCannot set Module backward hook for a Module with no input Tensors.c                 S   s*   g | ]"}|j d ur|j  dkr|j qS )NZBackwardHookFunctionBackward)rN   name).0tr   r   r   
<listcomp>       z2BackwardHook._apply_on_tensors.<locals>.<listcomp>zaError while setting up backward hooks. Please open an issue with a code sample to reproduce this.)	enumerate
isinstancetorchZTensorrG   requires_gradZis_grad_enablednnmodulesZ
_functionsZBackwardHookFunctionapplyr   rI   listr>   r?   )r   fnargsZtensors_idxZtensorsrX   iargZnew_tensorsZgrad_fnsarg_listrD   rE   r   r   r   _apply_on_tensors   s*    


zBackwardHook._apply_on_tensorsc                    s0    fdd}  ||\}}t| _| _|S )Nc                    s     |  d S r   )rO   )rN   r   r   r   r]      s    z)BackwardHook.setup_input_hook.<locals>.fn)rb   r   r<   r=   )r   r^   r]   rC   Z	input_idxr   r   r   setup_input_hook   s
    
zBackwardHook.setup_input_hookc                    sT    fdd}d}t |ts$|f}d} ||\}}t| _| _|sP|d }|S )Nc                    s    fdd}|  | d S )Nc           	         s     j| j _ jrnt j} jD ]B}| j j}|d u rFq*t|}||krftd||| _q* j	d u rֈ  g g  j
} jD ]@}| j| j}|d urt|trtdd |D stdqd  _ jd ur jd usJ t fdd jD S d S )NzTBackward pre hook returned an invalid number of grad_output, got {}, but expected {}c                 s   s   | ]}|d u V  qd S r   r   )rQ   elr   r   r   	<genexpr>   rT   zKBackwardHook.setup_output_hook.<locals>.fn.<locals>.hook.<locals>.<genexpr>zoBackward hook for Modules where no input requires gradient should always return None or None for all gradients.c                 3   s   | ]} j | V  qd S r   )r9   )rQ   r_   r   r   r   re      rT   )rF   r;   r:   r9   r7   r   r8   rI   r1   r=   r<   r6   rV   r?   all)	rJ   Zgrad_outputexpected_lenZuser_pre_hookZhook_grad_outputsZ
actual_lenZgrad_inputsZ	user_hookrC   r   r   r   r4      s4    



$
z8BackwardHook.setup_output_hook.<locals>.fn.<locals>.hookrL   )rN   r4   r   r   r   r]      s    !z*BackwardHook.setup_output_hook.<locals>.fnTFr   )rV   r?   rb   r   r:   r;   )r   r^   r]   Zis_tuplerC   Z
output_idxr   r   r   setup_output_hook   s    $

zBackwardHook.setup_output_hookN)r&   r'   r(   r)   r   rF   rH   rO   rb   rc   rh   r   r   r   r   r   \   s   	!	r   )rW   collectionsr   r   r/   typingr   __all__r   r   r   r   r   r   r   r   <module>   s   ?

