o
    iC                     @   s  d dl Z d dlZd dlZd dlZd dl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 d dlZd dlm  m  mZ d dlmZ g dZe jdejjd	efd
dZdvddZdd Zdd Zdd Zdd Zdejdejd	ejfddZdd Z de!de!d	e!fdd Z"dwd"d#Z#d$d% Z$dxd'd(Z%G d)d* d*ejjZ&dyd+d,Z'd-ej(d	e)fd.d/Z*d0d1 Z+d2d3 Z,d4d5 Z-	 d6d7 Z.d8d9 Z/d:d; Z0d<d= Z1dzd>d?Z2d@dA Z3dBedCefdDdEZ4dBedCed	efdFdGZ5dHdI Z6G dJdK dKejZ7dLdM Z8dNdO Z9dPdQ Z:dRdS Z;dTdU Z<dVe!dWe!d	e)fdXdYZ=dZd[ Z>d\d] Z?d^d_ Z@dVe!dWe!d	e)fd`daZAd{dcddZBd|dfdgZCdhdi ZDdje!dke!d	e!fdldmZEdneFdoeFfdpdqZGdrds ZHG dtdu duejjZIdS )}    Nreduce)versiongcd)AnyCallableOptional)return_and_correct_aliasing)benchmark_modelprofiler_runnerget_available_devicesget_compute_capability(benchmark_torch_function_in_microsecondsfind_multiple_register_custom_opget_model_size_in_bytesunwrap_tensor_subclassTorchAOBaseTensoris_cuda_version_at_leastis_MI300is_sm_at_least_89is_sm_at_least_90is_sm_at_least_100is_package_at_leastDummyModulemodulereturnc                 C   sb   dd |   D dd |  D B }t|dksJ d| t|dkr-tt|}|S d}|S )z
    Returns the unique device for a module, or None if no device is found.
    Throws an error if multiple devices are detected.
    c                 S   s   h | ]}|j qS  device).0pr   r   A/home/ubuntu/.local/lib/python3.10/site-packages/torchao/utils.py	<setcomp>0       z0_assert_and_get_unique_device.<locals>.<setcomp>   zKprepare only works with cpu or single-device CUDA modules, but got devices r   N)
parametersbufferslennextiter)r   devicesr    r   r   r#   _assert_and_get_unique_device*   s   r-   r   c              	   C   s  |du ri }|du rt | tjjsJ dt| j}|dkrjtj  tjjdd}tjjdd}|	  t
|D ] }tjjd | |i | W d   n1 sTw   Y  q9|	  tj  ||| S |dkrtj  tjjjdd}tjjjdd}|	  t
|D ] }tjjd | |i | W d   n1 sw   Y  q|	  tj  ||| S |dkrtj  t }t
|D ] }tjjd | |i | W d   n1 sw   Y  qt }	tj  |	| | }
|
S |d	krRtj  tjjdd}tjjdd}|	  t
|D ]"}tjjd | |i | W d   n	1 s;w   Y  q|	  tj  ||| S dS )
z?Benchmark model runs with `args` and `kwargs` both are optionalNzFExpecting `model` to be torch.nn.Module if device_type is not providedcudaT)enable_timingztimed regionmpscpuxpu)
isinstancetorchnnModuler-   typer.   synchronizeEventrecordrangeautogradprofilerrecord_functionelapsed_timer0   eventr1   timer2   )modelnum_runsargskwargsdevice_typestart_event	end_event_
start_timeend_timeaverage_time_per_runr   r   r#   r   <   sv   









r   c                 O   s\   t jjt jjjt jjjgdd}||i |}W d    n1 s"w   Y  ||  |S )NT)
activitiesrecord_shapes)r4   r=   profileProfilerActivityCPUCUDAexport_chrome_trace)pathfnrD   rE   profresultr   r   r#   r      s   
r   c                  C   sH   dg} t j r| d n
t j r| d t j r"| d | S )Nr1   r.   r2   r0   )r4   r.   is_availableappendr2   r0   )r,   r   r   r#   r      s   




r   c                   C   s   t j sJ t j S N)r4   acceleratorrX   current_acceleratorr   r   r   r#   get_current_accelerator_device   s   
r]   c                  C   s2   t j rt j } t| d  d| d  S dS )Nr   .r&   g        )r4   r.   rX   get_device_capabilityfloat)
capabilityr   r   r#   r      s   

