U
    Kc.]                     @  s"  d dl mZ d dlm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Z d dlmZ dd	d
ddgZdZdZdZdZdZdZdZdZdZdZdZdZdZ dZ!dZ"dZ#dZ$dZ%dZ&d Z'd!Z(d"Z)G d#d deZ*eG d$d dZ+eG d%d
 d
Z,G d&d dZ-G d'd	 d	Z.dS )(    )annotations)	dataclass)AnyCallableDictListOptionalTypeUnionN)_PartialWrapper)Pattern)EnumBackendConfigBackendPatternConfigDTypeConfigDTypeWithConstraintsObservationTypeinput_dtypeoutput_dtypeweight_dtype
bias_dtype
is_dynamicnameconfigspatternobservation_typedtype_configsroot_module
qat_moduleZ#reference_quantized_module_for_rootfused_modulefuser_methodroot_node_getterextra_inputs_getter#num_tensor_args_to_observation_typeinput_type_to_indexinput_output_observedoverwrite_output_fake_quantizeoverwrite_output_observerc                   @  s   e Zd ZdZdZdZdS )r   zg An enum that represents different ways of how an operator/operator pattern
    should be observed
    r      N)__name__
__module____qualname____doc__&OUTPUT_USE_DIFFERENT_OBSERVER_AS_INPUTZ OUTPUT_SHARE_OBSERVER_WITH_INPUT r.   r.   W/tmp/pip-unpacked-wheel-gikjz4vx/torch/ao/quantization/backend_config/backend_config.pyr   3   s   c                   @  sN   e Zd ZU dZdZded< dZded< dZded< dZded< dZ	ded	< dS )
r   z
    Config for specifying additional constraints for a given dtype, such as quantization value
    ranges and scale value ranges, to be used in :class:`~torch.ao.quantization.backend_config.DTypeConfig`.
    NOptional[torch.dtype]dtypezUnion[int, float, None]quant_min_lower_boundquant_max_upper_boundscale_min_lower_boundscale_max_upper_bound)
r)   r*   r+   r,   r1   __annotations__r2   r3   r4   r5   r.   r.   r.   r/   r   E   s   
c                   @  s   e Zd ZU dZded< ded< ded< ded< ded	< dddddddddZeddddZeddddZeddddZ	e
dd dddZddddZd
S )r   a  
    Config for the set of supported input/output activation, weight, and bias data types for the
    patterns defined in :class:`~torch.ao.quantization.backend_config.BackendConfig`.

    Example usage::

        >>> dtype_config1 = DTypeConfig(
        ...     input_dtype=torch.quint8,
        ...     output_dtype=torch.quint8,
        ...     weight_dtype=torch.qint8,
        ...     bias_dtype=torch.float)

        >>> dtype_config2 = DTypeConfig(
        ...     input_dtype=DTypeWithConstraints(
        ...         dtype=torch.quint8,
        ...         quant_min_lower_bound=0,
        ...         quant_max_upper_bound=255,
        ...     ),
        ...     output_dtype=DTypeWithConstraints(
        ...         dtype=torch.quint8,
        ...         quant_min_lower_bound=0,
        ...         quant_max_upper_bound=255,
        ...     ),
        ...     weight_dtype=DTypeWithConstraints(
        ...         dtype=torch.qint8,
        ...         quant_min_lower_bound=-128,
        ...         quant_max_upper_bound=127,
        ...     ),
        ...     bias_dtype=torch.float)

        >>> dtype_config1.input_dtype
        torch.quint8

        >>> dtype_config2.input_dtype
        torch.quint8

        >>> dtype_config2.input_dtype_with_constraints
        DTypeWithConstraints(dtype=torch.quint8, quant_min_lower_bound=0, quant_max_upper_bound=255, scale_min_lower_bound=None, scale_max_upper_bound=None)
    r   input_dtype_with_constraintsoutput_dtype_with_constraintsweight_dtype_with_constraintsr0   r   zOptional[bool]r   Nz.Union[torch.dtype, DTypeWithConstraints, None])r   r   r   r   r   c                 C  sj   t |tr|| _nt|d| _t |tr0|| _nt|d| _t |trN|| _nt|d| _|| _|| _d S )N)r1   )
