o
    ϯi %                     @   s  d dl Z d dlmZmZ d dlmZ d dl mZmZmZm	Z	m
Z
 d dlZzd dlmZ W n ey;   d dlmZ Y nw eee ee ge
e je ef f Zdede	ee  fdd	Z	 d,d
e	e defddZdee dee defddZdee dee defddZdee dee defddZ	d-dee dee dee dedef
ddZdee dee de je fddZdee dee defddZdee dee defd d!Zd"edefd#d$Zdee dee defd%d&Zd.d(ed)edefd*d+Z dS )/    N)CounterOrderedDict)Number)AnyCallableListOptionalUnionprodvalreturnc                 C   s   |   r
|   S dS )z
    Get the shapes from a jit value object.

    Args:
        val (torch._C.Value): jit value object.

    Returns:
        list(int): return a list of ints.
    N)isCompleteTensortypesizes)r    r   I/home/ubuntu/.local/lib/python3.10/site-packages/fvcore/nn/jit_handles.py	get_shape   s   
r   op_namec                    s0   dt dtt  dttjt tf f fdd}|S )aT  
    This method return a handle that counts the number of activation from the
    output shape for the specified operation.

    Args:
        op_name (str): The name of the operation. If given, the handle will
            return a counter using this name.

    Returns:
        Callable: An activation handle for the given operation.
    ioutputsr   c                    s,   t |d }t|} du r|S t |iS )z
        This is a generic jit handle that counts the number of activations for any
        operation given the output shape.
        r   N)r   r   r   )r   r   	out_shapeac_countr   r   r   _generic_activation_jitA   s
   z7generic_activation_jit.<locals>._generic_activation_jit)r   r   r	   typingr   strr   )r   r   r   r   r   generic_activation_jit4   s   r   inputsr   c                 C   sv   dd | dd D }t |d dksJ |d t |d dks'J |d |d \}}|d d }|| | }|S )z1
    Count flops for fully connected layers.
    c                 S      g | ]}t |qS r   r   .0vr   r   r   
<listcomp>X       z"addmm_flop_jit.<locals>.<listcomp>      r      len)r   r   input_shapes
batch_size	input_dim
output_dimflopsr   r   r   addmm_flop_jitR   s   r0   c                 C   sN   dd | dd D }|d d |d d ksJ t |d |d d  }|S )z4
    Count flops for the aten::linear operator.
    c                 S   r   r   r    r!   r   r   r   r$   i   r%   z#linear_flop_jit.<locals>.<listcomp>r   r(   r&   r
   )r   r   r+   r/   r   r   r   linear_flop_jitc   s   r2   c                 C   sT   t | dksJ t | dd | D }|d \}}}|d d }|| | | }|S )z,
    Count flops for the bmm operation.
    r(   c                 S   r   r   r    r!   r   r   r   r$   x   r%   z bmm_flop_jit.<locals>.<listcomp>r   r1   r)   )r   r   r+   nctdflopr   r   r   bmm_flop_jitq   s   r8   Fx_shapew_shaper   
transposedc                 C   s4   | d }|r| n|dd }|t | t | }|S )a  
    Count flops for convolution. Note only multiplication is
    counted. Computation for addition and bias is ignored.

    Flops for a transposed convolution are calculated as
    flops = (x_shape[2:] * prod(w_shape) * batch_size).

    Args:
        x_shape (list(int)): The input shape before convolution.
        w_shape (list(int)): The filter shape.
        out_shape (list(int)): The output shape after convolution.
        transposed (bool): is the convolution transposed
    Returns:
        int: the number of flops
    r   r(   Nr
   )r9   r:   r   r;   r,   
conv_shaper7   r   r   r   conv_flop_count   s   r=   c                 C   sx   t | dkst | dksJ t | | dd \}}t|t|t|d }}}| d  }tdt||||diS )	z&
    Count flops for convolution.
          Nr(   r      conv)r;   )r*   r   toIValuer   r=   )r   r   xwr9   r:   r   r;   r   r   r   conv_flop_jit   s   $	 rE   c                 C   sb  t | dksJ t | | d  }|dd}| d   }dd |D }tdd	 |D  }d