r   output
output_refc                 C   s$   t t | | t t | S rZ   )r4   meanabs)rb   rc   r   r   r#   compute_max_diff   s   rf   c                 O   sV   dd l m  m} | |i | | |i | |jd||| dd}| }|jd S )Nr   zf(*args, **kwargs))rD   rE   f)stmtglobalsg    .A)torch.utils.benchmarkutils	benchmarkTimerblocked_autorangerd   )rg   rD   rE   rl   t0measurementr   r   r#   r      s   

r   nrD   c                 G   s2   t dd |d }| | dkr| S | | | |  S )Nc                 S   s   | | t | | S rZ   r   )xyr   r   r#   <lambda>   r%   zfind_multiple.<locals>.<lambda>)r&   r   r   )rq   rD   kr   r   r#   r      s   r   Tc                    s.   ddl m r
dnd  fdd}|S )a  This decorator is used to preserve some high level operators for torch.export.export
    while still allow them to be decomposed for inductor path

    requirement: make sure `fn.__name__[1:]` is the operator name you want to register

    NOTE: This should be applied at the top, after all other decorators have been applied
    NOTE: We haven't tested the case when `fn` accepts tensor subclass instance as input,
    e.g. uint4 tensor subclass instance, and we'll probably need to figure out what would make
    sense for downstream system (like executorch) to accept as well

    Example:
        lib = torch.library.Library("my_namespace', "FRAGMENT")

        register_custom_op = _register_custom_op(lib)

        @register_custom_op
        def _the_op_that_needs_to_be_preserved(...)
            ...

        # after this, `_the_op_that_needs_to_be_preserved` will be preserved as
        # torch.ops.my_namespace.the_op_that_needs_to_be_preserved operator after
        # torch.export.export

    r   )register_decompositionCompositeImplicitAutogradCompositeExplicitAutogradc                    s   ddl m} t fdddD rJ d j  j}|d dkr(|dd  }|| i d	 }| |  j}tttj	||}rQ|g  |S )
Nr   )infer_schemac                 3   s    | ]}| j v V  qd S rZ   )__name__)r!   crU   r   r#   	<genexpr>   s    z9_register_custom_op.<locals>.decorator.<locals>.<genexpr>z.<>zEExpecting op to be defined in normal functions, not lambda or local: rI   r&   )mutates_args)
torch._library.infer_schemary   anyrz   defineimplnsgetattrr4   ops)rU   ry   op_nameschemalib_namespaceopdispatch_keyinductor_decomposedlibrv   r|   r#   	decorator   s   

z&_register_custom_op.<locals>.decorator)torch._inductor.decompositionrv   )r   r   r   r   r   r#   r      s   r   c                    s    fdd}|S )Nc                    s     | d}|S )NMeta)r   )rU   r   r   r   r   r#   r      s   z$_register_meta_op.<locals>.decoratorr   )r   r   r   r   r   r#   _register_meta_op   s   r   Fc                    st    fdd d}|   D ]+\}}t|tjjr|s7t|jdd|jddD ]}| |7 }q'|t	||7 }q|S )z
    Returns the model size in bytes. The option to ignore embeddings
    is useful for models with disproportionately large embeddings compared
    to other model parameters that get quantized/sparsified.
    c                    sJ   t | drd}|  d D ]}t| |}| |7 }q|S |  |   S )N__tensor_flatten__r   )hasattrr   r   numelelement_size)tensorsize	attr_name
sub_tensor	flat_sizer   r#   r   	  s   

z*get_model_size_in_bytes.<locals>.flat_sizer   F)recurse)
named_childrenr3   r4   r5   	Embedding	itertoolschainr'   r(   r   )rB   ignore_embeddings
model_sizenamechildr"   r   r   r#   r     s   r   c                   @   s   e Zd Zdd Zdd ZdS )UnwrapTensorSubclassc                 G   s   t |}t| jD ]+\}}}t|}dd t||| d  D }||d  }|||d d }|| q	t|dks=J |d S )Nc                 S   s   i | ]\}}||qS r   r   )r!   abr   r   r#   
<dictcomp>%  s    z0UnwrapTensorSubclass.forward.<locals>.<dictcomp>r&   r   )listreversedrebuild_stackr)   zip__tensor_unflatten__rY   )selftensorstodotpmetainner_tensors	nb_tensorrebuiltr   r   r#   forward!  s   zUnwrapTensorSubclass.forwardc           
      C   s   t |tjus	J g }g }|g}|rL| }| \}}|t |||f |D ]!}t||}	t |	tju r<||	 q(t|	tjsDJ ||	 q(|s|| _|S rZ   )	r7   r4   Tensorpopr   rY   r   r3   r   )
