o
    ϯi_                  	   @   sn  U 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	 d dlm
Z
mZmZmZmZmZmZmZm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 d
dlmZ edddZ h dZ!ee" e#d< eG dd dZ$dej%deee"ej%f  fddZ&dej%deeeedf f deee"ej%f e"f dej'j(fddZ)G dd dZ*dS )    N)Counter)copy)	dataclass)Number)	AnyDictIteratorListOptionalSetTupleTypeVarUnion_named_modules_with_dup)Tensor)_get_trace_graphTracerWarning   )HandleTJitModelAnalysis)bound>:   aten::taten::eqaten::geaten::gtaten::to	aten::Int	aten::cat	aten::max
aten::full
aten::ones
aten::relu
aten::roll
aten::size
aten::viewaten::chunkaten::clampaten::copy_aten::emptyaten::flooraten::indexaten::relu_aten::sliceaten::splitaten::stackaten::zerosaten::arangeaten::clamp_aten::detachaten::expandaten::gatheraten::narrowaten::selectaten::unbindaten::__and__aten::dropoutaten::flattenaten::nonzeroaten::permuteaten::reshapeaten::squeezeaten::type_asaten::new_fullaten::full_likeaten::new_emptyaten::new_zerosaten::remainderaten::transposeaten::unsqueezeaten::contiguousaten::index_put_aten::unsqueeze_aten::zeros_likeaten::bitwise_notaten::masked_fillaten::floor_divideaten::ScalarImplicitaten::constant_pad_ndaten::split_with_sizes_IGNORED_OPSc                   @   s*   e Zd ZU dZded< ded< ded< dS )
StatisticszY
    For keeping track of the various model statistics recorded during
    analysis.
    zDict[str, Counter[str]]countsunsupported_opszSet[str]uncalled_modsN)__name__
__module____qualname____doc____annotations__ r]   r]   J/home/ubuntu/.local/lib/python3.10/site-packages/fvcore/nn/jit_analysis.pyrT   Z   s
   
 rT   modelreturnc                 c   s:    t  }t| D ]\}}||vr|| ||fV  qdS )zd
    Like .named_modules(), but the results are slightly different for
    some wrapped models.
    N)setr   add)r_   seennamemodr]   r]   r^   _named_modules_without_dupf   s   

rf   moduleinputs.aliasesc           
         s   G dd dG dd d g dt jdtddf fd	d
}t| t jjjt jfr7||  }| j} || | t	| D ]\}}|| }||| q;t
| |\}}D ]}	|	  qR|S )a  
    Traces the provided module using torch.jit._get_trace_graph, but adds
    submodule scope information to each graph node. The resulting graph
    is in-lined and has all model parameters treated as inputs. The input
    model has the scope name '', while its descendants have names of the
    form 'child.grandchild.grandgrandchild...'.

    Args:
        model (nn.Module) : The module to trace
        inputs (tuple) : Inputs used during the trace of the model
        aliases (dict(str or nn.Module, str) : maps modules and module
            names to the canonical name to be used as the scope for
            that module.

    Returns:
        graph (torch._C.Graph) : The pytorch JIT trace of the model
    c                   @   s6   e Zd ZdeddfddZdejdedefdd	ZdS )
