U
    yhB                  
   @  s  d dl mZ d dlZd dl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  mZ d dlmZmZ d dlmZmZmZmZmZmZ d dlmZm Z  d dl!m"Z"m#Z#m$Z$m%Z%m&Z&m'Z' erd dl(m)Z) d d	l*m+Z+ d
dgZ,dddddZ-ddddZ.ddddZ/ddddZ0ej1d4d d d d!d!d!d!d"d#dZ2ddd$d%Z3d&d'd(d)Z4dd*d+d,Z5d-d.d/d0d1d2Z6G d3d
 d
e Z7dS )5    )annotationsN)AnyCallableDictListOptionalSetTYPE_CHECKING)FakeQuantizeFusedMovingAvgObsFakeQuantize)HistogramObserverMinMaxObserverMovingAverageMinMaxObserver%MovingAveragePerChannelMinMaxObserverPerChannelMinMaxObserverPlaceholderObserver)QuantizationSpec	Quantizer)_convert_scalars_to_attrsOP_TO_ANNOTATOROperatorConfigOperatorPatternTypepropagate_annotationQuantizationConfig)"_ObserverOrFakeQuantizeConstructor)NodeXNNPACKQuantizer!get_symmetric_quantization_configr   ztorch.fx.Graph)functionreturnc                 C  s&   t j| dd| \}}|j  |jS )NT)Z
aten_graph)torchdynamoZexportgraphZeliminate_dead_code)r   inputsZgm_ r$   c/var/www/html/venv/lib/python3.8/site-packages/torch/ao/quantization/quantizer/xnnpack_quantizer.py_get_dynamo_graph0   s    
r&   z	List[int])
input_sizec           	      C  s`   | d }d}t ||f}t |f}t | }ddd}t||||f}t|||f}||gS )N   c                 S  s   t | ||S N)Flinear)actweightbiasr$   r$   r%   	linear_op=   s    z'_get_linear_patterns.<locals>.linear_op)N)torchZonesr&   )	r'   Zin_channelsZout_channelsr.   r/   r-   r0   Zpattern_w_biasZpattern_wo_biasr$   r$   r%   _get_linear_patterns6   s    

r2   z$Dict[str, List[OperatorPatternType]]r   c                  C  sz   t jjt jjgt jjtjgtjt jjgtjtjggt jjgtjggt j	ggt jj
gtjggt jjgtjggd} t| S )N)conv2dr,   add
max_pool2dadaptive_avg_pool2d)r1   nnZConv2dZReLUr+   Zrelur4   ZLinearr,   r5   Z	MaxPool2dr6   ZAdaptiveAvgPool2dr7   copydeepcopy)Zsupported_operatorsr$   r$   r%   (_supported_symmetric_quantized_operatorsE   s    
r;   List[OperatorConfig]c                  C  sZ   g } t  t ddt ddt dddfD ](}t }| D ]}| t|| q8q&t| S )NT)is_qat)is_per_channel)r>   r=   )r   r;   valuesappendr   r9   r:   )supported_config_and_operatorsquantization_configopsZpattern_listr$   r$   r%   -_get_supported_symmetric_config_and_operatorsZ   s    
rD   F   boolint)r>   r=   
is_dynamicact_qminact_qmaxweight_qminweight_qmaxc              
   C  s   ddi}|r0|r*t }tjdd}	|	|d< q>t}n|r:t}nt}ttj||tj	||jf |d}
| rhtj
ntj}t}|r|t}n| rt}ddi}|r|tjkrt|d< nt|d< ttj|||dd|jf |d	}d }|rt|
d |||}nt|
|
|||}|S )
Nepsg      0?   )Zaveraging_constantZobserver)dtype	quant_min	quant_maxqschemerJ   observer_or_fake_quant_ctrr   F)rQ   rR   rS   rT   Zch_axisrJ   rU   )r
   r   Z	with_argsr   r   r   r   r1   Zint8Zper_tensor_affineZper_channel_symmetricZper_tensor_symmetricr   r   r   r   )r>   r=   rJ   rK   rL   rM   rN   
extra_argsZact_observer_or_fake_quant_ctrZdynamic_quant_observerZact_quantization_specZweight_qschemeZ!weight_observer_or_fake_quant_ctrZweight_quantization_specZbias_quantization_specrB   r$   r$   r%   r   j   s~    



c                   C  s   t  S r*   )rD   r$   r$   r$   r%   #_get_supported_config_and_operators   s    rW   strmodule_namec                   s   ddd fdd}|S )a  Get the module_name_filter function for a given module name, the filter accepts
    a node and checks if the node comes from a module that has certain module name

    For example:
        node: linear_op = call_function[...](...)  # comes from a module with name blocks.sub.linear1


    >> module_name_filter = _get_module_name_filter("blocks.sub")
    >> print(module_name_filter(node))
    True  # the node is from "blocks.sub" based on the fully qualified name "blocks.sub.linear1"
    r   rH   nr   c                   s4   | j di }dd   fdd| D }|kS )Nnn_module_stackc                 S  s"   d}|  drtd}| |d  S )Nr   z
L['self'].)
startswithlen)r\   prefixr$   r$   r%   _normalize_path   s    
zL_get_module_name_filter.<locals>.module_name_filter.<locals>._normalize_pathc                   s   g | ]\}} |qS r$   r$   ).0r\   r#   ra   r$   r%   
<listcomp>   s     zG_get_module_name_filter.<locals>.module_name_filter.<locals>.<listcomp>)metagetr?   )r\   r]   namesrY   rc   r%   module_name_filter   s    z3_get_module_name_filter.<locals>.module_name_filterr$   )rZ   rh   r$   rY   r%   _get_module_name_filter   s    ri   )tpc                   s(   | j d | j  ddd fdd}|S )a  Get the module_type_filter function for a given module type, the filter accepts
    a node and checks if the node comes from a module that has certain module type

    For example:
        node: linear_op = call_function[...](...)  # comes from a module with type Block -> Sub -> Linear


    >> module_type_filter = _get_module_type_filter(Sub)  # submodule with type `Sub`, under the `Block` submodule
    >> print(module_type_filter(node))
    True  # the node is from the submodule `Sub` (same for `Block` and `Linear` as well)
    .r   rH   r[   c                   sP   | j di }g }| D ],\}}t|tr<|jd |j }|| q |kS )Nr]   rk   )re   rf   r?   
isinstancetype
__module____qualname__r@   )r\   r]   typesr#   tZtp_strr$   r%   module_type_filter   s    
z3_get_module_type_filter.<locals>.module_type_filter)rn   ro   )rj   rs   r$   rr   r%   _get_module_type_filter   s    rt   zList[Callable]z	List[str]zCallable[[Node], bool])tp_listmodule_name_listr   c                   s6   dd | D dd |D  ddd fdd}|S )	Nc                 S  s   g | ]}t |qS r$   )rt   )rb   rj   r$   r$   r%   rd   
  s     z7_get_not_module_type_or_name_filter.<locals>.<listcomp>c                 S  s   g | ]}t |qS r$   )ri   )rb   mr$   r$   r%   rd     s     r   rH   r[   c                   s   t  fdd D  S )Nc                 3  s   | ]}| V  qd S r*   r$   )rb   fr\   r$   r%   	<genexpr>  s     z^_get_not_module_type_or_name_filter.<locals>.not_module_type_or_name_filter.<locals>.<genexpr>)anyry   Zmodule_name_list_filtersZmodule_type_filtersry   r%   not_module_type_or_name_filter  s    zK_get_not_module_type_or_name_filter.<locals>.not_module_type_or_name_filterr$   )ru   rv   r}   r$   r|   r%   #_get_not_module_type_or_name_filter  s    r~   c                      sH  e Zd Ze ZddddgZddddd	d
dddddddgZdgZ fddZe	ddddZ
e	dddddZdd dddZd dd d!d"d#Zd$dd%d&d'Zd(dd)d*d+Zd,d,d-d.d/Zd,d,d-d0d1ZdCd,dd3d,d4d5d6ZdDd,dd3d,d4d7d8Zd,d,d-d9d:Zd,d,d-d;d<Zd,d=d-d>d?Ze	d@ddAdBZ  ZS )Er   Zconv_bn_reluZconv_bnZconv_transpose_bn_reluZconv_transpose_bnZlinear_relur,   Z	conv_reluconvZconv_transpose_relur7   Zgru_io_onlyr6   Zadd_relur5   Zmul_relumulcatc                   s&   t    d | _i | _i | _i | _d S r*   )super__init__global_configoperator_type_configmodule_type_configmodule_name_config)self	__class__r$   r%   r   3  s    
zXNNPACKQuantizer.__init__zList[QuantizationConfig]r3   c                 C  s   dd | j D }t|S )Nc                 S  s   h | ]\}}|qS r$   r$   )rb   specr#   r$   r$   r%   	<setcomp>>  s    zFXNNPACKQuantizer.get_supported_quantization_configs.<locals>.<setcomp>)rA   list)clsZ
op_configsr$   r$   r%   "get_supported_quantization_configs<  s    z3XNNPACKQuantizer.get_supported_quantization_configszOptional[QuantizationConfig]zList[OperatorPatternType])rB   r   c                 C  sN   |d kr*g }| j D ]\}}|| q|S | j D ]\}}||kr0|  S q0g S r*   )rA   extend)r   rB   Zall_opsr#   rC   configr$   r$   r%   .get_supported_operator_for_quantization_configC  s    
z?XNNPACKQuantizer.get_supported_operator_for_quantization_configr   c                 C  s
   || _ | S r*   )r   )r   rB   r$   r$   r%   
set_globalW  s    zXNNPACKQuantizer.set_globalztorch._ops.OpOverloadPacket)operator_typerB   r   c                 C  s   || j |< | S r*   )r   )r   r   rB   r$   r$   r%   set_operator_type[  s    
z"XNNPACKQuantizer.set_operator_typer   )module_typerB   c                 C  s   || j |< | S )a5  Set quantization_config for a submodule with type: `module_type`, for example:
        quantizer.set_module_name(Sub) or quantizer.set_module_name(nn.Linear), it will quantize all supported operator/operator
        patterns in the submodule with this module type with the given `quantization_config`
        )r   )r   r   rB   r$   r$   r%   set_module_typec  s    
z XNNPACKQuantizer.set_module_typerX   )rZ   rB   c                 C  s   |dk	st d|| j|< | S )a  Set quantization_config for a submodule with name: `module_name`, for example:
        quantizer.set_module_name("blocks.sub"), it will quantize all supported operator/operator
        patterns in the submodule with this module name with the given `quantization_config`
        Nz1 quantization_config == None is not supported yet)AssertionErrorr   )r   rZ   rB   r$   r$   r%   set_module_namem  s    
z XNNPACKQuantizer.set_module_nameztorch.fx.GraphModule)modelr   c                 C  s   t |S )z-Transforms scalar values to tensor attributes)r   r   r   r$   r$   r%   transform_for_annotationz  s    z)XNNPACKQuantizer.transform_for_annotationc                 C  s2   | j r| j jjr| |}n
| |}t| |S )z!just handling global spec for now)r   Zinput_activationrJ   )_annotate_for_dynamic_quantization_config(_annotate_for_static_quantization_configr   r   r$   r$   r%   annotate  s
    
zXNNPACKQuantizer.annotateNz Optional[Callable[[Node], bool]])r   rB   	filter_fnr   c                 C  sN   |d kr|S |j r.| jD ]}t| ||| q| jD ]}t| ||| q4|S r*   )r=   STATIC_QAT_ONLY_OPSr   
STATIC_OPSr   r   rB   r   opr$   r$   r%   _annotate_all_static_patterns  s    

z.XNNPACKQuantizer._annotate_all_static_patternsc                 C  s,   |d kr|S | j D ]}t| ||| q|S r*   )DYNAMIC_OPSr   r   r$   r$   r%   _annotate_all_dynamic_patterns  s
    
z/XNNPACKQuantizer._annotate_all_dynamic_patternsc                 C  s   t | j }| j D ]\}}| ||t| qt | j }| j D ]\}}| ||t| qL| || jt	|| |S r*   )
r   r   keysitemsr   ri   r   rt   r   r~   r   r   rv   rZ   r   ru   r   r$   r$   r%   r     s(        z9XNNPACKQuantizer._annotate_for_static_quantization_configc                 C  s   t | j }| j D ]\}}| ||t| qt | j }| j D ]\}}| ||t| qL| || jt	|| |S r*   )
r   r   r   r   r   ri   r   rt   r   r~   r   r$   r$   r%   r     s(        z:XNNPACKQuantizer._annotate_for_dynamic_quantization_configNonec                 C  s   d S r*   r$   r   r$   r$   r%   validate  s    zXNNPACKQuantizer.validater<   c                 C  s   | j S r*   )rA   )r   r$   r$   r%   get_supported_operators  s    z(XNNPACKQuantizer.get_supported_operators)N)N)__name__rn   ro   rW   rA   r   r   r   r   classmethodr   r   r   r   r   r   r   r   r   r   r   r   r   r   __classcell__r$   r$   r   r%   r     sT   
	
  )FFFrE   rF   rG   rF   )8
__future__r   r9   	functoolstypingr   r   r   r   r   r   r	   r1   Ztorch._dynamoZ_dynamor    Ztorch.nn.functionalr8   Z
functionalr+   Z#torch.ao.quantization.fake_quantizer
   r   Ztorch.ao.quantization.observerr   r   r   r   r   r   Ztorch.ao.quantization.quantizerr   r   Z7torch.ao.quantization.quantizer.xnnpack_quantizer_utilsr   r   r   r   r   r   Ztorch.ao.quantization.qconfigr   Ztorch.fxr   __all__r&   r2   r;   rD   	lru_cacher   rW   ri   rt   r~   r   r$   r$   r$   r%   <module>   sD   $ 	 
       U"!