r   r   r   plain_tensorsr   objr   metadatar   valr   r   r#   right_inverse-  s"   
z"UnwrapTensorSubclass.right_inverseN)rz   
__module____qualname__r   r   r   r   r   r#   r      s    r   c                 C   s   |   D ]O\}}t|tjjst|tjjrOt|drOt|jtj	urOt|jtjj
urOt|jtj	rOtt|jtj	rOt|jtrOt|sOt|dt  t| q| S )a5  Unwraps (nested) tensor subclass in the model to plain tensors
    This is a workaround to make a model with tensor subclass to work with `torch.export.export`
    and `torch.aot_compile`, we hope this can be integrated into compile stack soon
    tracking issue: https://github.com/pytorch/ao/issues/345
    weight)r   r3   r4   r5   Linearr   r   r7   r   r   	Parameter
issubclassr   parametrizeis_parametrizedregister_parametrizationr   r   )rB   	filter_fnr   r   r   r   r#   r   C  s,   

r   dtypec                 C   s   t jt jt jt jh}| |v S rZ   )r4   float8_e4m3fnfloat8_e4m3fnuzfloat8_e5m2float8_e5m2fnuz)r   	fp8_typesr   r   r#   _is_float8_type_  s   r   c                 C   sT   t td| }td| }|r#tt| \}}}|rd}|||gS td|  )z
    Parse version string representing pre-release with -1

    Examples: "2.5.0.dev20240708+cu121" -> [2, 5, -1], "2.5.0" -> [2, 5, 0]
    z	(git|dev)z(\d+)\.(\d+)\.(\d+)zInvalid version string format: )boolresearchmatchmapintgroups
ValueError)version_stringis_prereleaser   majorminorpatchr   r   r#   parse_versioni  s   
r   c                   C   s   t tjd S )Ngit_version)r   r4   r   r   r   r   r#   	is_fbcode{     r   c                 C   s   t  rdS ttjt| kS )NT)r   r   r4   __version__)min_versionr   r   r#   torch_version_at_least  s   r   c                    sJ   t dsi _jvri j< t ttfs g  fdd}|S )a|  Decorator for implementing aten ops like `torch.ops.aten.linear.default` for
    tensor subclass, the implemented functions are called in ``__torch_dispatch__`` callback
    for ``torch.Tensor`` subclasses

    Examples::

        implements = MyTensor.implements

        @implements(torch.ops.aten.linear.default):
        def _(func, types, args, kwargs):
            ...

    _ATEN_OP_TABLEc                    s2    D ]}t | | fdd}|j |< q| S )Nc                 S      || |||S rZ   r   rg   typesrD   rE   _funcr   r   r#   wrapper     z/_implements.<locals>.decorator.<locals>.wrapper)	functoolswrapsr   )funcr   r   aten_opsclsr   r#   r     
   z_implements.<locals>.decorator)r   r   r3   r   tuple)r   r   r   r   r   r#   _implements  s   



r   c                    sJ   t  dsi  _  jvri  j < tttfsg fdd}|S )a  Decorator for implementing torch functions / ops
    like ``torch.nn.functional.linear``, ``torch.Tensor.t`` for the tensor subclass
    the implemented functions are called in ``__torch_function__`` callback
    for ``torch.Tensor`` subclasses

    Examples::

        implements_torch_function = MyTensor.implements_torch_function

        @implements_torch_function(torch.nn.functional.linear):
        def _(func, types, args, kwargs):
            ...

    _TORCH_FN_TABLEc                    s2   D ]}t | | fdd}| j  |< q| S )Nc                 S   r   rZ   r   r   r   r   r#   r     r   z>_implements_torch_function.<locals>.decorator.<locals>.wrapper)r   r   r   )r   rU   r   r   	torch_fnsr   r#   r     r   z-_implements_torch_function.<locals>.decorator)r   r   r3   r   r   )r   r   r   r   r   r#   _implements_torch_function  s   