z._get_scoped_trace_graph.<locals>.ScopePushHookrd   r`   Nc                 S   s
   || _ d S N)rd   selfrd   r]   r]   r^   __init__   s   
z7_get_scoped_trace_graph.<locals>.ScopePushHook.__init__rg   rh   c                 S   s   t j }|r|| j |S rj   )torch_C_get_tracing_state
push_scoperd   )rl   rg   rh   tracing_stater]   r]   r^   __call__   s   
z7_get_scoped_trace_graph.<locals>.ScopePushHook.__call__)	rX   rY   rZ   strrm   nnModuler   rs   r]   r]   r]   r^   ScopePushHook   s    rw   c                   @   s(   e Zd ZdejdededefddZdS )z-_get_scoped_trace_graph.<locals>.ScopePopHookrg   rh   outputsr`   c                 S   s   t j }|r|  |S rj   )rn   ro   rp   	pop_scope)rl   rg   rh   rx   rr   r]   r]   r^   rs      s   
z6_get_scoped_trace_graph.<locals>.ScopePopHook.__call__N)rX   rY   rZ   ru   rv   r   rs   r]   r]   r]   r^   ScopePopHook   s     rz   re   rd   r`   Nc                    s2   |  |}|   }| | d S rj   )register_forward_pre_hookregister_forward_hookappend)re   rd   prehookposthookrz   rw   hook_handlesr]   r^   register_hooks   s   
z/_get_scoped_trace_graph.<locals>.register_hooks)ru   rv   rt   
isinstanceparalleldistributedDistributedDataParallelDataParallelrg   rf   r   remove)
rg   rh   ri   r   	root_namerd   re   graph_handler]   r   r^   _get_scoped_trace_graphr   s"   
 

r   c                
   @   s&  e Zd ZdZdejdeeeedf f ddfddZ	dCd
e
defddZdCd
e
deje
 fddZdee
eje
 f fddZdeje
 fddZdCd
e
deje
 fddZdee
 fddZdee dd fddZdDddZde
de
fddZ		dEdeej d edeeedf f dd fd!d"Zd#ed$e
defd%d&Zd#ed$e
defd'd(Zd#ed)edefd*d+Z d#ed)edefd,d-Z!d.eje
 ddfd/d0Z"d1ee
 ddfd2d3Z#dejdeee
ejf e
f fd4d5Z$d
e
dee
 fd6d7Z%dFd9d:Z&d;e
de
fd<d=Z'd>e
defd?d@Z(defdAdBZ)dS )Gr   aK  
    Provides access to per-submodule model statistics obtained by
    tracing a model with pytorch's jit tracing functionality. Calculates
    a statistic on a per-operator basis using the provided set of functions
    that acts on the inputs and outputs to the operator, then aggregates
    this over modules in the model. Can return the aggregate statistic for
    any submodule in the model. Is lazily evaluated, and will perform the
    trace when a statistic is first requested. Changing the operator handles
    will cause the trace to be rerun on the next request.

    Submodules may be referred to using the module's name. The input model has
    name "", while its descendants have names of the form
    "child.grandchild.grandgrandchild...".

    An operator is treated as within the scope of a module if calling that
    module directly resulted in that operator being run. In particular,
    this means that calls to other functions owned by a module or explicit
    calls to module.forward(...) will not register resulting operators as
    contributing statistics to that module.
    r_   rh   .r`   Nc                 C   sh   || _ || _i | _tt|| _| || _d| _t	t
| _| d | d | d | d dS )a  
        Args:
            model: The model to analyze
            inputs: The inputs to the model for analysis.

        We will trace the execution of `model.forward(inputs)`. This means
        inputs have to be tensors or tuple of tensors (see
        https://pytorch.org/docs/stable/generated/torch.jit.trace.html#torch.jit.trace).
        In order to trace other methods or unsupported input types, you may need
        to implement a wrapper module.
        NTno_tracer_warningowner)_model_inputs_op_handlesdictr   _named_modules_get_aliases_aliases_statsr   rS   _ignored_opsunsupported_ops_warningsuncalled_modules_warningstracer_warningsancestor_mode)rl   r_   rh   r]   r]   r^   rm      s   



zJitModelAnalysis.__init__ module_namec                 C   s(   |   }| |}t|j|  }|S )a(  
        Returns the total aggregated statistic across all operators
        for the requested module.

        Args:
            module_name (str) : The submodule to get data for. Defaults to
                the entire model.
        Returns:
            int : The aggregated statistic.
        )_analyzecanonical_module_namesumrU   values)rl   r   statstotal_countr]   r]   r^   total   s   
