U
    Ò9%e­J  ã                	   @   s˜   d dl Z d dlmZ d dlmZmZ d dlZddgZeddƒZej	edd	d
ƒej
edd	dƒejedd	dƒiZG dd„ dejƒZdejeedœdd„ZdS )é    N)Ú
namedtuple)ÚAnyÚOptionalÚSparseSemiStructuredTensorÚto_sparse_semi_structuredÚ_SEMI_STRUCTURED_SPARSE_CONFIGz$compression_factor min_rows min_colsé
   é    é€   é	   é@   c                   @   s®   e Zd ZdZdZdZdZedee	j
 ee	j ee	j
 edœdd„ƒZedd„ ƒZdee	j
 ee	j ee	j
 edd	œd
d„Zedœdd„Ze	jjZeedœdd„ƒZdd„ ZdS )r   aÇ  This class implementes semi-structured sparsity as a Tensor subclass.

    Semi-structured sparsity describes a sparsity pattern where n in every 2n elements are sparse,
    depending on the datatype. It is also referred to as 2:4 sparsity or fine-grained
    structured sparsity.

    Currently, this class supports 2:4 sparsity for int8, float16 and bfloat16 dtypes.
    We also support 1:2 sparsity for float32 dtype.

    This subclass stores the dense tensor in a compressed form by only storing the specified elements and corresponding metadata.
    These two are stored next to each other in one contiguous tensor.

    We choose to store the specified elements and the metadata in a single tensor for compatibilty with cuSPARSELt,
    which expects the data to be stored in this format.

    compressed tensor = [ specified elements of original tensor | metadata ]

    For an original tensor of size (m, k) we expect the first m * k // 2 elements to be the kept elements
    The rest of the tensor is metadata.

    The subclass supports two backend, either CUTLASS or cuSPASRELt.

    When _FORCE_CUTLASS is set, or when cuSPARSELt is not available, this subclass calls into _sparse_semi_structured_linear
    and sparse_semi_structured_from_dense for conversion to the compressed format.

    When PyTorch is compiled with cuSPARSELt support, this subclass will call into _cslt_sparse_mm for sparse mm and
    _cslt_compress to convert into the compressed format.
    FN)Úoriginal_tensorÚoriginal_shapeÚcompressed_tensorÚ
transposedc                 C   s~   | j st dt¡ d| _ |dk	r,|}|j}n|dk	r:|}ntdƒ‚i }|j|d< |j|d< |j|d< d|d	< t	j
j| |f|ŽS )
a  
        Create a new instance of the class.

        When original_tensor is passed in, we compress it and store the compresed representation.
        We can also create new instance of the class from the compressed representation without the original tensor.

        Args:
            original_tensor: The original dense tensor, or None, if we have already compressed the tensor.
            original_shape: The shape of the original dense tensor
            compressed_tensor: A flattened tensor to store the specified elements and metadata.
            transposed: Whether the tensor is transposed or not.

        Returns:
            torch.Tensor: A torch.Tensor wrapper subclass.

        Raises:
            ValueError: If both original_tensor and compressed_tensor are None.

        zøThe PyTorch API of SparseSemiStructuredTensor is in prototype stage and will change in the near future. Please open a Github issue for features requests and see our documentation on the torch.sparse module for further information about the project.TNz4Both compressed_tensor and original_tensor are None!ÚdeviceÚdtypeÚlayoutFZrequires_grad)Ú_WARNING_SHOWNÚwarningsÚwarnÚUserWarningÚshapeÚ
ValueErrorr   r   r   ÚtorchÚTensorZ_make_wrapper_subclass)Úclsr   r   r   r   Zprevious_tensorÚkwargs© r   ú[/var/www/html/Darija-Ai-API/env/lib/python3.8/site-packages/torch/sparse/semi_structured.pyÚ__new__:   s$    ù	


z"SparseSemiStructuredTensor.__new__c                 C   s:   | t jkrt jS | t jt jfkr&t jS td| › dƒ‚d S )Nz	Datatype z  is not supported!)r   Úint8Zint32Úfloat16Úbfloat16Zint16ÚRuntimeError)Zvalues_dtyper   r   r   Z__get_indices_dtypeq   s    
z.SparseSemiStructuredTensor.__get_indices_dtype)r   r   r   r   Úreturnc                 C   sf  |dk	rP|j s"td|j› dƒ‚| ¡ dkrBtd| ¡ › dƒ‚|jtkr^td|j› dƒ‚|j\}}t|j j}t|j j}||k s || s ||k s || r²td	|j› d
ƒ‚| j	rF| 
¡ }	t|j j}
|	|
 d }tj|f|j|jd}ddlm} ||ƒ\}}| d¡|d|| d …< | |j¡ d¡||| d d…< n