r   c                    s   | j }| j}tjj}|tjjjjdd }|tjdd }|tjj	gdd }||j
j|jj|jj|j	jgdd }dtdtdtfd	d
 ||jj fdd}||jjdd }d S )Nc                    s   t |dksJ |d }| D ]}|dv sJ qd|v r&|d |jks&J d|v r3|d |jks3J |d  |jkr?|S |d  fdd}t|||S )	Nr&   r   )r   layoutr    r   r   r    c                    s   |  dS )Nr   r   rr   r    r   r   r#   rt     s    :_implements_common_tensor_ops.<locals>._.<locals>.<lambda>)r)   keysr   r   getr    _apply_fn_to_datar
   )r   r   rD   rE   r   ru   
new_tensorr   r   r#   rI     s   

z(_implements_common_tensor_ops.<locals>._c                 S   s<   t |dksJ t|d t|d ko|d j|d jkS )N   r   r&   )r)   r7   shaper   r   rD   rE   r   r   r#   rI     s   ,c                    s    d   fddS )Nr   c                       | g dd  R i S Nr&   r   r   rD   r   rE   r   r#   rt         r   )r   r  r   r  r#   rI     s   c              	      s$   t   d  fddS )Nr   c                    r  r  r   r   r  r   r#   rt   
  r  r   )r
   r   r  r   r  r#   rI     s   	r   srcr   c                    s   t  fdd jD }d}t dr!t  fdd jD }t  fdd jD }d}t drBt  fdd jD }t tkoW jjkoW|oW|oW|oW|S )	Nc                 3   s(    | ]}t  |jt |jkV  qd S rZ   r   r  r!   t_namer   r  r   r#   r}     s
    
zH_implements_common_tensor_ops.<locals>._same_metadata.<locals>.<genexpr>Toptional_tensor_data_namesc                 3   sD    | ]}t  |d urt  |jt |jknt |d u V  qd S rZ   r	  r
  r  r   r#   r}     s    
c                 3   $    | ]}t  |t |kV  qd S rZ   r   r!   a_namer  r   r#   r}     
    
optional_tensor_attribute_namesc                 3   r  rZ   r  r  r  r   r#   r}   %  r  )alltensor_data_namesr   r  tensor_attribute_namesr  r7   r  )r   r  _tensor_shape_match_optional_tensor_shape_match_attr_match_optional_attr_matchr   r  r#   _same_metadata  s6   
	

z5_implements_common_tensor_ops.<locals>._same_metadatac                    sd   |d }|d } ||r%|  d }|D ]}t||t|| qd S td|d |d f )Nr   r&   z7Not supported args for copy_ due to metadata mismatch: )r   r   copy_r   )r   r   rD   rE   r   r  self_tensorstensor_namer  r   r#   rI   3  s   
c                    s  |d t drt drj|dd  i |}|d  fddjD }g }t drNjD ]}t|}|d urH||  q4|d  q4 fd	djD }g }	t d
rk fddj	D }	j
g ||||	R  }
t| |||
S td)Nr   r  r  r&   r    c                    s   g | ]
}t | qS r   )r   tor!   r   r    r   r   r#   
<listcomp>H  s    z<_implements_common_tensor_ops.<locals>._.<locals>.<listcomp>r  c                    "   g | ]}|d krt |n qS r   r  r!   r   r"  r   r#   r#  U      r  c                    r$  r   r  r%  r"  r   r#   r#  [  r&  zSubclasses must implement `aten._to_copy.default` or specify `tensor_data_names` and `tensor_attribute_names` for tensor class or tensor instance before using it)r   _get_to_kwargsr   r  r  r   rY   r   r  r  	__class__r
   NotImplementedError)r   r   rD   rE   r   optional_tensorstensor_data_namemaybe_tensortensor_attributesoptional_tensor_attributestr   r"  r#   rI   @  sJ   




)
implementsimplements_torch_functionr4   r   atenr   dtype_layout!_has_compatible_shallow_copy_typer   
contiguousdetachdefaultclonealiasr   r   r  _to_copy)r   r0  r1  r2  rI   r   r  r#   _implements_common_tensor_ops  s2   




&
r;  c                 C   s   t | dr
t | dsJ tj| | t| dg D ]}|| jvr+t | |s+t| |d  qt| dg D ]}|| jvrDt | |sDt| |d  q2d S )Nr  r  r  r  )r   r4   _utils_set_obj_stater   __dict__setattr)r   stateoptional_tensor_data_nameoptional_tensor_attribute_namer   r   r#    _torchao_base_tensor__setstate__m  s&   rC  c                 C   s   |du ri n|}t | dr%| | jv r%|| j|  v r%| j|  | ||||S tj  ||i |W  d   S 1 s<w   Y  dS )a  Use this util function for a common `__torch_function__` implementation
    that dispatches to ops/functions registered with `_implements`

    class MyTensor(torch.Tensor):
        ...
        __torch_function__ = classmethod(_dispatch__torch_function__)
    Nr   )r   r   r4   _CDisableTorchFunctionSubclass)r   r   r   rD   rE   r   r   r#   _dispatch__torch_function__  s   
