o
    i?                     @  sr  d dl mZ d dlZd dlZd dlZd dl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 d dlmZmZmZmZmZmZmZmZ d dlmZmZm Z  d dl!m"Z"m#Z#m$Z$m%Z%m&Z&m'Z' ersd dl(m)Z) d d	lm*Z* d
dgZ+d8ddZ,d9ddZ-d:ddZ.d;ddZ/ej0							d<d=d)dZ1d;d*d+Z2d>d-d.Z3d?d4d5Z4edd6G d7d
 d
eZ5dS )@    )annotationsN)TYPE_CHECKINGAnyCallableOptional)compatibility)FakeQuantizeFusedMovingAvgObsFakeQuantizeHistogramObserverMinMaxObserverMovingAverageMinMaxObserver%MovingAveragePerChannelMinMaxObserverPerChannelMinMaxObserverPlaceholderObserver)QuantizationSpec	Quantizerget_module_name_filter)OP_TO_ANNOTATOROperatorConfigOperatorPatternTypeQuantizationConfig_convert_scalars_to_attrspropagate_annotation)Node)"_ObserverOrFakeQuantizeConstructorXNNPACKQuantizer!get_symmetric_quantization_configfunctionr   returntorch.fx.Graphc                 C  s&   t j| dd| \}}|j  |jS )NT)
aten_graph)torchdynamoexportgrapheliminate_dead_code)r   inputsgm_ r(   [/home/ubuntu/.local/lib/python3.10/site-packages/torchao/testing/pt2e/_xnnpack_quantizer.py_get_dynamo_graph8   s   
r*   
input_size	list[int]c           	      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_opE   s   z'_get_linear_patterns.<locals>.linear_opr/   )torchonesr*   )	r+   in_channelsout_channelsr3   r4   r2   r5   pattern_w_biaspattern_wo_biasr(   r(   r)   _get_linear_patterns>   s   

r<   $dict[str, list[OperatorPatternType]]c                  C  sj   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d} t| S )N)conv2dr1   addadaptive_avg_pool2d)r6   nnConv2dReLUr0   relur>   Linearr1   r?   AdaptiveAvgPool2dr@   copydeepcopy)supported_operatorsr(   r(   r)   (_supported_symmetric_quantized_operatorsM   s   

rJ   list[OperatorConfig]c                    sX   g } t  t ddt ddt dddfD ] t }|  fdd| D  qt| S )NT)is_qat)is_per_channel)rM   rL   c                 3  s    | ]}t  |V  qd S r/   )r   ).0pattern_listquantization_configr(   r)   	<genexpr>j   s
    
z@_get_supported_symmetric_config_and_operators.<locals>.<genexpr>)r   rJ   extendvaluesrG   rH   )supported_config_and_operatorsopsr(   rP   r)   -_get_supported_symmetric_config_and_operatorsa   s   


