o
    i                  	   @   sd   d dl Z d dlmZ g dZdd Zdd ZG dd	 d	eZ	
	dde jdedede jfddZ	dS )    N)UniformQuantizationObserverBase)create_block_sparse_tensorcreate_semi_structured_tensorPerChannelNormObservermask_creatorc                 C   sp   |dkr|dksJ dt t j| | || fd| |d}t j||dd}t j||dd}||  S )N      ?g        z*sparsity should be a value between 0 and 1   )dtyper   dim)torch	bernoullifullrepeat_interleaveto
contiguouscuda)MN	blocksizesparsityr	   A r   J/home/ubuntu/.local/lib/python3.10/site-packages/torchao/sparsity/utils.pyr      s   r   c                 C   sd   t dd| | d f }t jjj|dd| | t j	}|t 
| | |  }||S )z
    This function returns a 1:2 sparse matrix of size (r, c).
    Note that this means this matrix will also be 2:4 and 4:8 sparse as well.
    r      )num_classes)r   randintr   nn
functionalone_hotreshaper   r   int32rand)rcr	   choice_indicesmasksparse_weightr   r   r   r      s   	
r   c                       s2   e Zd ZdZd
 fddZdd Zdd	 Z  ZS )r   z`
    A custom observer that computes the L2 norm of each channel and stores it in a buffer.
    returnNc              
      sJ   t  jdtjtjdd d ttjjd| d| _| 	dt
g  d S )NF)r	   qschemereduce_range	quant_min	quant_maxepsr   normr   )super__init__r   quint8per_channel_affinefinfofloat32r-   averaging_constantregister_buffertensor)selfkwargs	__class__r   r   r0   8   s   
zPerChannelNormObserver.__init__c                 C   s   |  dkr|S | }dd t| D }|d |d |d< |d< ||}tj|dd}tjj|ddd }| j	  dkrP| j	
|j | j	| |S |  j	|7  _	|S )	Nr   c                 S   s   g | ]}|qS r   r   ).0ir   r   r   
<listcomp>O   s    z2PerChannelNormObserver.forward.<locals>.<listcomp>r   )	start_dimr
   r   )numeldetachranger   permuter   flattenlinalgvector_normr.   resize_shapecopy_)r8   x_origxnew_axis_listyr.   r   r   r   forwardI   s   
zPerChannelNormObserver.forwardc                 C   s   t d)Nz>PerChannelNormObserver is designed to store activations only. )NotImplementedError)r8   r   r   r   calculate_qparams_   s   z(PerChannelNormObserver.calculate_qparams)r(   N)__name__
__module____qualname____doc__r0   rO   rQ   __classcell__r   r   r:   r   r   3   s
    r   r      r7   r   r   r(   c                 C   s   d}|   | dkrtd| j d| d|   | }|   ||}tj|dddddt|| f }tj	|j|j
d}|jd|dd	| j}|S )
a  
    Class for creating N:M sparsity masks.
    Masks will be created using the N:M ratio, where for every block of
    M weights, N will be pruned based on ranked weight value. Each mask
    will correspond to the given tensor.
    :param tensor: The input tensor to create a mask for
    :param N: The number of weights in a group to keep
    :param M: The size of a weight group
    :return: A mask tensor with the same shape as the input tensor
    Nr   zTensor of size z can't be evenly divided into z groupsr   r
   )device)r   indexvalue)rA   
ValueErrorrI   rB   absr    r   argsortintonesrX   scatter_)r7   r   r   r&   
num_groupstensor_temprY   w_br   r   r   r   e   s   &r   )r   rW   )
r   torch.ao.quantization.observerr   __all__r   r   r   Tensorr^   r   r   r   r   r   <module>   s"   4