isinstancer   r7   r8   r9   r   r   )selfr   r   r   r   r   r.   r.   r/   __init__   s    


zDTypeConfig.__init__returnc                 C  s   | j jS N)r7   r1   r;   r.   r.   r/   r      s    zDTypeConfig.input_dtypec                 C  s   | j jS r?   )r8   r1   r@   r.   r.   r/   r      s    zDTypeConfig.output_dtypec                 C  s   | j jS r?   )r9   r1   r@   r.   r.   r/   r      s    zDTypeConfig.weight_dtypeDict[str, Any])dtype_config_dictr>   c                 C  s   | td}|dk	r,t|tjtfs,td| td}|dk	rXt|tjtfsXtd| td}|dk	rt|tjtfstd| t	d}| t
d}| |||||S )at  
        Create a ``DTypeConfig`` from a dictionary with the following items (all optional):
            "input_dtype": torch.dtype or ``DTypeWithConstraints``
            "output_dtype": torch.dtype or ``DTypeWithConstraints``
            "weight_dtype": torch.dtype or ``DTypeWithConstraints``
            "bias_type": torch.dtype
            "is_dynamic": bool
        Nz@Expected input_dtype to be a torch.dtype or DTypeWithConstraintszAExpected output_dtype to be a torch.dtype or DTypeWithConstraintszAExpected weight_dtype to be a torch.dtype or DTypeWithConstraints)getINPUT_DTYPE_DICT_KEYr:   torchr1   r   
ValueErrorOUTPUT_DTYPE_DICT_KEYWEIGHT_DTYPE_DICT_KEYBIAS_DTYPE_DICT_KEYIS_DYNAMIC_DICT_KEY)clsrB   r   r   r   r   r   r.   r.   r/   	from_dict   s    
zDTypeConfig.from_dictc                 C  sl   i }| j dk	r| j|t< | jdk	r,| j|t< | jdk	r@| j|t< | j	dk	rT| j	|t
< | jdk	rh| j|t< |S )z
        Convert this ``DTypeConfig`` to a dictionary with the items described in
        :func:`~torch.ao.quantization.backend_config.DTypeConfig.from_dict`.
        N)r   r7   rD   r   r8   rG   r   r9   rH   r   rI   r   rJ   )r;   rB   r.   r.   r/   to_dict   s    