$rF  c              
   C   s   t | dr| | jv r|| j|  v r| j|  | ||||S tdd |D }dd | D }t| j d|d|d|d	|	)
a  Use this util function for a common `__torch_dispatch__` implementation
    that dispatches to ops/functions registered with `_implements`

    class MyTensor(torch.Tensor):
        ...
        __torch_dispatch__ = classmethod(_dispatch__torch_dispatch__)
    r   c                 s   s    | ]}t |V  qd S rZ   r7   r!   argr   r   r#   r}     s    z._dispatch__torch_dispatch__.<locals>.<genexpr>c                 S   s   i | ]	\}}|t |qS r   rG  )r!   ru   rI  r   r   r#   r     s    z/_dispatch__torch_dispatch__.<locals>.<dictcomp>zC dispatch: attempting to run unimplemented operator/function: func=z, types=z, arg_types=z, kwarg_types=)r   r   r   itemsr)  rz   )r   r   r   rD   rE   	arg_typeskwarg_typesr   r   r#   _dispatch__torch_dispatch__  s   	
 rM  tensor_classlayout_classc                    s"   t dsi _ fdd}|S )a  
    .. deprecated:: 0.15.1
       This method is deprecated as of version 0.15.1 since it's
       part of the older tensor subclass development stack,
       for information about new dev stack, please check
       https://docs.pytorch.org/ao/main/quantization_overview.html
       and https://docs.pytorch.org/ao/main/contributor_guide.html

    Helper function for layout registrations, this is used to implement
    register_layout decorator for each tensor subclass, see aqt.py for example usage

    Args:
        tensor_class: Tensor subclass type
        layout_class: the class type of subclass of `Layout`, e.g. `PlainLayout`

    Returns:
        a decorator that registers the tensor impl constructor in the table
    _LAYOUT_CONSTRUCTOR_TABLEc                    s    | j j < tj | g | S rZ   )
from_plainrP  r4   serializationadd_safe_globals)tensor_impl_classrO  rN  r   r#   r     s   z#_register_layout.<locals>.decorator)r   rP  )rN  rO  r   r   rU  r#   _register_layout  s   
rV  c                 C   s@   t | dstd|  || jvrtd| d|  | j| S )a  
    .. deprecated:: 0.15.1
       This method is deprecated as of version 0.15.1 since it's
       part of the older tensor subclass development stack,
       for information about new dev stack, please check
       https://docs.pytorch.org/ao/main/quantization_overview.html
       and https://docs.pytorch.org/ao/main/contributor_guide.html

    Get TensorImpl class constructor (TensorImplClass.from_plain) for `tensor_class` based on `layout_class`
    `layout_class` means the class type of subclass of `Layout`, e.g. `PlainLayout`

    Args:
        tensor_class: Tensor subclass type
        layout_class: the class type of subclass of `Layout`, e.g. `PlainLayout`

    Returns:
        tensor impl subclass constructor for the layout_class
    rP  z1no registered tensor_impl class constructor for: zlayout_name: z is not supported yet for )r   r   rP  )rN  rO  r   r   r#   _get_tensor_impl_constructor  s   


rW  c                 O   sr   t dd |D }d|v r|d tjjj|i |\}}}}|du r'| jn|}|du r0| jn|}||d}|S )zHelper function to get the device and dtype keyword args for `aten._to_copy.default` op
    only device and dtype are kept

    Returns: {"device": device, "dtype": dtype}
    c                 s   s     | ]}t |tjs|V  qd S rZ   )r3   r4   r   rH  r   r   r#   r}     s    z!_get_to_kwargs.<locals>.<genexpr>r   N)r    r   )r   r   r4   rD  _nn	_parse_tor    r   )r   rD   rE   r    r   rI   r   r   r#   r'    s   