t |¡}d| _|| _|| _dS )a   SparseSemiStructuredTensor constructor.

        Args:
            original_tensor: The original dense tensor, or None, if we have already compressed the tensor.
            original_shape: The shape of the original dense tensor
            compressed_tensor: A flattened tensor to store the specified elements and metadata.
            transposed: Whether the tensor is transposed or not.

        Returns:
            None

        Raises:
            RuntimeError: If original_tensor is not a supported dtype, dim, shape, or device.
        NzError original_tensor.device= z= is not supported! Only CUDA tensors are currently supported.é   zError original_tensor.dim = z; is not supported! Only 2d tensors are currently supported.zError original_tensor.dtype zZ is not a supported dtype! dtype must be one of: {_DTYPE_TO_SEMI_STRUCTURED_SPARSE_CONFIG}zError original_tensor.shape zj is not supported! Both dimensions must be larger or equal than and a multiple of ({min_rows}, {min_cols})é   )r   r   r   )Ú!sparse_semi_structured_from_denseéÿÿÿÿ)Zis_cudar$   r   Údimr   Ú'_DTYPE_TO_SEMI_STRUCTURED_SPARSE_CONFIGr   Úmin_rowsÚmin_colsÚ_FORCE_CUTLASSZnelementÚcompression_factorr   ÚemptyÚ)torch.sparse._semi_structured_conversionsr(   ÚviewZ_cslt_compressr   r   r   )Úselfr   r   r   r   ÚmÚnr,   r-   Zoriginal_sizer/   Zcompressed_sizer(   ÚsparseÚmetar   r   r   Ú__init__{   sZ    
ÿÿ
ÿ
ÿÿ ÿÿýÿ
z#SparseSemiStructuredTensor.__init__)r%   c              	   C   s*   d| j › d| j› d|  ¡ › d|  ¡ › d	S )zžReturn string representation of SparseSemiStructuredTensor

        Returns:
            str: String representation

        Raises:
            None
        z!SparseSemiStructuredTensor(shape=z, transposed=zvalues=z	metadata=ú))r   r   ÚvaluesÚindices)r3   r   r   r   Ú__repr__Û   s    
(ÿz#SparseSemiStructuredTensor.__repr__c                 C   sâ  |t jjjjkr8t|d j|d j|d j|d j	dS |t jjj
jkrrt|d j|d j|d j|d j	 dS |t jjjjkrÒ|\}}}t|| ƒrÒ|j	rÒ| jr¼t j|| ¡ | ¡ |dS t  |j|j|¡ 
¡ S |t jjjjkr€|\}}t|| ƒr8|j	s8| jr&t  | 
¡ | ¡ | ¡ ¡ 
¡ S t  |j|d¡S nHt|| ƒr€|j	r€| jrjt  || ¡ | ¡ ¡S t  |j|jd¡ 
¡ S |t jjjjkr|\}}	}|j}
t|	| ƒr| jrÐt j||	 ¡ |	 ¡ |dS t  |	j| d|
d ¡ 
¡ |¡ 
¡ j|
dd… džŽ S |t jjjjkrP|d j\}}|| d }|d jd|…  ||d ¡S |t jjjjkr°|d j\}}|| d }|d j|d…  |d¡}t |d j¡}| |¡S d d|› d	gd
d„ t|ƒD ƒ ¡}t|ƒ‚dS )a‡  Overload __torch_dispatch__ to use torch._sparse_semi_structured_linear.

        `torch.structured_sparse_linear` uses accelerated sparse CUTLASS kernels.
        In the future we plan to also add in support for cuSPARSELt kernels.

        Args:
            func: The function being dispatched.
            types: The types of the arguments.
            args: The arguments passed to the function.
            kwargs: The keyword arguments passed to the function.

        Returns:
            Any: The result of the dispatched operation.

        Raises:
            NotImplementedError: If the dispatched operation is not implemented.
        r   )r   r   r   )ÚbiasNr)   r&   Ú