zJitModelAnalysis.totalc                 C   s   |   }| |}|j| S )a  
        Returns the statistics for a requested module, grouped by operator
        type. The operator handle determines the name associated with each
        operator type.

        Args:
            module_name (str) : The submodule to get data for. Defaults
                to the entire model.
        Returns:
            Counter(str) : The statistics for each operator.
        )r   r   rU   )rl   r   r   r]   r]   r^   by_operator   s   

zJitModelAnalysis.by_operatorc                 C      |   }|jS )a  
        Returns the statistics for all submodules, separated out by
        operator type for each submodule. The operator handle determines
        the name associated with each operator type.

        Returns:
            dict(str, Counter(str)):
                The statistics for each submodule and each operator.
                Grouped by submodule names, then by operator name.
        )r   rU   rl   r   r]   r]   r^   by_module_and_operator  s   z'JitModelAnalysis.by_module_and_operatorc                 C   s6   |   }t }|j D ]\}}t| ||< q|S )z
        Returns the statistics for all submodules, aggregated over
        all operators.

        Returns:
            Counter(str): statistics counter grouped by submodule names
        )r   r   rU   itemsr   r   )rl   r   summed_countsre   resultsr]   r]   r^   	by_module  s
   zJitModelAnalysis.by_modulec                 C   s(   | j du r	td| |}| j j| S )a  
        Lists the number of operators that were encountered but unsupported
        because no operator handle is available for them. Does not include
        operators that are explicitly ignored.

        Args:
            module_name (str) : The submodule to list unsupported ops.
                Defaults to the entire model.

        Returns:
            Counter(str) : The number of occurences each unsupported operator.
        NzDAnalysis results should be computed before calling unsupported_ops())r   RuntimeErrorr   rV   )rl   r   r]   r]   r^   rV   )  s   

z JitModelAnalysis.unsupported_opsc                 C   r   )a  
        Returns a set of submodules that were never called during the
        trace of the graph. This may be because they were unused, or
        because they were accessed via direct calls .forward() or with
        other python methods. In the latter case, statistics will not be
        attributed to the submodule, though the statistics will be included
        in the parent module.

        Returns:
            set(str) : The set of submodule names that were never called
                during the trace of the model.
        )r   rW   r   r]   r]   r^   uncalled_modules>  s   z!JitModelAnalysis.uncalled_moduleskwargsc                 O   s   d| _ t|d dkrtdt|ddd |ddd D ]\}}|||< q| D ]\}}|du r:| j| q+|| j|< q+| S )a@  
        Sets additional operator handles, or replaces existing ones.

        Args:
            args: (str, Handle) pairs of operator names and handles.
            kwargs: mapping from operator names to handles.

        If a handle is ``None``, the op will be explicitly ignored. Otherwise,
        handle should be a function that calculates the desirable statistic
        from an operator. The function must take two arguments, which are the
        inputs and outputs of the operator, in the form of ``list(torch._C.Value)``.
        The function should return a counter object with per-operator statistics.

        Examples
        ::
            handlers = {"aten::linear": my_handler}
            counter.set_op_handle("aten::matmul", None, "aten::bmm", my_handler2)
                   .set_op_handle(**handlers)
        N   r   z?set_op_handle should be called with pairs of names and handles!r   )r   len	TypeErrorzipr   r   rb   r   )rl   argsr   rd   r   r]   r]   r^   set_op_handleN  s   &
zJitModelAnalysis.set_op_handlec                 C   s   i | _ tt| _d| _| S )z<
        Clears all operator handles currently set.
        N)r   r   rS   r   r   rl   r]   r]   r^   clear_op_handlesp  s   
z!JitModelAnalysis.clear_op_handlesrd   c                 C   s.   t |ts	J d|| jv r| j| S td)a  
        Returns the canonical module name of the given ``name``, which might be
        different from the given ``name`` if the module is shared.
        This is the name that will be used as a key when statistics are
        output using .by_module() and .by_module_and_operator().

        Args:
            name (str) : The name of the module to find the canonical name for.
        Returns:
            str : The canonical name of the module.
        zModule name must be a string.zIRequested module name is not among the descendants of the analyzed model.)r   rt   r   KeyErrorrk   r]   r]   r^   r   y  s   

