a
    OSic3                     @   s  d Z ddlZ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 ddlmZ e
eeeef eeeeef f e	f ZG dd dZejjejjejjejjejjejjejjejjejjejjejjejjejjejjejjhZ ejj!j"ejj!j#ejj!j$ejj!j%ejj!j&ejj!j'ejj!j(ejj!j)ejj!j*ejj!j+ejj!j,ejj!j-ejj!j.ejj!j/ejj!j0ejj!j1ejj!j2ejj!j3ejj!j4ej5ej6ej4ej7ej8ej9ej:ej;ej<hZ=ej>dd	d
dddddddddddddddddddddhZ?d d! Z@d"d# ZAd$d% ZBd&d' ZCe	eDe	d(d)d*ZEd+d, ZFd-d. ZGd/d0 ZHd1d2 ZId3d4 ZJd5d6 ZKd7d8 ZLd9d: ZMd;d< ZNd=d> ZOePd?d@dAZQdBdC ZRdDdE ZSejTejTePdFdGdHZUeVeVePejWePeeVeVf dIdJdKZXdLdM ZYdNdO ZZdS )Pz?
Utils shared by different modes of quantization (eager/graph)
    N)	QuantTypequant_type_to_str)TupleAnyUnionCallable)is_parametrizedc                   @   s   e Zd ZdZdS )MatchAllNodezo A node pattern that matches all nodes, used in defining
    fusion patterns in FX Graph Mode Quantization
    N)__name__
__module____qualname____doc__ r   r   W/var/www/html/django/DPS/env/lib/python3.9/site-packages/torch/ao/quantization/utils.pyr	      s   r	   relurelu_
contiguousdetachdetach_hardsigmoidhardsigmoid_permuterepeatrepeat_interleavereshaperesize_shapesigmoidsigmoid_sizesqueezesqueeze_tanhtanh_	transpose	unsqueeze
unsqueeze_viewc                 C   sR   | j dko| jtv }| j dko&| jtv }| j dkoFt|t| j tv }|||fS )Ncall_functioncall_methodZcall_module)optarget	func_listmethod_listtypestrmodule_type_list)nodemodulesZis_call_functionZis_call_methodZis_call_moduler   r   r   
check_nodeb   s     r3   c                 C   s   |   }|| |S N)copyupdate)Zdefault_dictZadditional_dictdr   r   r   get_combined_dicti   s    
r8   c                 C   s   | t jkp| t jkS r4   )torchper_tensor_affineper_tensor_symmetricqschemer   r   r   is_per_tensorn   s    
r>   c                 C   s   | t jt jt jfv S r4   )r9   per_channel_affine per_channel_affine_float_qparamsper_channel_symmetricr<   r   r   r   is_per_channelr   s    rB   )objfqnreturnc                 C   s   t t|d| S )zO
    Given an obj and a fqn such as "foo.bar.baz", returns gm.foo.bar.baz.
    .)	functoolsreducegetattrsplit)rC   rD   r   r   r   getattr_from_fqnw   s    rK   c                 C   s   t | dr| jnd }| j}||d}|s,|S t|r<tj}n2t|r`|tjkrTtj}| j	|d< nt
d| ||d< |  \}}||d< ||d< |S )Nr=   )r=   dtypeaxiszUnrecognized qscheme: scale
zero_point)hasattrr=   rL   r>   r9   r:   rB   rA   r?   ch_axisRuntimeErrorcalculate_qparams)Zobserver_or_fake_quantr=   rL   ZqparamsrN   rO   r   r   r   get_qparam_dict}   s"    

rT   c                 C   sH   t |}t|}||i }t| |v s<J dt| ||t|  S )a   Get the observed/quantized custom module class that we need
    to swap `custom_module` to
    Input:
        custom_module: input, can be an instance of either a float or observed custom module
        custom_module_class_mapping: the float to observed or observed to quantized custom module class mapping
        qconfig: qconfig configured for the custom module

    Output:
        corresponding observed/quantized custom module class for input custom module instance
    zFdid not find corresponding observed module class for {} in mapping: {})get_quant_typer   getr.   format)Zcustom_moduleZcustom_module_class_mappingqconfig
quant_typeZquant_type_strZclass_mappingr   r   r   get_swapped_custom_module_class   s    rZ   c                 C   s   | d usJ |   }|jS r4   )
activationrL   )rX   r[   r   r   r   activation_dtype   s    r\   c                 C   s   | d usJ |   }|jS r4   )weightrL   )rX   r]   r   r   r   weight_dtype   s    r^   c                 C   s   t | tjtjtjfv S )z Given a qconfig, decide if the activation needs to be
    quantized or not, this includes quantizing to quint8, qint8 and float16
    )r\   r9   quint8qint8float16rX   r   r   r   "activation_is_statically_quantized   s    rc   c                 C   s,   t | \}}}|tjko*|tjtjtjfv S )z Given a qconfig, decide if the activation needs to be
    dynamically quantized or not, this includes dynamically quantizing to
    quint8, qint8 and float16
    )get_qconfig_dtypesr9   floatr_   r`   ra   )rX   r\   _activation_compute_dtyper   r   r   #activation_is_dynamically_quantized   s
    