zfunc z with args: c                 S   s    g | ]\}}d |› d|› ‘qS )Úargz: r   )Ú.0Úir?   r   r   r   Ú
<listcomp>j  s     zASparseSemiStructuredTensor.__torch_dispatch__.<locals>.<listcomp>)r)   )r   ZopsZatenÚdetachÚdefaultr   r   r   r   r   ÚtZaddmmÚ
isinstancer.   Z_sparse_semi_structured_linearr:   r;   Z_cslt_sparse_mmÚTÚmmZlinearr2   Ú._SparseSemiStructuredTensor__get_indices_dtyper   ÚjoinÚ	enumerateÚNotImplementedError)r   ÚfuncÚtypesÚargsr   r=   Zinput_AZinput_BZinput_tensorÚweightr   r4   ÚkZnum_kept_elementsÚmetadataÚindices_dtypeZerror_stringr   r   r   Ú__torch_dispatch__í   s°    ü

ü
   ÿ  ÿ  ÿ  ÿ  ÿ
üý
  üÿ
ÿÿz-SparseSemiStructuredTensor.__torch_dispatch__c                 C   sx   | j d krtdƒ‚| j\}}t | j¡}ddlm} || j d || d …  |d¡| j || d d …  |¡ |d¡ƒS )Nz6Compressed tensor is not set, cannot convert to dense!r   )Úsparse_semi_structured_to_denser&   r)   )	r   r$   r   r   rI   r   r1   rU   r2   )r3   r4   r5   rS   rU   r   r   r   Úto_densen  s    

"þz#SparseSemiStructuredTensor.to_dense)NNF)NNF)Ú__name__Ú
__module__Ú__qualname__Ú__doc__Z_FUSE_TRANSPOSEr.   r   Ústaticmethodr   r   r   ÚSizeÚboolr    rI   r8   Ústrr<   Z_CZ_disabled_torch_function_implZ__torch_function__Úclassmethodr   rT   rV   r   r   r   r   r      s@      ûû6
   ûú` F)r   r   r%   c                 C   s   t | | j|dS )a 	  
    This function converts a dense tensor into a sparse semi-structured tensor.
    It will return a SparseSemiStructuredTensor, a subclass of torch.Tensor.

    This function will check to ensure the dense tensor has the right dtype, size, dims, and device.
    We currently only support semi-structured sparse tensors for 2d CUDA tensors.
    Additionally, your tensor must be a positive multiple of a block size given the dtype

    - torch.float16  (r, c) must be >= and a multiple of 64
    - torch.int8     (r, c) must be >= and a multiple of 128

    Args:
        original_tensor (Tensor): the dense tensor to convert
        transposed (bool, optional): whether the dense tensor is transposed

    Returns:
        SparseSemiStructuredTensor: A sparse semi-structured tensor created from the given original_tensor

    Raises:
        None
    Example:
        >>> # xdoctest: +REQUIRES(env:TORCH_DOCTEST_CUDA)
        >>> A = torch.Tensor([0, 0, 1, 1]).tile((128, 32)).half().cuda()
        tensor([[0., 0., 1.,  ..., 0., 1., 1.],
                [0., 0., 1.,  ..., 0., 1., 1.],
                [0., 0., 1.,  ..., 0., 1., 1.],
                ...,
                [0., 0., 1.,  ..., 0., 1., 1.],
                [0., 0., 1.,  ..., 0., 1., 1.],
                [0., 0., 1.,  ..., 0., 1., 1.]], device='cuda:0', dtype=torch.float16)
        >>> A_sparse = to_sparse_semi_structured(A)
        SparseSemiStructuredTensor(shape=torch.Size([128, 128]), transposed=False, values=tensor([[1., 1., 1.,  ..., 1., 1., 1.],
                [1., 1., 1.,  ..., 1., 1., 1.],
                [1., 1., 1.,  ..., 1., 1., 1.],
                ...,
                [1., 1., 1.,  ..., 1., 1., 1.],
                [1., 1., 1.,  ..., 1., 1., 1.],
                [1., 1., 1.,  ..., 1., 1., 1.]], device='cuda:0', dtype=torch.float16),
            metadata=tensor([[-4370, -4370, -4370,  ..., -4370, -4370, -4370],
                [-4370, -4370, -4370,  ..., -4370, -4370, -4370],
                [-4370, -4370, -4370,  ..., -4370, -4370, -4370],
                ...,
                [-4370, -4370, -4370,  ..., -4370, -4370, -4370],
                [-4370, -4370, -4370,  ..., -4370, -4370, -4370],
                [-4370, -4370, -4370,  ..., -4370, -4370, -4370]], device='cuda:0',
       dtype=torch.int16))
    )r   r   )r   r   )r   r   r   r   r   r     s    3)F)r   Úcollectionsr   Útypingr   r   r   Ú__all__r   r!   r"   r#   r+   r   r   r]   r   r   r   r   r   Ú<module>   s4   þ ÿ 
 
 
ý	  k þý