r'  c                   @   s   e Zd ZdZedd ZeeZeeZ	ee
Z
eeZeeZeZeeZeeZdd Zdd Zedd	 Zd
d Zdd Zdd ZdS )r   a  A util tensor subclass that provides commonly used functions
    new tensor subclass can inherit to get all the utility functions

    Attributes (defined by subclass of ``TorchAOBaseTensor``):

    * :attr:`tensor_data_names` (List[str]): list of names of all required tensor_data, order should match
        the `__init__` list of tensor subclass (optional to define to use ``TorchAOBaseTensor``,
        required for getting the util functions been defined (see Note section))

    * :attr:`tensor_attribute_names` (List[str]): list of names of non-``Tensor`` attributes,
        order should match the ``__init__`` list of tensor subclass, following all the ``tensor_data_names`` arguments (optional to define to use ``TorchAOBaseTensor``, required for getting the
        util functions been defined (see Note section))

    * :attr:`optional_tensor_data_names` (List[str]): it's not required to get the
        additional util functions been implemented, but this will be need if there are
        some optional ``Tensor`` data attributes, when defined, this will be a list of names of ``Tensor``s that
        can be optional

    * :attr:`optional_tensor_attribute_names` (List[str]): it's not required to get the
        additional util functions been implemented, but this will be need if there are
        some optional non-``Tensor`` attributes, when defined, this will be a list of names of attributes
        that can be optional

    Note:
        Argument order in ``__init__`` and ``__new__`` of subclass of ``TorchAOBaseTensor`` should match exaclty with ``tensor_data_names`` + ``tensor_attribute_names`` + ``optional_tensor_data_names`` (if present) + ``optional_tensor_attribute_names`` (if present)


    Note:
        If ``tensor_data_names`` (torch.Tensor data attribute names) and ``tensor_attribute_names`` (non-torch.Tensor attribute names) are defined, there are some additional util
        functions that will be added, this includes:

        ``__tensor_flatten__``: flattens a subclassed tensor instance, returns a ``tuple``, first element is tensor data names for valid tensor data, second element is a dict from attribute_name to non-``Tensor`` attributes

        ``__tensor_unflatten__``: takes a ``tensor_data_dict`` (a map from tensor name to ``Tensor``), and list of non-``Tensor`` attributes, returns a new instance of the subclassed tensor

        ``_apply_fn_to_data``: takes a function (``Tensor -> Tensor``),  applies function to all tensor data and recreate a new subclassed Tensor with the transformed tensor data

        ``__repr__``: the string representation of the subclassed tensor instance

        ``_same_metadata``: returns whether the metadata is the same between two instances of cls

        ``__setstate__``: when loading a serialized tensor subclass checkpoints, it sets the new optional tensor and tensor attribute that is saved in the old checkpoint to None, to maintain BC of old checkpoints when we add new optional tensor data or attributes to the tensor subclass

        torch function supported (``__torch_function__``): ``torch.Tensor.contiguous``

        aten ops supported (``__torch_dispatch__``): ``aten.detach.default``, ``aten.clone.default``, ``aten.alias,default``, ``aten.contiguous.default``, ``aten.copy_.default``, ``aten._to_copy.default`` (enables ``t.to``)

    Examples::

        class MyTensor(torch.Tensor):
            tensor_data_names = ["a", "b"]
            tensor_attribute_names = ["c", "d"]
            optional_tensor_data_names = ["e", "f"]
            optional_tensor_attribute_names = ["g", "h"]


            def __new__(
                cls,
                a: Tensor,
                b: Tensor,
                c: int,
                d: str,
                e: Optional[Tensor] = None,
                f: Optional[Tensor] = None,
                g: Optional[int] = None,
                h: Optional[int] = None,
            ):
                pass

            def __init__(
                self,
                a: Tensor,
                b: Tensor,
                c: int,
                d: str
                e: Optional[Tensor] = None,
                f: Optional[Tensor] = None,
                g: Optional[int] = None,
                h: Optional[int] = None,
            ):
                pass

    c                 K   s   d| j vri | _d| j vri | _| | jvri | j| < | | jvr$i | j| < t| dr5t| dr5|   t| _| jD ].}t|dd }|rP||v rP| j|  	||  t|dd }|rf||v rf| j|  	||  q8d S )Nr   r   r  r  )
r>  r   r   r   r;  rC  __setstate__	__bases__r   update)r   rE   parentparent_aten_tableparent_torch_tabler   r   r#   __init_subclass__]  s(   






