
     Ng0                         d dl mZ d dlmZmZ d dlZd dlmZmZ d dlm	Z	m
Z
mZmZ d dlmZ d dlmZ  ee          Z G d d	          Z G d
 d          ZdS )    )	getLogger)OptionalTupleN)array_equalndarray)	NodeProtoTensorProtohelpernumpy_helper)onnx_pb)	OnnxModelc            
       V   e Zd ZdefdZdedeeef         fdZddefdZ		 	 	 d ded	e
d
ee         dee         fdZdefdZdefdZed             Zed!defd            Zed"defd            Zedej        fd            Zed#dedefd            Zde
fdZd Zd Zd Zd ZdS )$FusionUtilsmodelc                     || _         d S N)r   )selfr   s     a/var/www/html/ai-engine/env/lib/python3.11/site-packages/onnxruntime/transformers/fusion_utils.py__init__zFusionUtils.__init__   s     %


    
input_namereturnc                 8   | j                             |          }|Y|j        j        j        t
          j        k    r:|                     |          \  }}t          	                    d| d           d|fS t          	                    d| d|d u            d|fS )NzCasted graph input z	 to int32TzDid not cast graph input z to int32: found F)
r   find_graph_inputtypetensor_type	elem_typer	   INT32cast_input_to_int32loggerdebug)r   r   graph_inputcast_output	cast_nodes        r   cast_graph_input_to_int32z%FusionUtils.cast_graph_input_to_int32   s    j11*=="{'7'C'MQ\Qb'b'b%)%=%=j%I%I"KLLDzDDDEEE$$gggkaeNegghhhj  r   int32c                 &   |dz   |z   }|dk    rt          t          j                  }nO|dk    rt          t          j                  }n/|dk    rt          t          j                  }nt          d          |                     |||          }||fS )N_r&   float32float16z"Invalid target_type: {target_type})intr	   r   FLOATFLOAT16
ValueErroradd_cast_node)r   r   target_typeoutput_nameto_typer$   s         r   
cast_inputzFusionUtils.cast_input   s     3&4'!!++,,GGI%%++,,GGI%%+-..GGABBB&&z7KHH	I%%r   Nr2   r1   
graph_namec                 h   ||d| z   }|g}|| j                                         }||v r#||         }|r|j        dk    r|j        d         g}t	          j        d||g          }|j                            t	          j        d|          g           | j         	                    ||           |S )N	_cast_to_Castr   )inputsoutputsto)r4   )
r   output_name_to_nodeop_typeinputr
   	make_node	attributeextendmake_attributeadd_node)	r   r   r2   r1   r;   r4   r8   parent_noder$   s	            r   r/   zFusionUtils.add_cast_node/   s     $'<7'<'<<K &"&*"@"@"B"B,,,-j9K 0{2f<<%+A./$VF[MRRR	""F$9$$H$H#IJJJ
