U
    Kc-                  	   @   s  d dl 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 d dlmZmZmZ d dlmZ d dlmZ d dlmZ d d	lmZ d d
lmZ ddlmZmZ ddlmZm Z m!Z!m"Z" ddl#m$Z$m%Z% ddddddgZ&e"e'ee(eedddZ)ee"dddZ*e j+j,ee'e j+j,f ee"ee'ee'e-f f ee'ef dddZ.ee	e' e'ddddZ/e"e"dddZ0ee
e dd dZ1dS )!    N)defaultdictOrderedDict)CallableAnyDictTupleSetList)QConfig)add_module_to_qconfig_obs_ctr
QConfigAnyqconfig_equals)is_activation_post_process)DTypeConfig)GraphModule)Graph)_FusedModule   )_parent_nameget_qconfig_dtypes)OBJECT_TYPE_DICT_KEYMODULE_NAME_DICT_KEYMODULE_NAME_REGEX_DICT_KEYQConfigMapping)get_object_type_qconfig,maybe_adjust_qconfig_for_module_type_or_namecheck_is_valid_config_dict(compare_prepare_convert_qconfig_mappingsgenerate_qconfig_map%is_qconfig_supported_by_dtype_configs6maybe_adjust_qconfig_for_module_name_object_type_orderupdate_qconfig_for_fusion)qconfig_mappingcur_module_pathcur_object_typecur_object_type_idxfallback_qconfigreturnc           	      C   s>   | j  D ].\\}}}}||kr
||kr
||kr
|  S q
|S N)Z&module_name_object_type_order_qconfigsitems)	r"   r#   r$   r%   r&   module_nameZobject_typeindexqconfig r-   R/tmp/pip-unpacked-wheel-gikjz4vx/torch/ao/quantization/fx/qconfig_mapping_utils.pyr    1   s    
)modelr"   c           	      C   s   |j }t|dkr|S t|  }| jjD ]}|jdkr*|j|kr*|t|j }t	|t
s\q*t|j }|t|d d}|dd D ]@}t|t|d|stddt| d dt|  q|dk	r*||t|< q*dS )	z
    Update the QConfigMapping to account for fused modules such as LinearReLU.
    This assumes the QConfigMapping's attributes have already been converted to OrderedDicts.
    r   call_moduleN   z+During fusion, we need to specify the same z!qconfigs for all module types in  zoffending type: )object_type_qconfigslendictZnamed_modulesgraphnodesoptargetstr
isinstancer   listZ_modulesvaluesgettyper   LookupError)	r/   r"   Zobject_type_dictmodulesnodeZmaybe_fused_moduleopsZfused_qconfigr8   r-   r-   r.   r!   B   s,    
	)rootrA   input_graphr"   node_name_to_scoper'   c                 C   s  |j }i }tdd }|jD ]}d }	|jdkrlt|j\}
}t|t||
 |
|}	t|	|	|jd }nv|jdkrt
||j|}||j \}}t||||}	|| |j }|| |j  d7  < t|||j||	}	t|	|	|jd }n|jdkr:||j \}}t||j||}	t||||	}	t|	|	|jd }n|jdkrt||j rXqt|t||j |j|}	||j \}}t|\}}|| | }|| |  d7  < t|||||	}	t|	|	|jd }|||j _nd }|||j< q|S )Nc                   S   s   t tS r(   )r   intr-   r-   r-   r.   <lambda>w       z&generate_qconfig_map.<locals>.<lambda>Zget_attrcall_functionr1   Zcall_methodr0   )global_qconfigr   r7   r8   r   r9   r   r?   r   r>   r   namer    r   r,   )rD   rA   rE   r"   rF   rK   Zqconfig_mapZ#submodule_to_object_type_to_cur_idxrB   r,   r*   _Zqconfig_with_device_checkZfunction_qconfigmodule_pathmodule_typer%   parent_namer-   r-   r.   r   g   s    	

 
  
                  
   )config_dictallowed_keys	dict_namer'   c                 C   s>   |   D ]0}||krtd| d t| d | d qdS )z Checks if the given config_dict has the correct keys

    Args:
      `config_dict`: dictionary whose keys we want to check
    z	Expected z to have the following keys: z. But found 'z
' instead.N)keys
ValueErrorr:   )rQ   rR   rS   kr-   r-   r.   r      s    
)prepare_qconfig_mappingconvert_qconfig_mappingc              
   C   s   t | j|jstd| j| j| jg}|j|j|jg}tttg}t	t
|D ]}||  D ]z\}}||| kstd|| ||| | dks\t || | || | s\td|| ||| | || | q\qLdS )a   Compare the qconfig_mapping passed in convert to the one from prepare and check the values

    Args:
      `prepare_qconfig_mapping`: configuration for prepare quantization step
      `convert_qconfig_mapping`: configuration for convert quantization step
    zWExpected global qconfigs to be the same in the prepare and convert quantization configszZMissing key {} {} in convert QConfigMapping                 when it was present in prepareNz{Expected convert QConfigMapping to have the same qconfig as prepare for key {} {};                 prepare: {}; convert: {})r   rK   AssertionErrorr3   Zmodule_name_qconfigsZmodule_name_regex_qconfigsr   r   r   ranger4   r)   format)rW   rX   Zprepare_dictsZconvert_dictsZ
dict_namesirL   r,   r-   r-   r.   r      s8    	
   
 
)r,   dtype_configsc                 C   s   |D ]}|j }|d krd}|jp$tj}|jp0tj}|jp<tj}|jpHtj}t| \}}	}
|tjkrv|	tjkrv|svtjntj}|r||
ko|tjko||	k}n ||ko||ko||	ko||k}|r dS qdS )NFT)	
is_dynamicinput_dtypetorchfloatweight_dtype
bias_dtypeoutput_dtyper   Zfloat16)r,   r]   Zdtype_configr^   r_   rb   rc   rd   Zqconfig_activation_dtypeZqconfig_weight_dtypeZqconfig_compute_dtypeZqconfig_bias_dtypeZis_matchr-   r-   r.   r      sD    )2r`   collectionsr   r   typingr   r   r   r   r   r	   Ztorch.ao.quantizationr
   Ztorch.ao.quantization.qconfigr   r   r   Ztorch.ao.quantization.quantizer   Z$torch.ao.quantization.backend_configr   Ztorch.fxr   Ztorch.fx.graphr   Ztorch.nn.intrinsicr   utilsr   r   r"   r   r   r   r   Zqconfig_mapping_utilsr   r   __all__r:   rG   r    r!   nnModuler?   r   r   r   r   r-   r-   r-   r.   <module>   sN    & 
W