z#TorchAOBaseTensor.__init_subclass__c                 O   s   t jtt|  d S rZ   )r4   rD  _log_api_usage_oncestrr7   )r   rD   rE   r   r   r#   __init__  s   zTorchAOBaseTensor.__init__c                    s   t  drGt  drG j }t  dr( jD ]}t |}|d ur'|| q fdd jD }t  drC| fdd jD B }||fS td)	Nr  r  r  c                       i | ]}|t  |qS r   r  r!   attrr   r   r#   r     s    z8TorchAOBaseTensor.__tensor_flatten__.<locals>.<dictcomp>r  c                    rd  r   r  re  rg  r   r#   r         
zSubclasses should implement __tensor_flatten__ or specify `tensor_data_names` and `tensor_attribute_names` for tensor class before using it)	r   r  copyr  r   rY   r  r  r)  )r   r  r+  r,  	attr_dictr   rg  r#   r     s*   






z$TorchAOBaseTensor.__tensor_flatten__c           	         s   t | drNt | drNfdd| jD }i }t | dr%fdd| jD } fdd| jD }i }t | d	r@ fd
d| jD }| g ||R i ||S td)Nr  r  c                       g | ]} | qS r   r   r!  tensor_data_dictr   r#   r#        z:TorchAOBaseTensor.__tensor_unflatten__.<locals>.<listcomp>r  c                    s   i | ]	}|  |d qS rZ   )r   )r!   r+  rl  r   r#   r     s    z:TorchAOBaseTensor.__tensor_unflatten__.<locals>.<dictcomp>c                    rk  r   r   r!  r-  r   r#   r#    rn  r  c                    s   i | ]}| | qS r   r   r!  ro  r   r#   r     s    zSubclasses should implement __tensor_unflatten__ or specify `tensor_data_names` and `tensor_attribute_names` for tensor class before using it)r   r  r  r  r  r)  )	r   rm  r-  
outer_sizeouter_striderequired_tensorsoptional_tensor_dictrequired_attributesoptional_attribute_dictr   )r-  rm  r#   r     s:   





z&TorchAOBaseTensor.__tensor_unflatten__c                    s   t dr`t dr` fddjD }i }t dr6jD ]}t|}|d ur1 |||< qd ||< qfddjD }i }t drQfdd	jD }jg ||R i ||S td
)Nr  r  c                    s   g | ]	} t |qS r   r  re  rU   r   r   r#   r#    s    z7TorchAOBaseTensor._apply_fn_to_data.<locals>.<listcomp>r  c                    s   g | ]}t  |qS r   r  re  rg  r   r#   r#    s    
r  c                    rd  r   r  r%  rg  r   r#   r     rh  z7TorchAOBaseTensor._apply_fn_to_data.<locals>.<dictcomp>zSubclasses should implement _apply_fn_to_data or specify `tensor_data_names` and `tensor_attribute_names` for tensor class or tensor instance before using it)r   r  r  r   r  r  r(  r)  )r   rU   rr  rs  r+  r,  rt  ru  r   rv  r#   r     sB   






z#TorchAOBaseTensor._apply_fn_to_datac                 C   s  t | drt | drd}|| jd  dt| | jd  7 }| jdd  D ]}|d| dt| | 7 }q%| jD ]}|d| dt| | 7 }q8t | dr`| jD ]}|d| dt| | 7 }qPt | d	rx| jD ]}|d| dt| | 7 }qh| jj d
| dS td)Nr  r   r   =r&   z, r  r  ()zSubclasses must implement __repr__ or specify `tensor_data_names` and `tensor_attribute_names` for tensor class or tensor instance before using it)	r   r  r   r  r  r  r(  rz   r)  )r   repr_strr+  tensor_attribute_namer   r   r#   __repr__  s.   $




zTorchAOBaseTensor.__repr__c                 C   s   t | dsdS | jS )ax  
        .. deprecated:: 0.15.1
           This method is deprecated as of version 0.15.1 since it's
           part of the older tensor subclass development stack,
           for information about new dev stack, please check
           https://docs.pytorch.org/ao/main/quantization_overview.html
           and https://docs.pytorch.org/ao/main/contributor_guide.html
        _layoutN)r   r~  rg  r   r   r#   
