o
    e]E                     @   s8   d dl mZ G dd deZdd ZG dd deZdS )	    )PaddleGraphc                   @   s>   e Zd Zdd ZdddZdd Zdd	 Zd
d Zdd ZdS )PatternMatcherc                 C   s   || _ t | _d S N)patternlistmatches)selfr    r	   RD:\Projects\ConvertPro\env\Lib\site-packages\x2paddle/optimizer/pattern_matcher.py__init__   s   zPatternMatcher.__init__topoc                 C   sH   |dkr
|  | n|dkr| | n	|dkr| | |   | jS )Nr   edgeop)detect_patterns_by_topodetect_patterns_by_edgedetect_patterns_by_opremove_overlapped_matchr   )r   graph
match_kindr	   r	   r
   operate   s   
zPatternMatcher.operatec                    s   d fdd	 t |j D ]3\}\}} | j||}|r(|| jvr(| j| t |jD ]\}}t|jdkr@| |j|  q-qdS )uv    找到与模式匹配的子图，
            并将子图的id以拓扑排序存放到subgraph_id2layers。
        Fc                    s,  d}|   }t| }t }tt|j |d  }| D ]\}	}
| jt| j |  }|
j|jkr|
||	< |j}|	|jv r|| jvrX|dksO|rR dS |	|	 q t
|j|	 t
| j| kru|dksl|ro dS |	|	 q |j|	 }| j| }tt
|D ]7}|| }|| }|dkrt| }||vr  dS ||||krq|dks|r  dS |	|	 qq|	|jv rr|| jvrd|
jv rd|
jvr|jdd  }n|j}t|| js|dks|r dS |	|	 q n}t
|j|	 t
| j| kr6d|
jv rd|
jvr|jdd  }n|j}t|| js5|dks,|r/ dS |	|	 q n<|j|	 }| j| }d}tt
|D ] }|| }|| }|dkrg|| j| j| jkrgd} nqH|rr|	|	 q |
jdks~|
jd	krt
|jt
|
jkr|dks|r dS |	|	 q d}t|jD ] \}} |j| |
j| ddd
}|dur|| qd} |s|dks|r dS t| |	}t| |d  D ]}|	| qq |d7 }|t
| jkr|  S q |dks|r	 dS q |t
| jkr|S dS )Nr   Fz	paddle.nnZ
functional   Tzprim.ifz	prim.loop)is_subblock)get_global_layersr   keysdictlayersitemskernelidedges_inpoplenrangeindex	edges_outZoutputssetissubsetblocks	enumerateupdate)r   r   start_indexr   Zpattern_indexpattern_id2layerspattern_idssubgraph_id2layersgraph_layerslayer_idlayerpattern_layerpattern_layer_idZlayer_inZpattern_layer_iniZlayer_id_inpattern_layer_id_inZsubgraph_idsZpattern_layer_optZ	layer_outZpattern_layer_outZis_popZlayer_id_outpattern_layer_id_outZis_subblock_matchb
match_infor$   keyget_subgraphr	   r
   r;   )   s  








	

	




z<PatternMatcher.detect_patterns_by_topo.<locals>.get_subgraphr   N)F)	r)   r   r   r   r   appendr(   r"   r   )r   r   r4   r0   r1   r8   jblockr	   r:   r
   r   $   s    z&PatternMatcher.detect_patterns_by_topoc           	      C   x   dd }t |j D ].\}\}}|| j||}|r | j| t |jD ]\}}t|jdkr8| |j|  q%qdS )uF   当遇见顺序没有强制规定的pattern时使用该方式
        c                    s     t d }t t j | } j fddttkrH||}|dkr<dS ttkrFS dS d S )Nr   c           	         s0  |  }| }|j |j krdS || < j|ddkrStj| t j|  kr-dS tj| D ]\}}|dkr=q4|v rR j|  | }|v rMq4|| q4j|ddkr|  jvrcdS tj| t j|  krsdS tj| D ]\}}|v r j|  | }|v rqz|| qzd S d S )NFr   r   )r   r    getr"   r)   r%   )	r0   r3   r1   r2   r4   r5   Znew_layer_id_inr6   Znew_layer_id_outr   r/   r   r,   r-   r.   r*   r	   r
   r*      sN   