d t|D }||}|dkr[|d \}}}	|d d }
|| |	 |
 }|S |dkrv|d \}}	}|d d }||	 | | }|S dd |D }t	j
|g|R ddid }|dD ]}d| v rtt	t|dd d }|  S qtd)z/
    Count flops for the einsum operation.
    r(   r     r&   c                 S   r   r   r    r!   r   r   r   r$      r%   z#einsum_flop_jit.<locals>.<listcomp>c                 s   s     | ]}|  r|d fV  qdS )r   N)isalpha)r"   kr   r   r   	<genexpr>   s    z"einsum_flop_jit.<locals>.<genexpr>c                 S   s   i | ]\}}t |d | qS )a   )ord)r"   r   rC   r   r   r   
<dictcomp>   s    z#einsum_flop_jit.<locals>.<dictcomp>zabc,abd->acdr1   zabc,adc->adbc                 S   s   g | ]}t |qS r   )npzeros)r"   sr   r   r   r$      s    optimizeoptimal
zoptimized flop:zUnsupported einsum operation.)r*   rB   replacenoder   r   keys	enumerate	translaterN   einsum_pathsplitlowerfloatfloorNotImplementedError)r   r   equationinput_shapes_jitr+   letter_ordermappingr3   r4   r5   pr7   gnp_arrsoptimliner   r   r   einsum_flop_jit   s4   
 ri   c                 C   s^   dd | D }t |dksJ ||d d |d d ks!J |t|d |d d  }|S )z!
    Count flops for matmul.
    c                 S   r   r   r    r!   r   r   r   r$      r%   z#matmul_flop_jit.<locals>.<listcomp>r(   r   r1   r&   )r*   r   )r   r   r+   r7   r   r   r   matmul_flop_jit   s
    rk   affine_arg_indexc                    s&   dt t dt t dtf fdd}|S )zP
    Args:
        affine_arg_index: index of the affine argument in inputs
    r   r   r   c                    sb   t | d }t |   du}dt|  krdks"J | J |t||r,d }|S d }|S )z.
        Count flops for norm layers.
        r   Nr(         )r   r*   r   )r   r   input_shape
has_affiner7   rl   r   r   norm_flop_jit   s   (z(norm_flop_counter.<locals>.norm_flop_jitr   r   r   )rl   rr   r   rq   r   norm_flop_counter   s   "rt   c                 C   sb   | d   }t|tsJ d|rtd| |S t| d d u}tt| d }||r.d S d S )Nrm   z*Signature of aten::batch_norm has changed!r&   r   r(   )rB   
isinstanceboolrt   r   r   )r   r   trainingrp   ro   r   r   r   batchnorm_flop_jit   s   rx   r&   input_scaleoutput_scalec                    s(   dt t dt t dtf fdd}|S )a  
    Count flops by
        input_tensor.numel() * input_scale + output_tensor.numel() * output_scale

    Args:
        input_scale: scale of the input tensor (first argument)
        output_scale: scale of the output tensor (first element in outputs)
    r   r   r   c                    sP   d} dkrt | d }| t| 7 }dkr&t |d }|t| 7 }|S )Nr   )r   r   )r   r   retshapery   rz   r   r   elementwise_flop  s   z2elementwise_flop_counter.<locals>.elementwise_floprs   )ry   rz   r~   r   r}   r   elementwise_flop_counter  s   $

r   )N)F)r&   r   )!r   collectionsr   r   numbersr   r   r   r   r   r	   numpyrN   mathr   ImportErrorr   Handleintr   r   r0   r2   r8   rv   r=   rE   ri   rk   rt   rx   r]   r   r   r   r   r   <module>   sF   &
$+
