o
    h#y                     @   sX  d dl Z d dlZd dlZd dlZd dlZd dlZd dlm  m  m	Z
 d dlmZ 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 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" d dl#m$Z$ dd	l%m&Z&m'Z'm(Z( g d
Z)eZ*ej+ej,j+ej-ej,j-iej,j+ej	j+ej,j-ej	j-idZ.dd Z/			d7ddZ0d8ddZ1dd Z2dd Z3d9ddZ4				d:ddZ5dd Z6dd Z7e8e&				d;d d!Z9d"d# Z:d$d% Z;e8e&d<d&d'Z<e8e&dej=ddfd(d)Z>e8e&d<d*d+Z?e8e&d9d,d-Z@e8e&			.			d=d/d0ZA					d>d1d2ZB	d9d3d4ZCd?d5d6ZDdS )@    N)_FusedModule)_is_activation_post_process)_activation_is_memoryless_add_module_to_qconfig_obs_ctrdefault_dynamic_qconfigfloat16_dynamic_qconfig!float_qparams_weight_only_qconfig&float_qparams_weight_only_qconfig_4bit)_get_special_act_post_process_has_special_act_post_process)get_default_dynamic_quant_module_mappingsget_default_qat_module_mappings$get_default_qconfig_propagation_list(get_default_static_quant_module_mappings2get_default_static_quant_reference_module_mappingsno_observer_set)DeQuantStubQuantWrapper)type_before_parametrizations   )DEPRECATION_WARNINGget_qparam_dict)has_no_children_ignoring_parametrizations)
get_default_custom_config_dictpropagate_qconfig_add_quant_dequantpreparequantizequantize_dynamicprepare_qatquantize_qatconvertswap_module)%float_to_observed_custom_module_class)observed_to_quantized_custom_module_classc                   C   s   t S )z'Defines the default custom config dict.)_DEFAULT_CUSTOM_CONFIG_DICT r&   r&   d/home/www/facesmatcher.com/frenv_anti/lib/python3.10/site-packages/torch/ao/quantization/quantize.pyr   G   s   r    c           
      C   s   | t| |}| ||}t| d|}tjjj||  t|| }|| _| 	 D ]+\}}|r5|d | n|}	|du sM|| dg v sTt
|| dg v sTt||||	 q)dS )a  This is a helper function for `propagate_qconfig_`

    Args:
        module: input module
        qconfig_dict: dictionary that maps from name of submodule to quantization
                     configuration
        qconfig_parent: quantization config of parent module, we will fallback to
                       this config when there is no specified config for current
                       module
        prefix: corresponding prefix of the current module, used as key in
                qconfig_dict
        prepare_custom_config_dict: dictionary for custom handling of modules
                                    see docs for :func:`~torch.ao.quantization.prepare_fx`

    Return:
        None, module is modified inplace with qconfig attached
    qconfig.NZnon_traceable_module_nameZnon_traceable_module_class)getr   getattrtorchaoZquantizationr)   Z_assert_valid_qconfigr   named_childrentype_propagate_qconfig_helper)
moduleqconfig_dictZqconfig_parentprefixprepare_custom_config_dictZmodule_qconfigZqconfig_with_device_checknamechildmodule_prefixr&   r&   r'   r1   L   s,   

r1   c                 C   s*   |du ri }|du ri }t | ||d dS )a  Propagate qconfig through the module hierarchy and assign `qconfig`
    attribute on each leaf module

    Args:
        module: input module
        qconfig_dict: dictionary that maps from name or type of submodule to
            quantization configuration, qconfig applies to all submodules of a
            given module unless qconfig for the submodules are specified (when
            the submodule already has qconfig attribute)
        prepare_custom_config_dict: dictionary for custom handling of modules
            see docs for :func:`~torch.ao.quantization.prepare_fx`

    Return:
        None, module is modified inplace with qconfig attached
    N)r5   )r1   )r2   r3   r5   r&   r&   r'   r   }   s   