z&JitModelAnalysis.canonical_module_name	new_model
new_inputsc                 C   sV   |du r| j n|}|du r| jn|}t||djdi | j| j| j	| j
S )a  
        Returns a copy of the :class:`JitModelAnalysis` object, keeping all
        settings, but on a new model or new inputs.

        Args:
            new_model (nn.Module or None) : a new model for the new
                JitModelAnalysis. If None, uses the original model.
            new_inputs (typing.Tuple[object, ...] or None) : new inputs
                for the new JitModelAnalysis. If None, uses the original
                inputs.
        Returns:
            JitModelAnalysis : the new model analysis object
        N)r_   rh   r]   )r   r   r   r   r   r   _enable_warn_unsupported_opsr   _enable_warn_uncalled_modsr   _warn_trace)rl   r   r   r_   rh   r]   r]   r^   r     s   
zJitModelAnalysis.copyrl   modec                 C   s"   |dvrt d| d|| _| S )a  
        Sets which warnings to print when tracing the graph to calculate
        statistics. There are three modes. Defaults to 'no_tracer_warning'.
        Allowed values are:

        * 'all' : keeps all warnings raised while tracing
        * 'no_tracer_warning' : suppress torch.jit.TracerWarning only
        * 'none' : suppress all warnings raised while tracing

        Args:
            mode (str) : warning mode in one of the above values.
        )allr   nonez!Unrecognized tracer warning mode .)
ValueErrorr   rl   r   r]   r]   r^   r     s   z JitModelAnalysis.tracer_warningsc                 C   s    |dvrt d| || _| S )a  
        Sets how to determine the ancestor modules of an operator. Must be one of
        "owner" or "caller".

        * "caller": an operator belongs to all modules that is currently executing
          `forward()` at the time the operator is called.
        * "owner": an operator belongs to the last module that's executing
          `forward()` at the time the operator is called, plus this module's recursive
          parents.  If an module has multiple parents (e.g. a shared module), only one
          will be picked.

        For most cases, a module only calls submodules it owns, so both options would
        work identically. In certain edge cases, this option will affect the hierarchy
        of results, but won't affect the total count.
        )r   callerzUnrecognized ancestor mode: )r   _ancestor_moder   r]   r]   r^   r     s   zJitModelAnalysis.ancestor_modeenabledc                 C   
   || _ | S )aC  
        Sets if warnings for unsupported operators are shown. Defaults
        to True. Counts of unsupported operators may be obtained from
        :meth:`unsupported_ops` regardless of this setting.

        Args:
            enabled (bool) : Set to 'True' to show unsupported operator
                warnings.
        )r   rl   r   r]   r]   r^   r     s   
z)JitModelAnalysis.unsupported_ops_warningsc                 C   r   )a  
        Sets if warnings from uncalled submodules are shown. Defaults to true.
        A submodule is considered "uncalled" if it is never called during
        tracing. This may be because it is actually unused, or because it is
        accessed via calls to ``.forward()`` or other methods of the module.
        The set of uncalled modules may be obtained from
        :meth:`uncalled_modules` regardless of this setting.

        Args:
            enabled (bool) : Set to 'True' to show warnings.
        )r   r   r]   r]   r^   r     s   z*JitModelAnalysis.uncalled_modules_warningsopsc                 C   s<   | j sd S tt}| D ]\}}|d|| qd S )Nz.Unsupported operator {} encountered {} time(s))r   logging	getLoggerrX   r   warningformat)rl   r   loggeropfreqr]   r]   r^   _warn_unsupported_ops  s   

