U
    Kc/                     @   sb   d dl Z d dlmZ d dlmZmZ d dlmZmZ ej	ej
hZdd Zd
eej ddd	ZdS )    N)module_to_fqnfqn_to_module)DictListc                 C   s^   g }| g}|rZ|  }| D ]8\}}t| |}t|tkrL|||f q|| qq
|S )z>Fetches Embedding and EmbeddingBag modules from the model
    )popZnamed_childrenr   typeSUPPORTED_MODULESappend)modelembedding_modulesstackmodule_childfqn_name r   f/tmp/pip-unpacked-wheel-gikjz4vx/torch/ao/sparsity/_experimental/data_sparsifier/quantization_utils.py_fetch_all_embeddings   s    
r   T)select_embeddingsc                 K   s\  |f |}|dkrt | }n\g }t|ts2td|D ]@}t|tksNtdt| |}|dk	shtd|||f q6|r|D ]"\}	}
|	dd}|j	||
d q|
  |  |D ]\}}
tjjj|
_qtjj| dd	 tjj| dd	 nf|D ]\}}
tjjj|
_qtjj| dd	 tjj| dd	 i i i i i d
}|D ]\}	}t| |	}|dk	s`t| }| |d |	< | |d |	< t||d |	< | |d |	< |j|d |	< |j	|	dd|d |	 d q@|
  |  |D ]h\}	}t| |	}|dk	sttj|d |	 |d |	 |d |	 |d |	 |d |	 d}|| qdS )a  Takes in a model and applies sparsification and quantization to only embeddings & embeddingbags.
    The quantization step can happen before or after sparsification depending on the `sparsify_first` argument.

    Args:
        - model (nn.Module)
            model whose embeddings needs to be sparsified
        - data_sparsifier_class (type of data sparsifier)
            Type of sparsification that needs to be applied to model
        - sparsify_first (bool)
            if true, sparsifies first and then quantizes
            otherwise, quantizes first and then sparsifies.
        - select_embeddings (List of Embedding modules)
            List of embedding modules to in the model to be sparsified & quantized.
            If None, all embedding modules with be sparsified
        - sparse_config (Dict)
            config that will be passed to the constructor of data sparsifier object.

    Note:
        1. When `sparsify_first=False`, quantization occurs first followed by sparsification.
            - before sparsifying, the embedding layers are dequantized.
            - scales and zero-points are saved
            - embedding layers are sparsified and `squash_mask` is applied
            - embedding weights are requantized using the saved scales and zero-points
        2. When `sparsify_first=True`, sparsification occurs first followed by quantization.
            - embeddings are sparsified first
            - quantization is applied on the sparsified embeddings
    Nz9the embedding_modules must be a list of embedding moduleszAthe embedding_modules list must be an embedding or embedding bagsz1the embedding modules must be part of input model.r   )namedataT)Zinplace)scaleszero_pointsdequant_weightsaxisdtyper   r   r   r   r   )r   r   r   r   )r   
isinstancer   AssertionErrorr   r   r   r	   replaceZadd_datastepZsquash_masktorchZaoZquantizationZ!float_qparams_weight_only_qconfigZqconfigprepareconvertr   ZweightZq_per_channel_scalesZq_per_channel_zero_pointsZ
dequantizeZq_per_channel_axisr   Zquantize_per_channelZ
set_weight)r
   Zdata_sparsifier_classZsparsify_firstr   Zsparse_configZdata_sparsifierr   Zembr   r   Z
emb_moduleZ
valid_namer   Zquantize_paramsZquantized_embZquantized_weightZrequantized_vectorr   r   r   post_training_sparse_quantize   sf     


 
"




r$   )TN)r!   Ztorch.nnnnZ"torch.ao.sparsity.sparsifier.utilsr   r   typingr   r   Z	EmbeddingZEmbeddingBagr   r   Moduler$   r   r   r   r   <module>   s     