r   c                 C   s
   |  |S )z.Forward hook that calls observer on the outputactivation_post_process)selfinputoutputr&   r&   r'   _observer_forward_hook   s   
r>   c                 C   s   |  |d S )z2Forward pre hook that calls observer on the outputr   r9   )r;   r<   r&   r&   r'   _observer_forward_pre_hook   s   r?   Fc                 C   s:   t | ds	J d|r| jtdd d S | jtdd d S )Nr:   zGExpect activation_post_process attribute already attached to the moduleT)prepend)hasattrregister_forward_pre_hookr?   register_forward_hookr>   )r2   pre_hookr&   r&   r'   &_register_activation_post_process_hook   s   rE   c                    s  |du rt  }|du ri } du r0t| }t|dks"J d| t|dkr.tt|nd ddddd d fd	d
	}|  D ]\}}t|tjfv rSqFt	t|t
jt
jfry|rxt|dsqJ dt| d|j |_qFt|tr|r|| qF|durt||v r|r|| qFt|rt|}	|||	 qF|rt||v r|t| }
|
|}t| || t	|
tt s|| qFt||| | qFt| rt| tjjst| |v r||  t| dr	t| tjjst| |v r||  dS dS dS dS )as  Add observer for the leaf child of the module.

    This function insert observer module to all leaf child module that
    has a valid qconfig attribute.

    Args:
        module: input module with qconfig attributes for all the leaf modules that we want to quantize
        qconfig_propagation_list: a list of quantizable modules that will have observers added to them
            if they are leaf nodes
        device: parent device, if any
        non_leaf_module_list: list of non-leaf modules we want to add observer

    Return:
        None, module is modified inplace with added observer modules and forward_hooks
    Nr   zR_add_observer_ only works with cpu or single-device CUDA modules, but got devices r   c                 S   s,   |d u r|   n| }|d ur|| |S N)
activationto)r)   devicespecial_act_post_processrG   r&   r&   r'   get_activation_post_process   s   

z3_add_observer_.<locals>.get_activation_post_processc                 S   s   t | do	| jd uS )Nr)   rA   r)   )mr&   r&   r'   needs_observation      z)_add_observer_.<locals>.needs_observationc                    sF   | rt | ts!| d| j | t| t| jd dS dS dS )zmAdds an activation post process module and register
        a pre or post hook that calls the module
        r:   rD   N)
isinstancer   Z
add_moduler)   rE   r   )rM   rJ   rI   rK   rN   r&   r'   insert_activation_post_process   s   

z6_add_observer_.<locals>.insert_activation_post_processr:   zfunctional class z- has no pre-defined `activation_post_process`Zweight_fake_quantrF   )r   _get_unique_devices_lennextiterr/   r   nnZDropout
issubclassnnqZFloatFunctionalZQFunctionalrA   r)   r:   rQ   r   r   r
   
from_floatsetattrtupler   _add_observer_r   r-   Z
Sequential)r2   qconfig_propagation_listZnon_leaf_module_listrI   custom_module_class_mappingdevicesrS   r6   r7   rJ   Zobserved_classZobserved_childr&   rR   r'   r^      s   







