U
    T?h                     @   s   d dl mZ d dlmZmZ d dlmZ d dlmZ d dl	m
Z
mZmZ d dlmZ eeZG dd deZG d	d
 d
eZdS )    )	getLogger)DictList)Fusion)FusionUtils)	NodeProtoTensorProtohelper)	OnnxModelc                       sH   e Zd Zed fddZeeeee f eeef dddZ	  Z
S )FusionTransposemodelc                    s   t  |dd d S )N	Transposesuper__init__selfr   	__class__ [/var/www/html/venv/lib/python3.8/site-packages/onnxruntime/transformers/fusion_transpose.pyr      s    zFusionTranspose.__init__)transpose_nodeinput_name_to_nodesoutput_name_to_nodec                 C   sd  |}|j d |krdS ||j d  }|jdkr4d}nF|}| j||}|rZt|dkrZdS |j d |krldS ||j d  }|jdkrdS t|d}t|tst	t|d}	t|	tst	t|	t|kst	g }
t
|D ]\}}|
|	|  q|dkr t| j|||r@| j| n t| j|||r@| j| |d |jtd|
g dS )a  
        Note that onnxruntime will do comprehensive transpose optimization after loading model.
        The purpose of this fusion is to make graph clean before running onnxruntime.

        Case 1:
              (input)-->Transpose(perm=a)-->Transpose(perm=b)-->
        After:
              (input)-->Transpose(perm=a)-->  (this path can be removed if the output is not used anymore)
                |
                +----->Transpose(perm=a*b)-->

        Case 2 (Cast has only one child):
              (input)-->Transpose(perm=a)--> Cast -->Transpose(perm=b)-->
        After:
              (input)-->Transpose(perm=a)-->  (this path can be removed if the output is not used anymore)
                |
                +----->Cast --> Transpose(perm=a*b)-->
        r   NZCast   r   perm	attribute)inputZop_typer   get_childrenlenr
   get_node_attribute
isinstancelistAssertionError	enumerateappendr   Zskip_parentZnodes_to_removeZ
ClearFieldr   extendr	   make_attribute)r   r   r   r   Ztranspose_bZtranspose_aZ	cast_nodeZcast_childrenpermutationZparent_permutationZoutput_permutationZ_jindexr   r   r   fuse   s<    



zFusionTranspose.fuse)__name__
__module____qualname__r
   r   r   r   strr   r+   __classcell__r   r   r   r   r      s
   
r   c                       s^   e Zd Zed fddZdeee dddZe	e
eee	 f e
ee	f dd	d
Z  ZS )FusionInsertTransposer   c                    s   t  |dd d S )N Z	GroupNormr   r   r   r   r   r   Z   s    zFusionInsertTranspose.__init__N)
input_namer   c                 C   sT   | j d}|dkr$|d d | }tjd|g|g|d}|jtd|g |S )z&Append a Transpose node after an inputr   NZ_out-)inputsoutputsnamer   )r   create_node_namer	   Z	make_noder   r'   r(   )r   r3   r   Zoutput_nameZ	node_namer   r   r   r   create_transpose_node]   s    z+FusionInsertTranspose.create_transpose_node)group_norm_noder   r   c              	   C   s  | j |dddddgdddddg}|dkr0dS |\}}}}}	| j |jd rTdS t|d}
t|
tsnt|
ddd	d
gkrdS t	|j
dkr| j |j
d
 d	krt	|j
dkr| j |j
d
 dkrt	| j |	|d
krt	| j ||d
krt	| j ||d
ksdS d}| j |dkrN| j|tjd
gd
gdd d}| j |dkr~| j|tjd
gdgdd d|j
d
< d|j
d
< | j dd }| j |jd | | |jd dd	d
dg|}| j || j | d dS )a  
        This optimization will insert an Transpose, and onnxruntime transpose optimizer will remove it together with
        another Transpose so that we can get effect of reducing one Transpose after onnxruntime optimization.
        Before:
            --> Gemm --> Unsqueeze(axes=[2]) --> Unsqueeze(axes=[3]) --> Add --> Transpose([0,2,3,1]) --> GroupNorm
        After:
            --> Gemm --> Unsqueeze(axes=[1]) --> Unsqueeze(axes=[2]) -->Transpose([0,3,1,2]) --> Add --> Transpose([0,2,3,1]) --> GroupNorm
        r   AddZ	UnsqueezeZGemmr   Nr         r   Zort_const_unsqueeze_axes_1F)r7   Z	data_typeZdimsvalsrawZort_const_unsqueeze_axes_2Z_NCHWzInsert Transpose)r   Zmatch_parent_pathZfind_graph_outputoutputr
   r!   r"   r#   r$   r    r   Zget_constant_valuer   Zget_initializerZadd_initializerr   ZINT64r8   Zreplace_input_of_all_nodesr9   add_nodeZthis_graph_nameZincrease_counter)r   r:   r   r   Z	gemm_pathZ	transposeaddZunsqueeze_3Zunsqueeze_2Zgemmr)   Zaxes_1Zaxes_2Ztranspose_output_nameZnew_transposer   r   r   r+   f   sl      	

zFusionInsertTranspose.fuse)N)r,   r-   r.   r
   r   r/   r   intr9   r   r   r+   r0   r   r   r   r   r1   Y   s   
r1   N)loggingr   typingr   r   Zfusion_baser   Zfusion_utilsr   Zonnxr   r   r	   Z
onnx_modelr
   r,   loggerr   r1   r   r   r   r   <module>   s   H