rh   c                 C   s   t | tjtjfv S )z Given a qconfig, decide if the activation needs to be
    quantized to int8 or not, this includes quantizing to quint8, qint8
    )r\   r9   r_   r`   rb   r   r   r   activation_is_int8_quantized   s    ri   c                 C   s   t | tjkS )zY Given a qconfig, decide if the activation needs to be
    quantized to int32 or not
    )r\   r9   qint32rb   r   r   r   activation_is_int32_quantized   s    rk   c                 C   s   t | tjtjtjtjfv S )zL Given a qconfig, decide if the weight needs to be
    quantized or not
    )r^   r9   r_   r`   ra   quint4x2rb   r   r   r   weight_is_quantized   s    rm   c                 C   s   t | tjtjfv S )zW Given a qconfig, decide if the weight needs to be statically
    quantized or not
    )r^   r9   r_   r`   rb   r   r   r   weight_is_statically_quantized   s    rn   )rE   c                 C   s,   t | \}}}|tju o*|tju o*|tju S )zU Given a qconfig, returns True if this op is using int8 dynamic
    quantization
    )rd   r9   re   r`   r_   )rX   r\   r^   rg   r   r   r    op_is_int8_dynamically_quantized   s    
ro   c                 C   s>   | dusJ |   }|  }t|dr,|jnd}|j|j|fS )zk returns the qconfig tuple for qconfig:
    (activation_dtype, weight_dtype, activation_compute_dtype)
    Ncompute_dtype)r[   r]   rP   rp   rL   )rX   r[   r]   rp   r   r   r   rd      s
    rd   c                 C   s   | d usJ |   }|  }tjtjtjg}|j|v rf|j|v rFtjS t	|dr`|j
|v r`tjS tjS |jtjkr|jtjkrtjS |jtjkrtjS td|j|jd S )Nrp   zKUnrecognized dtype combination in get_quant_type: activation({}),weight({}))r[   r]   r9   r_   r`   rl   rL   r   STATICrP   rp   DYNAMICZWEIGHT_ONLYra   re   	ExceptionrW   )rX   r[   r]   Zstatic_dtypesr   r   r   rU      s$    

rU   )min_valmax_valrE   c                 C   s   |   dks|  dkr&td dS |  dks>| dkr~| tdkrd|tdkrdtd dS | |ksJ d| |nt| |ksJ d| |dS )z Checks if the given minimum and maximum values are valid, meaning that
    they exist and the min value is less than the max value.
    r   zMmust run observer before calling calculate_qparams. Returning default values.Finfz-infz!min {} should be less than max {}T)numelwarningswarndimre   rW   r9   all)rt   ru   r   r   r   check_min_max_valid  s(    
r|   )	quant_min	quant_maxhas_customized_qrangerL   reduce_rangerE   c           
      C   s&  |r|t jkrd\}}nd\}}| | }}|durD|durD|| }}|| d }	|t jkrzd|	  k rndksn J dn(|t jkrd|	  k rdksn J d	|r| d
 |d
  } }nd|t jkr|rd\} }nd\} }nB|t jkr |rd\} }nd\} }n|t jkrd\} }nd\} }| |fS )ztCalculates actual qmin and qmax based on the quantization range,
    observer datatype and if range is reduced.
    )r   )r      N   r      zRquantization range should be positive and not exceed the maximum bit range (=256).l        zYquantization range should be positive and not exceed the maximum bit range (=4294967296).   )i?   )i   )r   r   )i   r   )r      )r9   rj   r`   r_   )
r}   r~   r   rL   r   Zinitial_quant_minZinitial_quant_maxZcustom_quant_minZcustom_quant_maxZ
qrange_lenr   r   r   calculate_qmin_qmax*  sL    












r   c                 C   s8   |  dd}t|dkr$d|d fS |d |d fS dS )z,
    Turn 'foo.bar' into ['foo', 'bar']
    rF   r    r   N)rsplitlen)r+   rr   r   r   _parent_name_  s    r   c                 C   s:   t | jdkrdS t| r2t | jdko0d| jv S dS dS )z
    Checks if module._modules is empty or
    if module is a parametrization, checks that module._modules only has
    the 'parametrizations' module
    r   Tr   parametrizationsFN)r   _modulesr   )moduler   r   r   )has_no_children_ignoring_parametrizationsi  s
    r   )[r   rx   rG   r9   Z torch.ao.quantization.quant_typer   r   typingr   r   r   r   Ztorch.nn.utils.parametrizer   Patternr	   nnReLUReLU6AdaptiveAvgPool1dAdaptiveAvgPool2dAdaptiveAvgPool3d	AvgPool1d	AvgPool2d	AvgPool3d	MaxPool1d	MaxPool2d	MaxPool3dIdentityHardsigmoidSigmoidTanhr0   
functionaladaptive_avg_pool1dadaptive_avg_pool2dadaptive_avg_pool3delu	hardswishinstance_norm
layer_norm
leaky_relusilumishdropout
max_pool1d
max_pool2d
max_pool3dr   hardtanh	hardtanh_r   r   r$   r   r    stacksumr"   r%   catr,   meanr-   r3   r8   r>   rB   r/   rK   rT   rZ   r\   r^   rc   rh   ri   rk   rm   rn   boolro   rd   rU   Tensorr|   intrL   r   r   r   r   r   r   r   <module>   s   (


5