z&JitModelAnalysis._warn_unsupported_opsrW   c                    sR    j sd S  fdd|D }t|dkrd S tt}|ddt|  d S )Nc                    s   h | ]	}  |r|qS r]   )_has_forward).0xr   r]   r^   	<setcomp>  s    z7JitModelAnalysis._warn_uncalled_mods.<locals>.<setcomp>r   aB  The following submodules of the model were never called during the trace of the graph. They may be unused, or they were accessed by direct calls to .forward() or via other python methods. In the latter case they will have zeros for statistics, though their statistics will still contribute to their parent calling module.
z, )r   r   r   r   rX   r   joinsorted)rl   rW   r   r]   r   r^   _warn_uncalled_mods  s   
z$JitModelAnalysis._warn_uncalled_modsc                 C   s6   i }t |D ]\}}||vr|||< || ||< q|S rj   r   )rl   r_   ri   rd   rg   r]   r]   r^   r   	  s   zJitModelAnalysis._get_aliasesc                 C   sH   |  |d}dh}tt|d D ]}|d|d|  q|S )z
        Get all ancestors of the given module, defined by ownership.
        If the given module has multiple owners, use its canonical name.
        r   r   r   N)r   splitranger   rb   r   )rl   r   partsreskr]   r]   r^   _get_all_ancestors  s
   z#JitModelAnalysis._get_all_ancestorsrT   c                 C   s<  | j }|d ur	|S t ( | jdkrtd n| jdkr%tjdtd t| j| j	| j
}W d    n1 s8w   Y  i }i }t| jD ]\}}| j
| }t ||< t ||< qFt }| D ]}	|	 }
|
dkrs|
d |	  }
|	 d}|| | jdkrt|}n| |d	 }|| |
| jvr| |	rqa|D ]}|| |
  d
7  < qqat|	 t|	 }}| j|
 ||}t|trt| |
|i}| D ]}t|tt t!j"t!j#fst$dt%| dq|D ]
}||  |7  < qqat| j
 | }t&|||d}|| _ | '|d  | (| |S )Nr   ignorer   )categoryprim::PythonOpr   /r   r   zInvalid type z? for the flop count! Please use a wider type to avoid overflow.)rU   rV   rW   r   ))r   warningscatch_warningsr   simplefilterfilterwarningsr   r   r   r   r   r   r   ra   nodeskindpyname	scopeNamer   updater   r   r   _should_ignore_nodelistrh   rx   r   r   _simplify_op_namer   intfloatnpfloat64int64r   typerT   r   r   )rl   r   r   rU   rV   r   re   rd   all_seennoder   scope_names	ancestorsrh   rx   	op_countsvrW   r]   r]   r^   r     sl   












zJitModelAnalysis._analyzefull_op_namec                 C   s&   | d}|dkr||d d S |S )z|
        Get simplified name of the op without the preceding namespace, e.g.
        aten::batch_norm -> batch_norm
        z::r   r   N)find)rl   r   pr]   r]   r^   r   _  s   
z"JitModelAnalysis._simplify_op_namemod_namec                 C   sT   | j |}|d u rdS t|}tjtjtjtjh}|D ]}|j|ju r' dS qdS )NFT)	r   getr   ru   
ModuleList
ModuleDictrv   Identityforward)rl   r   rg   module_typeno_forward_modsre   r]   r]   r^   r   j  s   zJitModelAnalysis._has_forwardc                 C   s@   |  }|| jv rdS |ds|drdS |drdS dS )NTr   zprim::CallFunctionFzprim::)r   r   
startswith)rl   r   r   r]   r]   r^   r   ~  s   

z$JitModelAnalysis._should_ignore_node)r   )r`   r   )NN)r`   rT   )*rX   rY   rZ   r[   ru   rv   r   r   r   rm   rt   r   r   typingr   r   r   r   r   rV   r   r   r
   r   r   r   r   r   r   r   r   boolr   r   r   r   r   r   r   r   r   r   r]   r]   r]   r^   r      sN    

"	
	&
C)+r   r	  r   collectionsr   r   dataclassesr   numbersr   r   r   r   r	   r
   r   r   r   r   numpyr   rn   torch.nnru   fvcore.common.checkpointr   r   	torch.jitr   r   jit_handlesr   r   rS   rt   r\   rT   rv   rf   ro   Graphr   r   r]   r]   r]   r^   <module>   s<   
,>"
F