r^   c                 C   s$   dd |   D dd |  D B S )Nc                 S   s   h | ]}|j jd kr|j qS )meta)rI   r0   ).0pr&   r&   r'   	<setcomp>4  s    z'_get_unique_devices_.<locals>.<setcomp>)
parametersbuffersr2   r&   r&   r'   rT   3  s   rT   c                 C   sD   t | rt| dr| jrt| S |  D ]\}}t|| j|< q| S )a{  Wrap the leaf child module in QuantWrapper if it has a valid qconfig
    Note that this function will modify the children of module inplace and it
    can return a new module which wraps the input module as well.

    Args:
        module: input module with qconfig attributes for all the leaf modules
        that we want to quantize

    Return:
        Either the inplace modified module with submodules wrapped in
        `QuantWrapper` based on qconfig or a new `QuantWrapper` module which
        wraps the input module, the latter case only happens when the input
        module is a leaf module and we want to quantize it.
    r)   )r   rA   r)   r   r/   r   _modules)r2   r6   r7   r&   r&   r'   r   9  s   r   c                 C   s   t jd |du rt }|di }|st| } |}|du r#t }t| dd t	dd | 
 D s9td t| |||d | S )	af  Prepares a copy of the model for quantization calibration or quantization-aware training.

    Quantization configuration should be assigned preemptively
    to individual submodules in `.qconfig` attribute.

    The model will be attached with observer or fake quant modules, and qconfig
    will be propagated.

    Args:
        `model`: input model to be modified in-place
        `inplace`: carry out model transformations in-place, the original module is mutated
        `allow_list`: list of quantizable modules
        `observer_non_leaf_module_list`: list of non-leaf modules we want to add observer
        `prepare_custom_config_dict`: customization configuration dictionary for prepare function

    .. code-block:: python

       # Example of prepare_custom_config_dict:
       prepare_custom_config_dict = {
           # user will manually define the corresponding observed
           # module class which has a from_float class method that converts
           # float custom module to observed custom module
           "float_to_observed_custom_module_class": {CustomModule: ObservedCustomModule}
       }

    z!quantization_api.quantize.prepareNr#   r3   c                 s   s     | ]}t |d o|jV  qdS )r)   NrL   )rc   rM   r&   r&   r'   	<genexpr>  s    zprepare.<locals>.<genexpr>zNone of the submodule got qconfig applied. Make sure you passed correct configuration through `qconfig_dict` or by assigning the `.qconfig` attribute directly on submodules)r`   )r-   _C_log_api_usage_oncer   r+   copydeepcopyr   r   anymoduleswarningswarnr^   )modelinplaceZ
allow_listobserver_non_leaf_module_listr5   r`   r_   r&   r&   r'   r   T  s.   "
r   c                    sD   t  drt jrt d d fdd	}|dd |dd d S )Nr:   Fc                    s^   | r j n j}| rtnt}t }| D ]\}}||u r"|| q|D ]}|| q%d S rF   )_forward_pre_hooks_forward_hooksr?   r>   setitemsaddpop)rD   Zhook_mapZobserver_hookZhandle_ids_to_removeZ	handle_idhook_fnrh   r&   r'   remove_hooks  s   

z5_remove_activation_post_process.<locals>.remove_hooksTrP   F)rA   r   r:   delattr)r2   r~   r&   rh   r'   _remove_activation_post_process  s   

r   c                 C   s0   |   D ]}t| qt| dr| `t|  dS )zClean up the qconfig left in the module so that new qconfig can be
    propagated.

    Args:
        module: module to be cleaned up
    r)   N)children_remove_qconfigrA   r)   r   )r2   r7   r&   r&   r'   r     s
   

r   c                 C   s^   t jd |du rt }|st| } |   t| dd || g|R   t| |dd | S )a  Quantize the input float model with post training static quantization.

    First it will prepare the model for calibration, then it calls
    `run_fn` which will run the calibration step, after that we will
    convert the model to a quantized model.

    Args:
        model: input float model
        run_fn: a calibration function for calibrating the prepared model
        run_args: positional arguments for `run_fn`
        inplace: carry out model transformations in-place, the original module is mutated
        mapping: correspondence between original module types and quantized counterparts

    Return:
        Quantized model.
    z"quantization_api.quantize.quantizeNTru   )	r-   rl   rm   r   rn   ro   evalr   r!   )rt   run_fnrun_argsmappingru   r&   r&   r'   r     s   
