a
    7SicÍ  ã                   @   sl   d dl Z d dlmZ d dlZd dlZd dlZd dlmZ G dd„ deƒZ	dd„ Z
dd	„ ZG d
d„ deƒZdS )é    N)ÚOrderedDict)ÚAnyc                   @   s|   e Zd ZU dZeed< dZeed< 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 )ÚRemovableHandlez8A handle which provides the capability to remove a hook.Úidr   Únext_idN)Ú
hooks_dictÚreturnc                 C   s&   t  |¡| _tj| _t jd7  _d S )Né   )ÚweakrefÚrefÚhooks_dict_refr   r   r   ©Úselfr   © r   úM/var/www/html/django/DPS/env/lib/python3.9/site-packages/torch/utils/hooks.pyÚ__init__   s    zRemovableHandle.__init__)r   c                 C   s&   |   ¡ }|d ur"| j|v r"|| j= d S ©N©r   r   r   r   r   r   Úremove   s    zRemovableHandle.removec                 C   s   |   ¡ | jfS r   r   ©r   r   r   r   Ú__getstate__   s    zRemovableHandle.__getstate__c                 C   sN   |d d u rt  tƒ ¡| _nt  |d ¡| _|d | _ttj| jd ƒt_d S )Nr   r	   )r
   r   r   r   r   Úmaxr   r   )r   Ústater   r   r   Ú__setstate__   s
    
zRemovableHandle.__setstate__c                 C   s   | S r   r   r   r   r   r   Ú	__enter__%   s    zRemovableHandle.__enter__)ÚtypeÚvalueÚtbr   c                 C   s   |   ¡  d S r   )r   )r   r   r   r   r   r   r   Ú__exit__(   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   Úunserializable_hook,   s    r'   c                 C   s>   | j r:| j D ],}| j | }t|dƒst d t|ƒ¡¡ qd S )Nr%   z«backward 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)Ú_backward_hooksÚhasattrÚwarningsÚwarnÚformatÚrepr)ÚtensorÚkÚhookr   r   r   Úwarn_if_has_hooks6   s    


ýr1   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 )ÚBackwardHooka§  
    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   s.   || _ || _d | _d| _d | _d| _d | _d S )Néÿÿÿÿ)Ú
user_hooksÚmoduleÚgrad_outputsÚ	n_outputsÚoutput_tensors_indexÚn_inputsÚinput_tensors_index)r   r5   r4   r   r   r   r   J   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_noneT   s    

zBackwardHook._pack_with_nonec                 C   s$   g }|D ]}|  || ¡ qt|ƒS r   )Úappendr<   )r   r=   r>   r@   rA   r   r   r   Ú_unpack_none[   s    zBackwardHook._unpack_nonec                    s&   t  ˆ¡‡ ‡fdd„ƒ}| |¡ d S )Nc                    sv   ˆ j d u rtdƒ‚ˆ  ˆ j| ˆ j¡} ˆˆ j| ˆ j ƒ}|d u r@|S t|ƒt| ƒkrhtd t|ƒt| ƒ¡ƒ‚ˆ  ˆ j|¡S )Na(  Module backward hook for grad_input is called before the grad_output one. This happens because the gradient in your nn.Module flows to the Module's input without passing through the Module's output. Make sure that the output depends on the input and that the loss is computed based on the output.zOBackward hook returned an invalid number of grad_input, got {}, but expected {})	r6   ÚRuntimeErrorrC   r:   r9   r5   Úlenr,   rE   )Z
grad_inputÚ_r@   ©r   Ú	user_hookr   r   r0   c   s    
ÿz)BackwardHook._set_user_hook.<locals>.hook)Ú	functoolsÚwrapsÚregister_hook)r   Úgrad_fnrJ   r0   r   rI   r   Ú_set_user_hookb   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r‚tdƒ‚dd„ |D ƒ}	t|	ƒdkr¤tdƒ‚||	d ƒ t|ƒ}
t||ƒD ]\}}||
|< qÂt|
ƒ|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ÚtorchÚTensorrD   Úrequires_gradÚis_grad_enabledÚnnÚmodulesZ
_functionsZBackwardHookFunctionÚapplyrG   rF   Úlistr;   r<   )r   ÚfnÚargsZtensors_idxÚtensorsrY   ÚiÚargZnew_tensorsZgrad_fnsÚarg_listrA   rB   r   r   r   Ú_apply_on_tensorsx   s*    


zBackwardHook._apply_on_tensorsc                    s0   ‡ fdd„}ˆ   ||¡\}}t|ƒˆ _|ˆ _|S )Nc                    s   ˆ j D ]}ˆ  | |¡ qd S r   )r4   rO   ©rN   r0   r   r   r   r_   š   s    
z)BackwardHook.setup_input_hook.<locals>.fn)re   rG   r9   r:   )r   r`   r_   r@   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                    sz   ˆ   ˆ j|ˆ j¡ˆ _ˆ jd u rvˆ   g g ˆ j¡}ˆ jD ]@}|ˆ j|ˆ jƒ}|d ur4t|t	ƒrlt
dd„ |D ƒƒs4tdƒ‚q4d S )Nc                 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.)rC   r8   r7   r6   r:   r9   r4   r5   rV   r<   ÚallrF   )rH   Zgrad_outputZgrad_inputsrJ   r@   r   r   r   r0   ¥   s    þ

$z8BackwardHook.setup_output_hook.<locals>.fn.<locals>.hook)rM   rf   r   r   r   r_   ¤   s    z*BackwardHook.setup_output_hook.<locals>.fnTFr   )rV   r<   re   rG   r7   r8   )r   r`   r_   Zis_tupler@   Z
output_idxr   r   r   Úsetup_output_hook£   s    

zBackwardHook.setup_output_hookN)r   r    r!   r"   r   rC   rE   rO   re   rg   rk   r   r   r   r   r2   @   s   	
!
r2   )rW   Úcollectionsr   r
   r*   rK   Útypingr   Úobjectr   r'   r1   r2   r   r   r   r   Ú<module>   s   #