get_layout  s   
	zTorchAOBaseTensor.get_layoutN)rz   r   r   __doc__classmethodr`  r   r0  r   r1  r;  rM  __torch_dispatch__rF  __torch_function__r'  rV  register_layoutrW  get_tensor_impl_constructorrc  r   r   r   r}  r  r   r   r   r#   r     s&    T

#%"r   c                 C   sV   |t | t | krtdt| }tt | |D ]}|||| t |   q|S )a  
    __torch_dispatch__ doesn't guarantee the number of arguments you are
    passed (e.g., defaulted arguments are not passed); but usually it is
    convenient to pad out the arguments list with defaults.  This function
    helps you do that.
    Args:
        args: the list of positional arguments passed to __torch_dispatch__
        n: the number of arguments you are expecting to get
        defaults_tail: default values for the arguments, starting from the
            end of the list
    Example:
        >>> fill_defaults([1, 2, 3], 5, [3, 4, 5])
        [1, 2, 3, 4, 5]
        >>> fill_defaults([1, 2, 3], 5, [None, None, None])
        [1, 2, 3, None, None]]
    z%not enough defaults to fill arguments)r)   RuntimeErrorr   r;   rY   )rD   rq   defaults_tailrir   r   r#   fill_defaults  s   r  c                   C   s   t j ot jjS rZ   )r4   r.   rX   r   hipr   r   r   r#   is_ROCM=  s   r  c                  C   s8   t  rg d} tjdj}| D ]	}||v r dS qdS )N)gfx940gfx941gfx942r   TFr  r4   r.   get_device_propertiesgcnArchName)
mxArchNamearchNamearchr   r   r#   r   A  s   r   c                  C   s$   t  rtjdj} d| v rdS dS )Nr   gfx950TFr  r  r   r   r#   is_MI350K  s
   r  c                  C   s   t  rtjdj} 	 dS dS )Nr   gfx1200gfx1201TFr  r  r   r   r#   is_Navi4S  s
   r  r   r   c                 C   s,   t j ot jj}|rt j | |fkS dS )z0Check if the CUDA version is exactly major.minorFr4   r.   rX   r   r_   )r   r   is_cudar   r   r#   is_sm_version[  s   r  c                   C       t j ot jjot j dkS )N)   	   r  r   r   r   r#   r   a  
   
r   c                   C   r  )N)r  r   r  r   r   r   r#   r   i  r  r   c                   C   r  )N)
   r   r  r   r   r   r#   r   r  r  r   c                 C   sN   t j sdS t jj}|d u rdS tt|dd d \}}||f| |fkS )NFr^   r  )r4   r.   rX   r   r   r   split)r   r   cuda_version
cuda_major
cuda_minorr   r   r#   r   z  s   
r   2.6.0c                 C   "   t | tjr	| j} | dkot|S )Nr1   r3   r4   r    r7   r   r    r   r   r   r#   check_cpu_version     r  2.8.0c                 C   r  )Nr2   r  r  r   r   r#   check_xpu_version  r  r  c                 C   s   | | d | S r  r   r   r   r   r   r#   ceil_div  s   r  r   r   c                 C   s   t | || S rZ   )r  r  r   r   r#   round_up  r   r  package_namer   c                 C   s$   t j| d u}|sdS t| |kS )NF)	importlibutil	find_specr   )r  r   package_existsr   r   r#   r     s   r   c                  C   s*   t jdd up
t } | sdS dd l}dS )NmslkFr   T)r  r  r  r   r  )has_mslkr  r   r   r#   _is_mslk_available  s
   r  c                       s4   e Zd ZdZddejdeej f fddZ  ZS )r   a  This is used because the TorchAO quantization functions tend to operate on modules so to apply the transform to a tensor, we can load a
    DummyModule with the target tensor and then apply the transformation to the module and then extract the transformed tensor.
    Nr   biasc                    s   t    || _|| _d S rZ   )superrc  r   r  )r   r   r  r(  r   r#   rc    s   

zDummyModule.__init__rZ   )	rz   r   r   r  r4   r   r	   rc  __classcell__r   r   r  r#   r     s    (r   )r   NN)T)FrZ   )r   N)r  )r  )Jr   r  r   r   rA   r   importlib.metadatar   mathr   typingr   r   r	   r4   torch.nn.utils.parametrizer5   rk   r   torch.utils._python_dispatchr
   __all__cacher6   r-   r   r   r   r]   r   r   rf   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r;  rC  rF  rM  rV  rW  r'  r   r  r  r   r  r  r  r   r   r   r   r  r  r  r  rb  r   r  r   r   r   r   r#   <module>   s   
G
7

#
"# 
%
!  "
	