r   c                 C   sj  t jd |du r_|t jkr$tjttjttjttj	ttj
ttjti}q|t jkr>tjttjttjttj	ttj
ttjti}q|t jkrLtjttjti}q|t jkrWtjti}qtd| dt|tr|t ju rlt}n|t ju rtt}n|t ju r|t}n|t ju rt}ntdt|tt|t|}|du rt }|st| } |    t!| | t"| |dd | S )av  Converts a float model to dynamic (i.e. weights-only) quantized model.

    Replaces specified modules with dynamic weight-only quantized versions and output the quantized model.

    For simplest usage provide `dtype` argument that can be float16 or qint8. Weight-only quantization
    by default is performed for layers with large weights size - i.e. Linear and RNN variants.

    Fine grained control is possible with `qconfig` and `mapping` that act similarly to `quantize()`.
    If `qconfig` is provided, the `dtype` argument is ignored.

    Args:
        model: input model
        qconfig_spec: Either:

            - A dictionary that maps from name or type of submodule to quantization
              configuration, qconfig applies to all submodules of a given
              module unless qconfig for the submodules are specified (when the
              submodule already has qconfig attribute). Entries in the dictionary
              need to be QConfig instances.

            - A set of types and/or submodule names to apply dynamic quantization to,
              in which case the `dtype` argument is used to specify the bit-width

        inplace: carry out model transformations in-place, the original module is mutated
        mapping: maps type of a submodule to a type of corresponding dynamically quantized version
            with which the submodule needs to be replaced

    z*quantization_api.quantize.quantize_dynamicNz5Don't know how to quantize with default settings for z. Provide full qconfig pleasez.Unknown dtype specified for quantize_dynamic: Tr   )#r-   rl   rm   qint8rX   ZLinearr   LSTMZGRUZLSTMCellZRNNCellZGRUCellZfloat16r   Zquint8ZEmbeddingBagr   Z	EmbeddingZquint4x2r	   
ValueErrorrQ   ry   RuntimeErrorstrdictzip	itertoolsrepeatr   rn   ro   r   r   r!   )rt   Zqconfig_specZdtyper   ru   Zdefault_qconfigr&   r&   r'   r     sb    











r   c                 C   sl   t jd | jsJ d|du rt }|st| } t| dd t| |ddd t	| t
| dd | S )	a  
    Prepares a copy of the model for quantization calibration or
    quantization-aware training and converts it to quantized version.

    Quantization configuration should be assigned preemptively
    to individual submodules in `.qconfig` attribute.

    Args:
        model: input model to be modified in-place
        mapping: dictionary that maps float modules to quantized modules to be
                 replaced.
        inplace: carry out model transformations in-place, the original module
                 is mutated
    z%quantization_api.quantize.prepare_qatz1prepare_qat only works on models in training modeNrj   TF)r   ru   remove_qconfig)rv   ru   )r-   rl   rm   Ztrainingr   rn   ro   r   r!   r   ry   values)rt   r   ru   r&   r&   r'   r   :  s   
r   c                 C   sN   t jd |st| } |   t| dd || g|R   t| dd | S )ag  Do quantization aware training and output a quantized model

    Args:
        model: input model
        run_fn: a function for evaluating the prepared model, can be a
                function that simply runs the prepared model or a training
                loop
        run_args: positional arguments for `run_fn`

    Return:
        Quantized model.
    z&quantization_api.quantize.quantize_qatTr   )r-   rl   rm   rn   ro   trainr   r!   )rt   r   r   ru   r&   r&   r'   r    X  s   
r    Tc                 C   s>   t jd |st| } t| |d|||d |rt|  | S )a  Converts submodules in input module to a different module according to `mapping`
    by calling `from_float` method on the target module class. And remove qconfig at the
    end if remove_qconfig is set to True.

    Args:
        `module`: prepared and calibrated module
        `mapping`: a dictionary that maps from source module type to target
                   module type, can be overwritten to allow swapping user defined
                   Modules
        `inplace`: carry out model transformations in-place, the original module
                   is mutated
        `convert_custom_config_dict`: custom configuration dictionary for convert function
        `use_precomputed_fake_quant`: a flag to enable use of precomputed fake quant

    .. code-block:: python

       # Example of convert_custom_config_dict:
       convert_custom_config_dict = {
           # user will manually define the corresponding quantized
           # module class which has a from_observed class method that converts
           # observed custom module to quantized custom module
           "observed_to_quantized_custom_module_class": {
               ObservedCustomModule: QuantizedCustomModule
           }
       }

    z!quantization_api.quantize.convertT)ru   is_referenceconvert_custom_config_dictuse_precomputed_fake_quant)r-   rl   rm   rn   ro   _convertr   )r2   r   ru   r   r   r   r   r&   r&   r'   r!   p  s   %