I*===r   c                 .    |                      |d          S )Nr&   )r3   )r   r   s     r   r   zFusionUtils.cast_input_to_int32J   s    z7333r   c                 j   | j                                         }||         }|D ]}|j        dk    rd}|j        D ]3}|j        dk    r&|j        t          t          j                  k    rd} n4|rB|j	        d         }| j         
                    |           | j                             ||           d S )Nr7   Fr:   Tr   )r   input_name_to_nodesr<   r?   nameir+   r	   r   outputremove_nodereplace_input_of_all_nodes)r   r   rF   nodesnodeis_int32attr1   s           r   remove_cast_int32zFusionUtils.remove_cast_int32M   s    "j<<>>#J/ 
	S 
	SD|v%% >  Cx4''CES9J5K5K,K,K#' S"&+a.KJ**4000J99+zRRR
	S 
	Sr   c                 >   d}| j         |         |v r[| || j         |                  v rF|| j         |                                      |            t          || j         |                            }|| j         |<   ||v r||                             |            n| g||<   |S )Nr   )r=   removelenappend)rM   rH   new_input_namerF   old_input_references        r   update_node_inputzFusionUtils.update_node_input\   s    JqM000d>QRVR\]^R_>`6`6`
1.55d;;;"%&9$*Q-&H"I"I&
1000/66t<<<<37&/""r   r   c                     |j         |         }|j         |         }t                              ||||          }|dk    o|                     |           }	|	S )a  
        Before:
              (input)-->parent-->node-->(output)
        After:
              (input)-->parent-->
                |
                +----->node-->(output)

        This function returns a flag whether the parent node can be removed.
        r   )r=   r   rW   find_graph_output)
r   rM   rC   rF   node_input_indexparent_input_indexold_input_namerU   rV   parent_can_be_removeds
             r   skip_parentzFusionUtils.skip_parentl   sf     $45$*+=>);;DBRTbdwxx "5!9 j5CZCZ[iCjCj?j$$r   attribute_namec                     |}| j         D ]!}|j        |k    rt          j        |          }"t	          |t
                    r.t	          |t          t
          f          ot          ||d          S ||k    S )a  Verify that a node has expected value for an attribute.

        Args:
            node (NodeProto): a node to check
            attribute_name (str): name of attribute
            expected_value (Any): expected value of the attribute
            default_value (Any, optional): default value if the attribute does not exist. Defaults to None.

        Returns:
            bool: whether the check is passed or not
        F	equal_nan)r?   rG   r
   get_attribute_value
isinstancelistr   r   )rM   r_   expected_valuedefault_valuevalueattrs         r   check_node_attributez FusionUtils.check_node_attribute   s     N 	9 	9DyN**2488nd++ 	+uwo66oKX]in<o<o<ooN**r   tensorc                    t          | t          j                  st          dt	          |                      t          | j                  dk    s| j        t          j        j        k    rt          d          | j	        rdt          j        t          j        | j	        d          | j                  }t          j        |ddg          }|                                | _	        nt          d          | S )	zTranspose a 2-D INT8 TensorProto
        Args:
            tensor (TensorProto): tensor to be transposed
        Returns:
            tensor (TensorProto): transposed tensor
        z3Expected input type is an ONNX TensorProto but got    z'Only INT8 2-D tensors can be transposedint8)dtype   r   zonly raw buffer supported)rd   
onnx_protor	   r.   r   rS   dims	data_typeINT8raw_datanumpyreshape
frombuffer	transposetobytes)rk   
int32_dataint32_transposed_datas      r   transpose_2d_int8_tensorz$FusionUtils.transpose_2d_int8_tensor   s     &*"899 	caSWX^S_S_aabbbv{q  F$4
8N8S$S$SFGGG? 	:u'7v'V'V'VX^XcddJ$)OJA$G$G!3;;==FOO 8999r   TrM   c                    | j         dvr"t                              d| j                     |                    | j        d                   }|dS |j        dk    p|j        dk    o|j        d         dk    }|r|sdS t          | j                  dk    rdS |                    | j        d                   }|j        |j        k    rdS |dS t          j	        |dk              S )	a  Verify if a provided QuantizeLinear (Q) / DequantizeLinear (DQ) node is a good candidate for fusion.
           It is a good candidate for fusion if:
           (1) The Q/DQ node is for per-tensor quantization if allow_per_tensor_quantization_only is `True`
           (2) The Q/DQ node should have constant scale
           (3) The Q/DQ node should have a zero point of 0
        Args:
            node (NodeProto): a Q/DQ node to check
        Returns:
            bool: whether the check is passed or not
        >   QuantizeLinearDequantizeLinearz+Provided node is not a Q/DQ node. Op Type: rp   NFr   rm   T)
r<   r    r!   get_constant_valuer=   ndimshaperS   rv   all)rM   r   "allow_per_tensor_quantization_onlyscalescale_has_single_element
zero_points         r   check_qdq_node_for_fusionz%FusionUtils.check_qdq_node_for_fusion   s     <EEELLUt|UUVVV((A77 =5 $):?#_uzQ7^5;WX>]^K^ - 	6N 	5 tz??a4 --djm<<
 :((5 5yq)))r   input_indexc                    t          |j                  |k    sJ | j                            |j        |                   }t	          |t
                    r.t	          |t          t
          f          ot          ||d          S ||k    S )a7  Verify that a node has expected input value

        Args:
            node (NodeProto): a node to check
            input_index (int): index of its input to be verified
            expected_value (Any): expected value of the input

        Returns:
            bool: whether the check is passed or not
        Fra   )rS   r=   r   r   rd   re   r   r   )r   rM   r   rf   rh   s        r   check_node_input_valuez"FusionUtils.check_node_input_value   s     4:,,,,
--dj.EFFnd++ 	+uwo66oKX]in<o<o<ooN**r   c                    g }| j                                         }| j                                         D ]b}|j        dk    rU|j        d         |vrF| j                             |j        d         |j        d                    |                    |           c|rG| j                             |           t          
                    dt          |           d           dS dS )z>Remove Identity nodes, except those right before graph output.Identityr   zRemoved z Identity nodesN)r   get_graphs_output_namesrL   r<   rI   rK   r=   rT   remove_nodesr    inforS   )r   nodes_to_removegraph_output_namesrM   s       r   remove_identity_nodesz!FusionUtils.remove_identity_nodes   s    !Z??AAJ$$&& 	1 	1D|z));q>);;;J99$+a.$*UV-XXX#**4000 	JJ##O444KKH3#7#7HHHIIIII	J 	Jr   c                 8    | j                                          d S r   )r   remove_cascaded_cast_nodesr   s    r   r   z&FusionUtils.remove_cascaded_cast_nodes   s    
--/////r   c                 8    | j                                          d S r   )r   remove_useless_cast_nodesr   s    r   r   z%FusionUtils.remove_useless_cast_nodes  s    
,,.....r   c                 P   | j                             d          }|dS g }| j                                         D ]}|j        dk    r|                    |j        d                   }|                    |j        d                   }|rB|r@||k    r:t                              d|j	         d|            |
                    |           |rTt          | j                                                   }t          | j                                                   }|D ]}t          t          |j                  |z            rt          t          |j                  |z            smt          | j                                         |j        d                            dk    r2| j                             |j        d         |j        d                    n2| j                             |j        d         |j        d                    | j                             |           dS dS )	ziRemove reshape node that is not needed based on symbolic shape inference: input and output has same shapeT)updateNReshaper   zRemove reshape node z* since its input shape is same as output: rp   )r   infer_runtime_shaperL   r<   get_edge_shaper=   rI   r    r   rG   rT   setget_graphs_input_namesr   boolrS   rF   replace_output_of_all_nodesrK   rJ   )r   shape_inferr   rM   input_shapeoutput_shapegraph_input_namesr   s           r   remove_useless_reshape_nodesz(FusionUtils.remove_useless_reshape_nodes  s   j44D4AAFJ$$&& 	1 	1D|y(()88AGG*99$+a.II 1< 1K<4O4OKKqtyqqdoqq   $**4000 	- #DJ$E$E$G$G H H!$TZ%G%G%I%I!J!J' - -DK((+==>> 	Y TZ3D!DEE!
 > > @ @A OPPTUUU
>>tz!}dkZ[n]]]] J99$+a.$*UV-XXX
&&t,,,,	- 	-- -r   )r&   )NNN)r   r   r   )T)__name__
__module____qualname__r   r   strr   r   r%   r3   r+   r   r/   r   rP   staticmethodrW   r^   rj   rq   r	   r}   r   r   r   r   r   r   r    r   r   r   r      s2       &i & & & &!C !E$)<L ! ! ! !& &S & & & &( &* $(   c]	 SM   64c 4 4 4 4SC S S S S # # \# % %9 % % % \%* + +3 + + + \+, )?    \. (* (*	 (*) (* (* (* \(*T+ + + + +(J J J0 0 0/ / /- - - - -r   r   c                   4    e Zd Zeddededefd            ZdS )NumpyHelperFrk   
fill_zerosr   c                     |r,ddl m} t          | j        |j        | j                           S t          j        |           S )Nr   )mapping)r   ro   )onnxr   r   rr   TENSOR_TYPE_TO_NP_TYPErs   r   to_array)rk   r   r   s      r   r   zNumpyHelper.to_array'  s[      	$$$$$$k4V5EF   
 $V,,,r   N)F)r   r   r   r   r	   r   r   r   r   r   r   r   r   &  sL        - - -$ -7 - - - \- - -r   r   )loggingr   typingr   r   rv   r   r   r   r   r	   r
   r   r   rq   
onnx_modelr   r   r    r   r   r   r   r   <module>r      s  
       " " " " " " " "  & & & & & & & & = = = = = = = = = = = = & & & & & &            	8		R- R- R- R- R- R- R- R-j- - - - - - - - - -r   