U
    T?h*$  ã                   @   sÆ   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
 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 d dlmZ d dlmZ d dlmZ e  e¡ZG dd„ deƒZdS )é    N)ÚOptional)ÚFusionAttentionUnet)ÚFusionBiasAdd)ÚFusionBiasSplitGelu)ÚFusionGroupNorm)ÚFusionNhwcConv)ÚFusionOptions)ÚFusionSkipGroupNorm)ÚFusionInsertTransposeÚFusionTranspose)Úis_installed)Ú
ModelProto)Ú	OnnxModel)ÚBertOnnxModelc                       sœ   e Zd Zdeeedœ‡ fdd„Zdd„ Zdd„ Zd	d
„ Zdd„ Z	dd„ Z
dee dœdd„Zdd„ Zdee dœdd„Zdee dœdd„Zdd„ Z‡  ZS )ÚUnetOnnxModelr   )ÚmodelÚ	num_headsÚhidden_sizec                    s>   |dkr|dks(|dkr$|| dks(t ‚tƒ j|||d dS )aG  Initialize UNet ONNX Model.

        Args:
            model (ModelProto): the ONNX model
            num_heads (int, optional): number of attention heads. Defaults to 0 (detect the parameter automatically).
            hidden_size (int, optional): hidden dimension. Defaults to 0 (detect the parameter automatically).
        r   )r   r   N)ÚAssertionErrorÚsuperÚ__init__)Úselfr   r   r   ©Ú	__class__© úZ/var/www/html/venv/lib/python3.8/site-packages/onnxruntime/transformers/onnx_model_unet.pyr      s    (zUnetOnnxModel.__init__c                 C   s   |   ¡  d S ©N)Úremove_useless_div©r   r   r   r   Ú
preprocess&   s    zUnetOnnxModel.preprocessc                 C   s   |   ¡  |  ¡  d S r   )Zprune_graphZremove_unused_constantr   r   r   r   Úpostprocess)   s    zUnetOnnxModel.postprocessc                 C   s~   dd„ |   ¡ D ƒ}g }|D ]}|  |d¡dkr| |¡ q|D ]}|  |jd |jd ¡ q>|rz|  |¡ t dt	|ƒ¡ dS )zRemove Div by 1c                 S   s   g | ]}|j d kr|‘qS )ÚDiv)Zop_type)Ú.0Únoder   r   r   Ú
<listcomp>/   s     
 z4UnetOnnxModel.remove_useless_div.<locals>.<listcomp>g      ð?é   r   zRemoved %d Div nodesN)
ÚnodesZfind_constant_inputÚappendÚreplace_input_of_all_nodesÚoutputÚinputZremove_nodesÚloggerÚinfoÚlen)r   Z	div_nodesÚnodes_to_removeÚdivr#   r   r   r   r   -   s    
z UnetOnnxModel.remove_useless_divc                 C   s   t | dd}| ¡  d S )NT)Zupdate_weight)r   Úapply)r   Zconv_to_nhwc_convr   r   r   Úconvert_conv_to_nhwc=   s    z"UnetOnnxModel.convert_conv_to_nhwcc                 C   sØ   t | ƒ}| ¡  d}|  d¡}|D ]’}t |d¡}t|tƒs@t‚|ttt	|ƒƒƒkrVq"|  
|jd ¡s†|  |jd ¡s†|  
|jd ¡rŠt‚|  |jd |jd ¡ |  |¡ |d7 }q"t	|jƒ| }|rÔt d|¡ d S )Nr   Z	TransposeÚpermr%   zRemoved %d Transpose nodes)r   r0   Úget_nodes_by_op_typer   Zget_node_attributeÚ
isinstanceÚlistr   Úranger-   Zfind_graph_outputr)   Zfind_graph_inputr*   r(   Úremove_noder.   r+   r,   )r   Úfusion_transposeZremove_countr&   r#   ZpermutationÚtotalr   r   r   Úmerge_adjacent_transposeB   s*    
ÿþý