zDTypeConfig.to_dict)NNNNN)r)   r*   r+   r,   r6   r<   propertyr   r   r   classmethodrL   rM   r.   r.   r.   r/   r   R   s*   
(     c                   @  sr   e Zd ZdZdddddZdd ddd	Zd
d dddZdd dddZedd dddZ	ddddZ
dS )r   a  Config that defines the set of patterns that can be quantized on a given backend, and how reference
    quantized models can be produced from these patterns.

    A pattern in this context refers to a module, a functional, an operator, or a directed acyclic graph
    of the above. Each pattern supported on the target backend can be individually configured through
    :class:`~torch.ao.quantization.backend_config.BackendPatternConfig` in terms of:

    (1) The supported input/output activation, weight, and bias data types

    (2) How observers and quant/dequant ops are inserted in order to construct the reference pattern, and

    (3) (Optionally) Fusion, QAT, and reference module mappings.

    The format of the patterns is described in:
    https://github.com/pytorch/pytorch/blob/master/torch/ao/quantization/backend_config/README.md

    Example usage::

        import torch
        from torch.ao.quantization.backend_config import BackendConfig, BackendPatternConfig, DTypeConfig, ObservationType
        from torch.ao.quantization.fuser_method_mappings import reverse_sequential_wrapper2

        weighted_int8_dtype_config = DTypeConfig(
            input_dtype=torch.quint8,
            output_dtype=torch.quint8,
            weight_dtype=torch.qint8,
            bias_type=torch.float)

        linear_config = BackendPatternConfig(torch.nn.Linear)             .set_observation_type(ObservationType.OUTPUT_USE_DIFFERENT_OBSERVER_AS_INPUT)             .add_dtype_config(weighted_int8_dtype_config)             .set_root_module(torch.nn.Linear)             .set_qat_module(torch.nn.qat.Linear)             .set_reference_quantized_module(torch.nn.quantized._reference.Linear)

        conv_relu_config = BackendPatternConfig((torch.nn.ReLU, torch.nn.Conv2d))             .set_observation_type(ObservationType.OUTPUT_USE_DIFFERENT_OBSERVER_AS_INPUT)             .add_dtype_config(weighted_int8_dtype_config)             .set_fused_module(torch.nn.intrinsic.ConvReLU2d)             .set_fuser_method(reverse_sequential_wrapper2(torch.nn.intrinsic.ConvReLU2d))

        backend_config = BackendConfig("my_backend")             .set_backend_pattern_config(linear_config)             .set_backend_pattern_config(conv_relu_config)

     strr   c                 C  s   || _ i | _d S r?   )r   r   r;   r   r.   r.   r/   r<     s    zBackendConfig.__init__)r   r>   c                 C  s
   || _ | S )z5
        Set the name of the target backend.
        rR   rS   r.   r.   r/   set_name  s    zBackendConfig.set_namer   )configr>   c                 C  s   || j |j< | S )z
        Set the config for an pattern that can be run on the target backend.
        This overrides any existing config for the given pattern.
        )r   r   )r;   rU   r.   r.   r/   set_backend_pattern_config  s    z(BackendConfig.set_backend_pattern_configzList[BackendPatternConfig])r   r>   c                 C  s   |D ]}|  | q| S )z
        Set the configs for patterns that can be run on the target backend.
        This overrides any existing config for a given pattern if it was previously registered already.
        )rV   )r;   r   confr.   r.   r/   set_backend_pattern_configs  s    z)BackendConfig.set_backend_pattern_configsrA   )backend_config_dictr>   c                 C  sd   | | td}| tg D ]B}t|tr6|| qt|trR|t| qtdt q|S )z
        Create a ``BackendConfig`` from a dictionary with the following items:

            "name": the name of the target backend

            "configs": a list of dictionaries that each represents a `BackendPatternConfig`

        rP   z5Expected backend_config_dict['%s'] to be a dictionary)	rC   NAME_DICT_KEYCONFIGS_DICT_KEYr:   r   rV   r   rL   rF   )rK   rY   rW   dr.   r.   r/   rL     s    


zBackendConfig.from_dictr=   c                 C  s   t | jtdd | j D iS )z
        Convert this ``BackendConfig`` to a dictionary with the items described in
        :func:`~torch.ao.quantization.backend_config.BackendConfig.from_dict`.
        c                 S  s   g | ]}|  qS r.   rM   .0cr.   r.   r/   