rW   F   rM   boolrL   
is_dynamicact_qminintact_qmaxweight_qminweight_qmaxc                 C  s  ddi}|r|rt }tjdd}	|	|d< n
t}n|rt}nt}ttj||tj	||jd
i |d}
| r6tj
ntj}t}|r@t}n| rDt}ddi}|rX|tjkrTt|d< nt|d< ttj|||dd|jd
i |d	}d }|rxt|
d |||}|S t|
|
|||}|S )Nepsg      0?   )averaging_constantobserver)dtype	quant_min	quant_maxqschemer\   observer_or_fake_quant_ctrr   F)rf   rg   rh   ri   ch_axisr\   rj   r(   )r   r   	with_argsr	   r   r
   r   r6   int8per_tensor_affineper_channel_symmetricper_tensor_symmetricr   r   r   r   )rM   rL   r\   r]   r_   r`   ra   
extra_argsact_observer_or_fake_quant_ctrdynamic_quant_observeract_quantization_specweight_qscheme!weight_observer_or_fake_quant_ctrweight_quantization_specbias_quantization_specrQ   r(   r(   r)   r   q   s   



c                   C  s   t  S r/   )rW   r(   r(   r(   r)   #_get_supported_config_and_operators   s   ry   tpc                   s"   | j d | j  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)
    .nr   r   r[   c                   sP   | j di }g }| D ]\}}t|tr|jd |j }|| q |v S )Nnn_module_stackr{   )metagetrT   
isinstancetype
__module____qualname__append)r|   r}   typesr'   ttp_strr(   r)   module_type_filter   s   
z3_get_module_type_filter.<locals>.module_type_filterNr|   r   r   r[   )r   r   )rz   r   r(   r   r)   _get_module_type_filter   s   r   tp_listlist[Callable]module_name_list	list[str]Callable[[Node], bool]c                   s0   dd | D dd |D  d
 fdd	}|S )Nc                 S     g | ]}t |qS r(   )r   )rN   rz   r(   r(   r)   
<listcomp>       z7_get_not_module_type_or_name_filter.<locals>.<listcomp>c                 S  r   r(   )r   )rN   mr(   r(   r)   r      r   r|   r   r   r[   c                   s   t  fdd D  S )Nc                 3  s    | ]}| V  qd S r/   r(   )rN   fr|   r(   r)   rR      s    z^_get_not_module_type_or_name_filter.<locals>.not_module_type_or_name_filter.<locals>.<genexpr>)anyr   module_name_list_filtersmodule_type_filtersr   r)   not_module_type_or_name_filter   s   zK_get_not_module_type_or_name_filter.<locals>.not_module_type_or_name_filterr   r(   )r   r   r   r(   r   r)   #_get_not_module_type_or_name_filter   s   r   )is_backward_compatiblec                      s   e Zd ZdZe Zg dZg dZdgZd6 fddZ	e
d7d
dZe
d8ddZd9ddZd:ddZd;ddZd<ddZd=d"d#Zd=d$d%Z	&d>d?d)d*Z	&d>d?d+d,Zd=d-d.Zd=d/d0Zd@d1d2Ze
dAd4d5Z  ZS )Br   z
    !!! DEPRECATED !!!
    XNNPACKQuantizer is a marked as deprected. It will be removed in the future.
    It has been moved to executorch.backends.xnnpack.quantizer.xnnpack_quantizer.XNNPACKQuantizer.
    Please use the new quantizer instead.
    )conv_bn_reluconv_bnconv_transpose_bn_reluconv_transpose_bn)linear_relur1   	conv_reluconvconv_transpose_relur@   gru_io_onlyadd_relur?   mul_relumulcatr1   r   Nonec                   s:   t    t| jj d d | _i | _i | _i | _	d S )Nz is deprecated!)
super__init__warningswarn	__class____name__global_configoperator_type_configmodule_type_configmodule_name_config)selfr   r(   r)   r     s   

zXNNPACKQuantizer.__init__list[QuantizationConfig]c                 C  s   dd | j D }t|S )Nc                 S  s   h | ]\}}|qS r(   r(   )rN   specr'   r(   r(   r)   	<setcomp>+  s    zFXNNPACKQuantizer.get_supported_quantization_configs.<locals>.<setcomp>)rU   list)cls
op_configsr(   r(   r)   "get_supported_quantization_configs)  s   z3XNNPACKQuantizer.get_supported_quantization_configsrQ   Optional[QuantizationConfig]list[OperatorPatternType]c                 C  sN   |d u rg }| j D ]	\}}|| q	|S | j D ]\}}||kr$|  S qg S r/   )rU   rS   )r   rQ   all_opsr'   rV   configr(   r(   r)   .get_supported_operator_for_quantization_config0  s   z?XNNPACKQuantizer.get_supported_operator_for_quantization_configr   c                 C  s
   || _ | S r/   )r   )r   rQ   r(   r(   r)   
set_globalD  s   zXNNPACKQuantizer.set_globaloperator_typetorch._ops.OpOverloadPacketc                 C     || j |< | S r/   )r   )r   r   rQ   r(   r(   r)   set_operator_typeH  s   
z"XNNPACKQuantizer.set_operator_typemodule_typer   c                 C  r   )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   rQ   r(   r(   r)   set_module_typeP  s   
z XNNPACKQuantizer.set_module_typemodule_namestrc                 C  s   |dusJ 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)r   )r   r   rQ   r(   r(   r)   set_module_nameZ  s
   

z XNNPACKQuantizer.set_module_namemodeltorch.fx.GraphModulec                 C  s   t |S )z-Transforms scalar values to tensor attributes)r   r   r   r(   r(   r)   transform_for_annotationg  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   input_activationr\   )_annotate_for_dynamic_quantization_config(_annotate_for_static_quantization_configr   r   r(   r(   r)   annotatem  s
   
zXNNPACKQuantizer.annotateN	filter_fn Optional[Callable[[Node], bool]]c                 C  sN   |d u r|S |j r| jD ]
}t| ||| q| jD ]
}t| ||| q|S r/   )rL   STATIC_QAT_ONLY_OPSr   
STATIC_OPSr   r   rQ   r   opr(   r(   r)   _annotate_all_static_patternsw  s   

z.XNNPACKQuantizer._annotate_all_static_patternsc                 C  s,   |d u 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     t | j }| j D ]\}}| ||t| qt | j }| j D ]\}}| ||t| q&| || jt	|| |S r/   )
r   r   keysitemsr   r   r   r   r   r   r   r   r   r   r   r   r   r(   r(   r)   r         

z9XNNPACKQuantizer._annotate_for_static_quantization_configc                 C  r   r/   )
r   r   r   r   r   r   r   r   r   r   r   r(   r(   r)   r     r   z:XNNPACKQuantizer._annotate_for_dynamic_quantization_configc                 C  s   d S r/   r(   r   r(   r(   r)   validate  s   zXNNPACKQuantizer.validaterK   c                 C  s   | j S r/   )rU   )r   r(   r(   r)   get_supported_operators  s   z(XNNPACKQuantizer.get_supported_operators)r   r   )r   r   )rQ   r   r   r   )rQ   r   r   r   )r   r   rQ   r   r   r   )r   r   rQ   r   )r   r   rQ   r   )r   r   r   r   r/   )r   r   rQ   r   r   r   r   r   )r   r   r   r   r   rK   )r   r   r   __doc__ry   rU   r   r   r   r   classmethodr   r   r   r   r   r   r   r   r   r   r   r   r   r   __classcell__r(   r(   r   r)   r      s6    	










)r   r   r   r   )r+   r,   )r   r=   r   )FFFrX   rY   rZ   rY   )rM   r[   rL   r[   r\   r[   r]   r^   r_   r^   r`   r^   ra   r^   )rz   r   )r   r   r   r   r   r   )6
__future__r   rG   	functoolsr   typingr   r   r   r   r6   torch._dynamo_dynamor!   torch.nn.functionalrA   
functionalr0   torch.fx._compatibilityr   torchao.quantization.pt2er   r	   r
   r   r   r   r   r   #torchao.quantization.pt2e.quantizerr   r   r   -torchao.testing.pt2e._xnnpack_quantizer_utilsr   r   r   r   r   r   torch.fxr   r   __all__r*   r<   rJ   rW   	lru_cacher   ry   r   r   r   r(   r(   r(   r)   <module>   sH   (
 	




U

!