zLPatternMatcher.detect_patterns_by_edge.<locals>.get_subgraph.<locals>.updateFr   r   r   r   r   r"   )r   r   r+   r3   r0   outr	   rA   r
   r;      s   "
z<PatternMatcher.detect_patterns_by_edge.<locals>.get_subgraphr   N)	r)   r   r   r   r   r<   r(   r"   r   	r   r   r;   r4   r0   r1   r8   r=   r>   r	   r	   r
   r      s   4z&PatternMatcher.detect_patterns_by_edgec           	      C   r?   )u-    当只匹配op时使用此方式。
        c                    s   |   t }|d }t t|j | }|j  fdd}ttkrD|||}|dkr8dS ttkrBS dS d S )Nr   c                    s,    |  }| }|j |j krdS || < d S )NF)r   )r0   r3   r1   r2   r/   r,   r.   r	   r
   r*     s
   zJPatternMatcher.detect_patterns_by_op.<locals>.get_subgraph.<locals>.updateFrB   )r   r   r+   r-   r3   r0   r*   rC   r	   rE   r
   r;      s   
z:PatternMatcher.detect_patterns_by_op.<locals>.get_subgraphr   N)	r)   r   r   r   r   r<   r(   r"   r   rD   r	   r	   r
   r      s   z$PatternMatcher.detect_patterns_by_opc                 C   s`   g }t | jD ]&\}}d}| D ]}||v r!| j| d} nq|s-|t|  qdS )u>    如果2个子图有重叠，只取前一个子图。
        FTN)r)   r   r   r!   extendr   )r   Z	match_idsr4   matchZis_overlappedr   r	   r	   r
   r      s   z&PatternMatcher.remove_overlapped_matchNr   )	__name__
__module____qualname__r   r   r   r   r   r   r	   r	   r	   r
   r      s    

 @%r   c                 C   s   | d}t|dkr|S | dkr!|d }| d|dd 7 } n| d |d  }| dd|dd  7 } |j| jt|d  }d|dd }t| ||S )u   根据prefix_layer_id和suffix_layer_id获取需要子图。
        Args:
            prefix_layer_id (str): 起初为一个空字符串，之后为suffix_layer_id分割出来的前缀。
            suffix_layer_id (str): 起初为以一个layer的id，之后将分割部分给prefix_layer_id；例如”57.0.1“；
            graph (x2paddle.core.program.PaddleGraph): 需要进行pass的子图。
    .r    r   N   )splitr"   joinr   r(   intr;   )Zprefix_layer_idZsuffix_layer_idr   Zid_partr0   subgraphr	   r	   r
   r;   /  s   
r;   c                   @   s0   e Zd Zdd ZdddZdddZdd	 Zd
S )FuseBasec                 C   s   t  | _t | _t | _d S r   )r   r   r   patternsr&   	rm_params)r   r	   r	   r
   r   E  s   zFuseBase.__init__r   c                 C   s|   |j }|   | || | jD ]}t| d }td||}| ||| q| | | j	D ]}|
| q0|  d S )Nr   rM   )
parametersZbuild_patternperform_pattern_matcherr   r   r   r;   Zinsert_new_layerdelete_matchrU   r!   build)r   r   r   rV   rG   first_layer_idrR   
param_namer	   r	   r
   r   J  s   


zFuseBase.operatec                 C   s^   t | jdkr!t | _| jD ]}t|}| j||| qdS t| j}|||| _dS )u7    执行模式匹配，找到匹配的子图。
        r   N)r"   rT   r   r   r   rF   r   r   )r   r   r   r   Zpattern_matcherr	   r	   r
   rW   W  s   

z FuseBase.perform_pattern_matcherc                 C   sb   | j D ]+}t|dkrqt| d }td||}| D ]\}}||jv r-|j| qqdS )u<    删除不需要的中间layer及其对应参数。
        r   rM   N)r   r"   r   r   r;   r   r   r!   )r   r   rG   rZ   rR   r0   r1   r	   r	   r
   rX   c  s   

zFuseBase.delete_matchNrH   )rI   rJ   rK   r   r   rW   rX   r	   r	   r	   r
   rS   D  s
    

rS   N)Zx2paddle.core.programr   objectr   r;   rS   r	   r	   r	   r
   <module>   s     