<listcomp>9  s     z)BackendConfig.to_dict.<locals>.<listcomp>)rZ   r   r[   r   valuesr@   r.   r.   r/   rM   2  s
      zBackendConfig.to_dictN)rP   )r)   r*   r+   r,   r<   rT   rV   rX   rO   rL   rM   r.   r.   r.   r/   r      s   .	c                   @  s0  e Zd ZdZ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ddZ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#d$d%Zdd d&d'd(Zd)d d*d+d,Zd-d d.d/d0Zd1d d2d3d4Zd5d d6d7d8Zd5d d9d:d;Zed<d d=d>d?Zd<d@dAdBZdCS )Dr   z
    Config for ops defined in :class:`~torch.ao.quantization.backend_config.BackendConfig`.
    For a detailed example usage, see :class:`~torch.ao.quantization.backend_config.BackendConfig`.

    r   )r   c                 C  s`   || _ tj| _g | _d | _d | _d | _d | _d | _	d | _
d | _i | _i | _d | _d | _d | _d S r?   )r   r   r-   r   r   r   r   reference_quantized_moduler   r    _root_node_getter_extra_inputs_getter$_num_tensor_args_to_observation_type_input_type_to_index_input_output_observed_overwrite_output_fake_quantize_overwrite_output_observer)r;   r   r.   r.   r/   r<   C  s    zBackendPatternConfig.__init__r   )r   r>   c                 C  s
   || _ | S )z
        Set how observers should be inserted for this pattern.
        See :class:`~torch.ao.quantization.backend_config.ObservationType` for details

        )r   )r;   r   r.   r.   r/   set_observation_typeV  s    z)BackendPatternConfig.set_observation_typer   )dtype_configr>   c                 C  s   | j | | S )zo
        Add a set of supported input/output activation, weight, and bias data types for this pattern.
        )r   append)r;   rl   r.   r.   r/   add_dtype_config_  s    z%BackendPatternConfig.add_dtype_configzList[DTypeConfig])r   r>   c                 C  s
   || _ | S )z
        Set the supported input/output activation, weight, and bias data types for this pattern,
        overriding all previously registered data types.
        )r   )r;   r   r.   r.   r/   set_dtype_configsf  s    z&BackendPatternConfig.set_dtype_configszType[torch.nn.Module])r   r>   c                 C  s
   || _ | S )z
        Set the module that represents the root for this pattern.
        For example, the root module for :class:`torch.nn.intrinsic.LinearReLU` should be :class:`torch.nn.Linear`.
        )r   )r;   r   r.   r.   r/   set_root_modulen  s    z$BackendPatternConfig.set_root_module)r   r>   c                 C  s
   || _ | S )zY
        Set the module that represents the QAT implementation for this pattern.
        )r   )r;   r   r.   r.   r/   set_qat_modulev  s    z#BackendPatternConfig.set_qat_module)rc   r>   c                 C  s
   || _ | S )zw
        Set the module that represents the reference quantized implementation for this pattern's root module.
        )rc   )r;   rc   r.   r.   r/   set_reference_quantized_module}  s    z3BackendPatternConfig.set_reference_quantized_module)r   r>   c                 C  s
   || _ | S )z[
        Set the module that represents the fused implementation for this pattern.
        )r   )r;   r   r.   r.   r/   set_fused_module  s    z%BackendPatternConfig.set_fused_moduler   )r    r>   c                 C  s
   || _ | S )z[
        Set the function that specifies how to fuse the pattern for this pattern.
        )r    )r;   r    r.   r.   r/   set_fuser_method  s    z%BackendPatternConfig.set_fuser_method)r!   r>   c                 C  s
   || _ | S r?   )rd   )r;   r!   r.   r.   r/   _set_root_node_getter  s    z*BackendPatternConfig._set_root_node_getter)r"   r>   c                 C  s
   || _ | S r?   )re   )r;   r"   r.   r.   r/   _set_extra_inputs_getter  s    z-BackendPatternConfig._set_extra_inputs_getterzDict[int, ObservationType])r#   r>   c                 C  s
   || _ | S r?   )rf   )r;   r#   r.   r.   r/   (_set_num_tensor_args_to_observation_type  s    z=BackendPatternConfig._set_num_tensor_args_to_observation_typezDict[str, int])r$   r>   c                 C  s
   || _ | S r?   )rg   )r;   r$   r.   r.   r/   _set_input_type_to_index  s    z-BackendPatternConfig._set_input_type_to_indexbool)r%   r>   c                 C  s
   || _ | S r?   )rh   )r;   r%   r.   r.   r/   _set_input_output_observed  s    z/BackendPatternConfig._set_input_output_observedr   )r&   r>   c                 C  s
   || _ | S r?   )ri   )r;   r&   r.   r.   r/   #_set_overwrite_output_fake_quantize  s    z8BackendPatternConfig._set_overwrite_output_fake_quantize)r'   r>   c                 C  s
   || _ | S r?   )rj   )r;   r'   r.   r.   r/   _set_overwrite_output_observer  s    z3BackendPatternConfig._set_overwrite_output_observerrA   )backend_pattern_config_dictr>   c                 C  sB  ddddd}t |kr$tdt  | |t  }t|krF||t  |tg D ]}||| qR||td |	|t
d ||td ||td ||td ||td ||td ||ti  ||ti  ||td ||td ||td |S )a  
        Create a ``BackendPatternConfig`` from a dictionary with the following items:

            "pattern": the pattern being configured
            "observation_type": the :class:`~torch.ao.quantization.backend_config.ObservationType` that specifies how
            observers should be inserted for this pattern
            "dtype_configs": a list of dictionaries that represents :class:`~torch.ao.quantization.backend_config.DTypeConfig` s
            "root_module": a :class:`torch.nn.Module` that represents the root for this pattern
            "qat_module": a :class:`torch.nn.Module` that represents the QAT implementation for this pattern
            "reference_quantized_module": a :class:`torch.nn.Module` that represents the reference quantized
            implementation for this pattern's root module.
            "fused_module": a :class:`torch.nn.Module` that represents the fused implementation for this pattern
            "fuser_method": a function that specifies how to fuse the pattern for this pattern

        r   r   )objr>   c                 S  s:   t | tr| S t | tr"t| S tdtt| f dS )zo
            Convert the given object into a ``DTypeConfig`` if possible, else throw an exception.
            zNExpected a list of DTypeConfigs in backend_pattern_config_dict["%s"], got '%s'N)r:   r   r   rL   rF   DTYPE_CONFIGS_DICT_KEYtype)r~   r.   r.   r/   _get_dtype_config  s    



z9BackendPatternConfig.from_dict.<locals>._get_dtype_configz-backend_pattern_config_dict must contain '%s'N)PATTERN_DICT_KEYrF   OBSERVATION_TYPE_DICT_KEYrk   rC   r   rn   rp   ROOT_MODULE_DICT_KEYrq   QAT_MODULE_DICT_KEYrr   #REFERENCE_QUANTIZED_MODULE_DICT_KEYrs   FUSED_MODULE_DICT_KEYrt   FUSER_METHOD_DICT_KEYru   ROOT_NODE_GETTER_DICT_KEYrv   EXTRA_INPUTS_GETTER_DICT_KEYrw   ,NUM_TENSOR_ARGS_TO_OBSERVATION_TYPE_DICT_KEYrx   INPUT_TYPE_TO_INDEX_DICT_KEYrz   INPUT_OUTPUT_OBSERVED_DICT_KEYr{   'OVERWRITE_OUTPUT_FAKE_QUANTIZE_DICT_KEYr|   "OVERWRITE_OUTPUT_OBSERVER_DICT_KEY)rK   r}   r   rW   r\   r.   r.   r/   rL     s.    
zBackendPatternConfig.from_dictr=   c                 C  s   t | jt| jtdd | jD i}| jdk	r4| j|t< | jdk	rH| j|t	< | j
dk	r\| j
|t< | jdk	rp| j|t< | jdk	r| j|t< | jdk	r| j|t< | jdk	r| j|t< t| jdkr| j|t< t| jdkr| j|t< | jdk	r| j|t< | jdk	r| j|t< | jdk	r| j|t< |S )z
        Convert this ``BackendPatternConfig`` to a dictionary with the items described in
        :func:`~torch.ao.quantization.backend_config.BackendPatternConfig.from_dict`.
        c                 S  s   g | ]}|  qS r.   r]   r^   r.   r.   r/   ra     s     z0BackendPatternConfig.to_dict.<locals>.<listcomp>Nr   )r   r   r   r   r   r   r   r   r   r   rc   r   r   r   r    r   rd   r   re   r   lenrf   r   rg   r   rh   r   ri   r   rj   r   )r;   r}   r.   r.   r/   rM     s@       



















zBackendPatternConfig.to_dictN)r)   r*   r+   r,   r<   rk   rn   ro   rp   rq   rr   rs   rt   ru   rv   rw   rx   rz   r{   r|   rO   rL   rM   r.   r.   r.   r/   r   =  s(   	1)/
__future__r   Zdataclassesr   typingr   r   r   r   r   r	   r
   rE   Ztorch.ao.quantization.observerr   Ztorch.ao.quantization.utilsr   enumr   __all__rD   rG   rH   rI   rJ   rZ   r[   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r.   r.   r.   r/   <module>   sR   $
k