z&UnetOnnxModel.merge_adjacent_transposeN)Úoptionsc                 C   s`   |d kp|j }t| | j| jd|dd}| ¡  |d kp:|j}t| | j| jdd|d}| ¡  d S )NF)Zis_cross_attentionÚenable_packed_qkvÚenable_packed_kvT)r<   r   r   r   r0   r=   )r   r;   r<   Zself_attention_fusionr=   Zcross_attention_fusionr   r   r   Úfuse_multi_head_attention^   s(    úúz'UnetOnnxModel.fuse_multi_head_attentionc                 C   s   t | ƒ}| ¡  d S r   )r   r0   )r   Úfusionr   r   r   Úfuse_bias_addw   s    zUnetOnnxModel.fuse_bias_addc              	   C   sn   t dƒrTdd l}ddlm} |ƒ * d}|jt|ƒddd}|  ||¡ W 5 Q R X nt d¡ |  |d ¡ d S )NÚtqdmr   )Úlogging_redirect_tqdmé   r?   )ÚinitialÚdescz<tqdm is not installed. Run optimization without progress bar)r   rA   Ztqdm.contrib.loggingrB   r6   Ú	_optimizer+   r,   )r   r;   rA   rB   ZstepsÚprogress_barr   r   r   Úoptimize{   s    
zUnetOnnxModel.optimizec                 C   sÔ  |d k	r|j s|  ¡  | j ¡  |r.| d¡ | j ¡  |rF| d¡ |d ksT|jr\|  ¡  |rj| d¡ |d ksx|jr€|  	¡  |rŽ| d¡ |  
¡  |r¤| d¡ |  ¡  |rº| d¡ |d ksÈ|jrø|d kpÔ|j}t| |ƒ}| ¡  t| ƒ}| ¡  |r| d¡ |d ks|jr*t| ƒ}| ¡  |r:| d¡ |d ksL|jrV|  |¡ |rf| d¡ |d ksx|jr€|  ¡  |r| d¡ |  ¡  |r¨| d¡ | j ¡  |rÂ| d¡ |d ksÔ|jrät| ƒ}| ¡  |rô| d¡ |d ks|jr|  ¡  |r| d¡ |d k	r8|jr8|  ¡  |rH| d¡ |d ksZ|jrj|   ¡  |  !¡  |rz| d¡ |d k	r”|j"r”|  #¡  |r¤| d¡ |  $¡  |r¼| d¡ t% &d|  '¡ › ¡ d S )Nr%   zopset version: )(Zenable_shape_inferenceZdisable_shape_inferenceÚutilsZremove_identity_nodesÚupdateZremove_useless_cast_nodesZenable_layer_normZfuse_layer_normZenable_geluZ	fuse_gelur   Zfuse_reshapeZenable_group_normZgroup_norm_channels_lastr   r0   r
   Zenable_bias_splitgelur   Zenable_attentionr>   Zenable_skip_layer_normZfuse_skip_layer_normZ
fuse_shapeZremove_useless_reshape_nodesZenable_skip_group_normr	   Zenable_bias_skip_layer_normZfuse_add_bias_skip_layer_normZenable_gelu_approximationZgelu_approximationZenable_nhwc_convr1   r:   Zenable_bias_addr@   r    r+   r,   Zget_opset_version)r   r;   rG   Zchannels_lastZgroup_norm_fusionZinsert_transpose_fusionZbias_split_gelu_fusionZskip_group_norm_fusionr   r   r   rF   ˆ   s–    






















zUnetOnnxModel._optimizec              	   C   sN   i }ddddddddd	g	}|D ]}|   |¡}t|ƒ||< qt d
|› ¡ |S )z8
        Returns node count of fused operators.
        Z	AttentionZMultiHeadAttentionZLayerNormalizationZSkipLayerNormalizationZBiasSplitGeluZ	GroupNormZSkipGroupNormZNhwcConvZBiasAddzOptimized operators:)r3   r-   r+   r,   )r   Zop_countZopsÚopr&   r   r   r   Úget_fused_operator_statisticsí   s     ÷
z+UnetOnnxModel.get_fused_operator_statistics)r   r   )N)N)NN)Ú__name__Ú
__module__Ú__qualname__r   Úintr   r   r    r   r1   r:   r   r   r>   r@   rH   rF   rL   Ú__classcell__r   r   r   r   r      s   er   ) ÚloggingÚtypingr   Zfusion_attention_unetr   Zfusion_bias_addr   Zfusion_biassplitgelur   Zfusion_group_normr   Zfusion_nhwc_convr   Zfusion_optionsr   Zfusion_skip_group_normr	   r8   r
   r   Zimport_utilsr   Zonnxr   Z
onnx_modelr   Zonnx_model_bertr   Ú	getLoggerrM   r+   r   r   r   r   r   Ú<module>   s   