r!   c              	   C   s   |du r|r	t  nt }|du rt }|di }|s t| } i }|  D ]"\}}	t|	ts?t	|	|vr?t
|	|d|||d t|	|||||< q&| D ]	\}
}|| j|
< qM| S )ao  Converts submodules in input module to a different module according to `mapping`
    by calling `from_float` method on the target module class

    Args:
        module: input module
        mapping: a dictionary that maps from source module type to target
                 module type, can be overwritten to allow swapping user defined
                 Modules
        inplace: carry out model transformations in-place, the original module
                 is mutated
        is_reference: a flag to enable quantized reference module
        use_precomputed_fake_quant: a flag to enable use of precomputed fake quant

    Nr$   Tr   )r   r   r   r+   rn   ro   r/   rQ   r   r   r   r"   rz   ri   )r2   r   ru   r   r   r   r`   Zreassignr6   modkeyvaluer&   r&   r'   r     s@   


r   c                 C   s~  | }t | dr| jdurd}t| |v r |t|  | }d}nJt| |v rj|t|  }t |drP|jrP| jdus;J | j }|| j t|}|| |}nt	|j}	d|	j
v rc|j| |d}n|| }d}|r| j D ]}
||
 qq| j D ]}|tur|| q~t| }t|dkst|d	krtd
|v sJ d| t|dkrtt|nd}|r|| |S )a	  Swaps the module if it has a quantized counterpart and it has an
    `observer` attached.

    Args:
        mod: input module
        mapping: a dictionary that maps from nn module to nnq module

    Return:
        The corresponding quantized module of `mod`
    r)   NFT_IS_REFERENCEr   r   r      rb   zOswap_module only works with cpu or single-device CUDA modules, but got devices r   )rA   r)   r   Zfrom_observedr   weightr   r[   inspect	signaturerf   rw   r   rB   rx   r>   rC   rT   rU   r-   rI   rV   rW   rH   )r   r   r`   r   new_modZswappedZqmodZweight_post_processZweight_qparamssigZpre_hook_fnr}   ra   rI   r&   r&   r'   r"     sX   






r"   c                 C   sZ   dd }t | dr| j|||d < |  D ]\}}|r"||| n|}t||| qdS )a,  Traverse the modules and save all observers into dict.
    This is mainly used for quantization accuracy debug
    Args:
        mod: the top module we want to save all observers
        prefix: the prefix for the current module
        target_dict: the dictionary used to save all the observers
    c                 S   s   | dkr| S | d S )Nr(   r*   r&   )r4   r&   r&   r'   
get_prefix*  rO   z&_get_observer_dict.<locals>.get_prefixr:   N)rA   r:   r/   _get_observer_dict)r   target_dictr4   r   r6   r7   r8   r&   r&   r'   r   !  s   	
r   )Nr(   N)NNr   )NNNN)FNNN)NF)NFTFNF)NFFNF)r(   )Ern   r   r   Ztyping_extensionsrr   r-   Ztorch.ao.nn.quantizedr.   rX   Z	quantizedrZ   Ztorch.nnZtorch.ao.nn.intrinsicr   Ztorch.ao.quantization.observerr   Ztorch.ao.quantization.qconfigr   r   r   r   r   r	   Z+torch.ao.quantization.quantization_mappingsr
   r   r   r   r   r   r   r   Ztorch.ao.quantization.stubsr   r   Ztorch.nn.utils.parametrizer   utilsr   r   r   __all__Zis_activation_post_processr   ZquantizableZMultiheadAttentionr%   r   r1   r   r>   r?   rE   r^   rT   r   
deprecatedr   r   r   r   r   r   r   r    r!   r   r"   r   r&   r&   r&   r'   <module>   s    (




1

 
B
Z6
?
>