U
    d                     @   s   d dl Z d dlZ d dlZd dlmZmZ d dlmZmZm	Z	m
Z
mZ d dlmZ eddG dd de	Ze jed	d
dZeddG dd de jjZdS )    N)Nodemap_aggregate)AnyTuple
NamedTupleOptionalDict)compatibilityT)Zis_backward_compatiblec                   @   s\   e Zd ZU ejed< ejed< eed< ee	 ed< e
ej ed< eed< eeef ed< dS )	TensorMetadatashapedtyperequires_gradstridememory_formatis_quantizedqparamsN)__name__
__module____qualname__torchSize__annotations__r   boolr   intr   r   r   strr    r   r   >/tmp/pip-unpacked-wheel-ua33x9lu/torch/fx/passes/shape_prop.pyr
   
   s   


r
   )resultreturnc                 C   s   | j }| j}| j}|  }tjtjtjh}d}|D ]}| j|dr2|} qLq2| j	}i }	|r| 
 }
|
|	d< |
tjtjhkr|  |	d< |  |	d< n@|
tjtjtjhkr|   |	d< |   |	d< |  |	d< t|||||||	S )zB
    Extract a TensorMetadata NamedTuple describing `result`.
    N)r   qschemeZscaleZ
zero_pointZaxis)r   r   r   r   r   Zcontiguous_formatZchannels_lastZchannels_last_3dZis_contiguousr   r   Zper_tensor_affineZper_tensor_symmetricZq_scaleZq_zero_pointZper_channel_affineZ per_channel_affine_float_qparamsZper_channel_symmetricZq_per_channel_scalestolistZq_per_channel_zero_pointsZq_per_channel_axisr
   )r   r   r   r   r   Zmemory_formatsr   Zquery_formatr   r   r   r   r   r   _extract_tensor_metadata   sD          r!   c                       s4   e Zd ZdZeed fddZ fddZ  ZS )	ShapePropa  
    Execute an FX graph Node-by-Node and
    record the shape and type of the result
    into the corresponding node.

    Example:
         In this example, we record the shape
         and data type of a module given
         an example input ``torch.randn(50, D_in)``.
         We print the name, shape and dtype of each node.

        class TwoLayerNet(torch.nn.Module):
            def __init__(self, D_in, H, D_out):
                super(TwoLayerNet, self).__init__()
                self.linear1 = torch.nn.Linear(D_in, H)
                self.linear2 = torch.nn.Linear(H, D_out)
            def forward(self, x):
                h_relu = self.linear1(x).clamp(min=0)
                y_pred = self.linear2(h_relu)
                return y_pred
        N, D_in, H, D_out = 64, 1000, 100, 10
        x = torch.randn(N, D_in)
        y = torch.randn(N, D_out)
        model = TwoLayerNet(D_in, H, D_out)
        gm = torch.fx.symbolic_trace(model)
        sample_input = torch.randn(50, D_in)
        ShapeProp(gm).propagate(sample_input)

        for node in gm.graph.nodes:
            print(node.name, node.meta['tensor_meta'].dtype,
                node.meta['tensor_meta'].shape)

        The output of this code is:

        x torch.float32 torch.Size([50, 1000])
        linear1 torch.float32 torch.Size([50, 100])
        clamp_1 torch.float32 torch.Size([50, 100])
        linear2 torch.float32 torch.Size([50, 10])
        output torch.float32 torch.Size([50, 10])

    Args:
         module (GraphModule): The module to be executed

    )nr   c                    s   zt  |}W n6 tk
rF   t  td|  d|j Y nX d  fdd}t||} rp||jd< t	||jd< |S )NzShapeProp error for: node=z with meta=Fc                    s    t | tjrd t| S | S d S )NT)
isinstancer   Tensorr!   )objZfound_tensorr   r   extract_tensor_meta}   s    z/ShapeProp.run_node.<locals>.extract_tensor_metaZtensor_metatype)
superrun_node	Exception	traceback	print_excRuntimeErrorZformat_nodemetar   r)   )selfr#   r   r(   r0   	__class__r'   r   r+   q   s    


zShapeProp.run_nodec                    s   t  j| S )a  
        Run `module` via interpretation and return the result and
        record the shape and type of each node.

        Args:
            *args (Tensor): the sample input.

        Returns:
            Any: The value returned from executing the Module
        )r*   run)r1   argsr2   r   r   	propagate   s    zShapeProp.propagate)	r   r   r   __doc__r   r   r+   r6   __classcell__r   r   r2   r   r"   C   s   ,r"   )r   Ztorch.fxr-   Ztorch.fx.noder   r   typingr   r   r   r   r   Ztorch.fx._compatibilityr	   r
   r%   r!   ZfxZInterpreterr"   r   r   r   r   <module>   s   )