o
    pi._                     @  s  d dl mZ 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 d dlmZ d d	lmZ g d
ZG dd dZG dd dZG dd dZG dd dZdd Zedd ZdTddZdd Zdd Zdd Zd d! Zd"d# Zd$d% Z d&d' Z!d(d) Z"d*d+ Z#d,d- Z$d.d/ Z%d0d1 Z&d2d3 Z'd4d5 Z(d6d7 Z)d8d9 Z*d:d; Z+d<d= Z,d>d? Z-d@dA Z.dBdC Z/dDdE Z0edUdHdIZ1dJdK Z2dLdM Z3dNdO Z4dPdQ Z5dRdS Z6dS )V    )annotationsN)Sequence)	lru_cache)Any)pir)core)get_used_external_value)signature_safe_contextmanager)Sz	pd_op.absz	pd_op.addz
pd_op.amaxz
pd_op.aminzpd_op.anglezpd_op.argsortzpd_op.assignzpd_op.batch_norm_z
pd_op.castz
pd_op.ceilzpd_op.concatz	pd_op.coszpd_op.cumprodzpd_op.cumsumzpd_op.dividez	pd_op.dotzpd_op.dropoutzpd_op.elementwise_powz	pd_op.erfz	pd_op.expzpd_op.expandzpd_op.floorz
pd_op.fmaxz
pd_op.fminzpd_op.gatherzpd_op.gather_ndz
pd_op.geluzpd_op.group_normzpd_op.hardsigmoidzpd_op.hardswishz
pd_op.kronzpd_op.kthvaluezpd_op.layer_normzpd_op.leaky_reluz	pd_op.logzpd_op.logcumsumexpzpd_op.logsumexpzpd_op.matmulz	pd_op.maxzpd_op.maximumz
pd_op.meanzpd_op.minimumzpd_op.multiplyz	pd_op.padz	pd_op.powz
pd_op.prodzpd_op.reduce_asz
pd_op.reluzpd_op.relu6zpd_op.reshapez
pd_op.rollzpd_op.rsqrtzpd_op.scalezpd_op.scatterzpd_op.scatter_nd_addzpd_op.sigmoidz
pd_op.siluz	pd_op.sinzpd_op.softmaxzpd_op.softsignzpd_op.splitz
pd_op.sqrtzpd_op.squarezpd_op.squeezezpd_op.stackzpd_op.subtractz	pd_op.sumzpd_op.swigluzpd_op.swishzpd_op.take_along_axisz
pd_op.tanhz
pd_op.tilez
pd_op.topkzpd_op.transposezpd_op.trunczpd_op.unsqueezezpd_op.wherezpd_op.p_normzpd_op.index_putzpd_op.index_addz	pd_op.eluzpd_op.masked_fillzpd_op.masked_selectc                   @  s*   e Zd ZdddZdddZdd	d
ZdS )ValueWrapperreturnNonec                 C  sb   t |trt |jtd tjfsJ nt |td tjfs!tdt |tr,|j| _d S || _d S )Nz0Value Wrapper is only support None and pir.Value)
isinstancer
   _valuetyper   Value	TypeError)selfvalue r   e/home/app/PaddleOCR-VL/.venv_paddleocr/lib/python3.10/site-packages/paddle/autograd/backward_utils.py__init__w   s   
 zValueWrapper.__init__intc                 C  s"   t | jtjr| j S t| jS N)r   r   r   r   hashr   r   r   r   __hash__   s   

zValueWrapper.__hash__boolc                 C  sX   t |tstd|j d dS | jd u s|jd u r%| jd u o$|jd u S | j|jS )NzMIn ValueWrapper.__eq__ expected type of `other` is ValueWrapper but received .F)r   r
   warningswarn	__class__r   is_samer   otherr   r   r   __eq__   s   
zValueWrapper.__eq__Nr   r   )r   r   )r   r   )__name__
__module____qualname__r   r   r$   r   r   r   r   r
   v   s    


r
   c                   @  s   e Zd Z	d'ddddZdd Zdd Zd	d
 Zdd Zdd Zd'ddZ	dd Z
d'ddZd(ddZdd Zdd Zdd Zdd  Zd!d" Zd)d%d&ZdS )*	ValueDictNdefault_factoryc                C  s6   i | _ || _|d ur| D ]
\}}|| |< qd S d S r   )_items_default_factoryitems)r   iterr+   keyvalr   r   r   r      s   
zValueDict.__init__c                 C  s   t  }| j |_| j|_|S r   )r)   r,   copyr-   r   retr   r   r   r2      s   zValueDict.copyc                 C  s   |  D ]\}}|| |< qd S r   )r.   )r   
other_dictr0   r1   r   r   r   update   s   
zValueDict.updatec                 c  s    | j  D ]}|jV  qd S r   )r,   keysr   r   r0   r   r   r   r7      s   
zValueDict.keysc                 C  s
   | j  S r   )r,   valuesr   r   r   r   r9         
zValueDict.valuesc                 c  s&    | j  D ]
\}}|j|fV  qd S r   )r,   r.   r   r   r0   r1   r   r   r   r.      s   zValueDict.itemsc                 C  s   |  |s|S | jt| S r   )__contains__r,   r
   r   r0   defaultr   r   r   get   s   
zValueDict.getc                 C  s(   |  |st| d| jt|S Nz is not in ValueDict)r<   KeyErrorr,   popr
   r8   r   r   r   rB      s   
zValueDict.popc                 C  s   |  |s	|| |< | | S r   )r<   r=   r   r   r   
setdefault   s   
zValueDict.setdefaultr1   r   c                 C  s   || j t|< d S r   )r,   r
   r;   r   r   r   __setitem__   s   zValueDict.__setitem__c                 C  s>   |  |s| jd ur|  | |< nt| d| jt| S r@   )r<   r-   rA   r,   r
   r8   r   r   r   __getitem__   s
   

zValueDict.__getitem__c                 C  
   t | jS r   )r   r,   r   r   r   r   __bool__   r:   zValueDict.__bool__c                 C  rF   r   )lenr,   r   r   r   r   __len__   r:   zValueDict.__len__c                 C  s   |   S r   )r7   r   r   r   r   __iter__   s   zValueDict.__iter__c                 C     t || jv S r   )r
   r,   r8   r   r   r   r<         zValueDict.__contains__r   strc                 C  s$   d dd |  D }d| dS )N, c                 s  s"    | ]\}}| d | V  qdS )z: Nr   ).0r0   r1   r   r   r   	<genexpr>   s     z%ValueDict.__repr__.<locals>.<genexpr>z
ValueDict())joinr.   r   Z	items_strr   r   r   __repr__   s   zValueDict.__repr__r   )r1   r   r   rM   )r&   r'   r(   r   r2   r6   r7   r9   r.   r?   rB   rC   rD   rE   rG   rI   rJ   r<   rT   r   r   r   r   r)      s(    


r)   c                   @  s   e Zd Z	d&d'ddZdd Zdd	 Zd(ddZdd Zdd Zdd Z	d)ddZ
d)ddZd)ddZdd Zdd Zdd Zd d! Zd*d$d%ZdS )+ValueSetNr/   1Sequence[ValueWrapper] | set[ValueWrapper] | Nonec                 C  s,   t  | _|d ur|D ]	}| | q
d S d S r   )set_setadd)r   r/   r1   r   r   r   r      s   zValueSet.__init__c                 C  s   t  }| j |_|S r   )rV   rY   r2   r3   r   r   r   r2      s   zValueSet.copyc                 C  s"   |  |s| jt| d S d S r   )r<   rY   rZ   r
   r   r1   r   r   r   rZ      s   
zValueSet.addr#   rX   c                 C  s   |D ]}|  | qd S r   )rZ   )r   r#   r1   r   r   r   r6      s   zValueSet.updatec                 C  s   | j  jS r   )rY   rB   r   r   r   r   r   rB      s   zValueSet.popc                 C     | j t| d S r   )rY   remover
   r[   r   r   r   r]         zValueSet.removec                 C  r\   r   )rY   discardr
   r[   r   r   r   r_      r^   zValueSet.discardc                 C  s   t | j|j@ S r   rV   rY   r"   r   r   r   __and__      zValueSet.__and__c                 C  s   t | j|j S r   r`   r"   r   r   r   __sub__  rb   zValueSet.__sub__c                 C  s   t | j|jB S r   r`   r"   r   r   r   __or__  rb   zValueSet.__or__c                 C  rF   r   )r   rY   r   r   r   r   rG     r:   zValueSet.__bool__c                 C  rF   r   )rH   rY   r   r   r   r   rI     r:   zValueSet.__len__c                 c  s    | j D ]}|jV  qd S r   )rY   r   r[   r   r   r   rJ     s   

zValueSet.__iter__c                 C  rK   r   )r
   rY   r[   r   r   r   r<     rL   zValueSet.__contains__r   rM   c                 C  s    d dd | D }d| dS )NrN   c                 s  s    | ]}t |V  qd S r   )repr)rO   itemr   r   r   rP         z$ValueSet.__repr__.<locals>.<genexpr>z	ValueSet(rQ   )rR   rS   r   r   r   rT     s   zValueSet.__repr__r   )r/   rW   )r#   rX   )r#   rV   rU   )r&   r'   r(   r   r2   rZ   r6   rB   r]   r_   ra   rc   rd   rG   rI   rJ   r<   rT   r   r   r   r   rV      s"    



rV   c                   @  s*   e Zd ZdZdd ZdddZdd	 Zd
S )Statez
    record relationship of forward op/value and backward op/value
    one state must be binding with a block, if block has parent block,
    state will include parent block info.

    c                 C  sZ   || _ ttd| _ttd| _tt| _ttd| _ttd| _	tt| _
t | _d S )Nr*   )blockr)   listvalue_to_valuegradvalue_to_sumvaluegradcollectionsdefaultdictop_to_opgradvaluegrad_to_valuesumvaluegrad_to_valueopgrad_to_op!inside_value_to_outside_value_map)r   ri   r   r   r   r   "  s   zState.__init__r   r   c                 C  s   t td| _t td| _tt| _| j D ]\}}|g kr,|d D ]}|g| j|< q#q| j	 D ]\}}|g krG|d D ]}|g| j|< q>q2| j
 D ]\}}|g kr]|g| j|d < qMd S )Nr*   r   )r)   rj   rp   rq   rm   rn   rr   rk   r.   rl   ro   )r   kvr   r   r   r   turn_map4  s$   zState.turn_mapc                 C  s`   t |}| j |_| j |_| j |_| j |_| j |_| j |_| j |_|S r   )	rh   rk   r2   rl   ro   rp   rq   rr   rs   )r   Z	new_blockstater   r   r   r2   E  s   z
State.copyNr%   )r&   r'   r(   __doc__r   rv   r2   r   r   r   r   rh     s
    
rh   c                 C  s:   |D ]}|D ]}|  r| rd|jv r  dS qqd S )NT)Zis_dense_tensor_typeZinitializedshape)opinputsr.   rf   r   r   r   _check_vjp_dynamic_shape[  s   
r}   c              	   c  s    t  }|  dkrd}n|ot  ot| |o|  tv}z|r)|r)t d d V  W |r6t d d S d S |r@t d w w )Ncf.tuple_pushTF)r   Z_is_bwd_prim_enablednameZ_enable_prim_skip_dynamic_shaper}   ALLOW_DYNAMIC_SHAPE_VJP_OPSZ_set_prim_backward_enabled)r{   r|   Zorigin_primZ	skip_primr   r   r   dynamic_shape_prim_vjp_guardg  s(   

r    c                 C  s8   t | |std| d| d| dt|  d| 
d S )NzThe type of 'z' in z	 must be z, but received z. )r   r   r   )inputZ
input_nameexpected_typeZop_nameZextra_messager   r   r   
check_type}  s
   
$r   c                 C  s$   | d u rg S t | trt| S | gS r   )r   r   rj   )xr   r   r   _as_list  s   r   c                   s   t  fdd| D S )Nc                 3  s    | ]}| v V  qd S r   r   )rO   ru   	value_setr   r   rP     rg   zsome_in_set.<locals>.<genexpr>)any)Z
value_listr   r   r   r   some_in_set  s   r   c                 C  s   |   dkp|   dkS )Npd_op.ifpd_op.while)r   r{   r   r   r   is_control_flow  s   r   c                 C  s   |   d\}}|dkS )Nr   builtin)r   split)r{   Zdialect_nameopnamer   r   r   is_builtin_op  s   r   c                 C  sV   | j D ]%}t|r| D ]}t|| q| D ]}|jr'||vr'|| qqd S r   )opsr   blocks"update_no_grad_set_by_stopgradientresultsstop_gradientrZ   )ri   Zno_grad_setr{   	sub_blockr   r   r   r   r     s   

r   c                 C  sT   |   dkr
t| S |   dkr|  t|    S |   dkr&t| S |  S )Nr   r   pd_op.pylayer)r   r   operands_sourceas_while_opbodyr   r   r   r   get_real_op_inputs  s   
r   c                 C  s|   |   }|  dkr|  D ]	}||  q|  dkr<|   jD ]}| dkr;| D ]	}||  q1q%|S )Npd_op.array_write_r   )r   r   Zoperandsappendsourcer   r   r   )r{   Zoutputsr   Zinternal_opr   r   r   get_real_op_outputs  s   r   c                   s  t t}g   fdd| D  t }g } D ]}t|D ]}t|s5| |v r5||   d7  < qqt  } D ]}|| dkrJ|	| q=|rv|
 }|	| t|D ]}| }||  d8  < || dkrs|	| qZ|sMt|t krtdg }t|D ]A}| dkr||}	||}
t|d|| D ]}t| tt|r| dkr||}
q|	|
kr|	|	|
f q|D ]\}	}
||
 ||	 ||	< ||
< q|S )	zH
    if topo graph is op1 -> op2 -> op3
    return [op3, op2, op1]

    c                   s   g | ]}| vr  |qS r   )r   )rO   r   r   r   r   
<listcomp>  s    z#inverse_sort_op.<locals>.<listcomp>   r   zHinverse_sort_op wrong, sorted_list size is not equal to origin_list sizezpd_op.increment_Nr~   )rm   rn   r   rX   r   r   Zis_fake_valueget_defining_opdequer   popleftrH   
ValueErrorreversedr   indexr   r   rV   )Zold_opspending_countZops_setsorted_listr{   r   queueZx_opZchange_listZidx_1Zidx_2Zop_inr   r   r   inverse_sort_op  sh   




	



r   c                 C  sH   | D ]}|  dv r dS t|r!| D ]}t|jr   dS qqdS )zX
    when program has inplace op , it's difficult to find the actual pending_count.
    )r   zpd_op.assign_out_TF)r   r   r   is_inplace_netr   )op_listr{   ri   r   r   r   r      s   
r   c                 C  s   |j | g kr|j | d }|j| | | D ]#}|j| g kr=|j| d }g |j|< ||jv r=td|  q| 	| dS )z
    remove op from block
    r   z.input_grad in [%s] is value which need to sum N)
rr   ro   r]   r   rp   rk   rq   r   r   	remove_op)ri   r{   rw   Zfwd_opZ	valuegradr   r   r   r   r     s   

r   c                 C  s4   t | dkr| d  D ]	}| s dS qdS dS )Nr   FT)rH   r   	use_empty)Zwhile_tuple_opsZopresultr   r   r   while_prune_check&  s   r   c                 C  s   g }t t|}|D ]3}| dkr+|d r*|d }|| || q
t|r=|	 D ]	}t
||j| q3q
|D ]}t| || q@dS )z7
    remove ops which are not in use recursively,

    zpd_op.full_liker   r   N)r   rj   r   resultr   operand_sourcer   r   r   r   remove_useless_full_like_opsr   r   )ri   r   rw   Z
remove_opsZinverse_opsr{   Zfull_opr   r   r   r   r   /  s    

r   c                 C  s0   | j D ]}| D ]}|jdu r  dS q	qdS NFT)r   r   r   )ri   r{   r   r   r   r   all_stop_gradient_trueE  s   

r   c                 C  s(   | D ]}|D ]
}|du r  dS qqdS r   r   )list_of_listlist_r   r   r   r   all_input_stop_gradient_trueM     r   c                 C  s(   | D ]}|D ]
}|d ur  dS qqdS r   r   )r   r   r   r   r   r   all_output_grad_noneU  r   r   c                 C  s   t | p
|  dkS )Nr   )r   Zhas_vjpr   r   r   r   r   
op_has_vjp]  s   r   c                 C  s>   g }| j dur| j j r|| j j j7 }|| j j7 }|| j7 }|S )z
    when block is sub_block, forward op should include its parent block ops
    (sub block nest should Add on demand to avoid block copy)
    N)parent_blockr   )ri   Z	total_opsr   r   r   parent_total_opse  s   

r   c                 C  s    | }||v r|| }||v s|S r   r   )r   mapoutputr   r   r   return_map_valueu  s
   r   c                 C  sJ   g }t t| D ]}| | |v r|t| | | q|| |  q|S r   )rangerH   r   r   )r   r   r   ir   r   r   return_map_value_list|  s   r   c                 C  s   |   dkrt t fS t|   d t|  ks J dt }t }t|   |  dd D ]\}}|||< |||< q5||fS )zp
    return while op's relationship of (block_argument to input value) and (input value to block_argument).
    r   r   zRwhile op's block_arguments size + 1 should same to while op's operands_source sizeN)r   r)   rH   r   Zblock_argumentsr   zip)while_opZarg_to_value_mapZvalue_to_arg_mapargr   r   r   r   argument_to_value  s    

r   c                 C  sJ   |   dv rdd ttt| D }|   dkrd|d< |S |  }|S )z
    return whether op's inputs has grad, usually handled from yaml.
    some op has uncertain inputs need special handling.
    )zbuiltin.combiner   r   r   r~   zdist_op.moe_global_mesh_tensorzdist_op.moe_sub_mesh_tensorszdist_op.dist_reshapec                 S  s   g | ]}d qS )Tr   )rO   _r   r   r   r     s    z*get_grad_semantic_info.<locals>.<listcomp>r   Fr   )r   r   rH   r   Zget_input_grad_semantics)r{   Zgrad_semantic_infor   r   r   get_grad_semantic_info  s   
r   c                 C  s&   |   D ]}| dkr|  S qd S )Nzbuiltin.split)Zall_used_opsr   )r   r{   r   r   r   get_split_op  s
   r   messagerM   c                 C  s   t |  d S r   )loggingwarning)r   r   r   r   warning_once  s   r   c                 C  s   |  dks|  dkrtdt| t| kr tdt|  t| kr0tdtt| D ]}||j}||j}|rJ|sPd| |_q8dS )z
    Update if_op's stop_gradient based on true_yield_op and false_yield_op.

    Args:
    true_yield_op: true block of if_op's last op.
    false_yield_op: false block of if_op's last op.
    if_op: update it's op_results()'s stop_gradient.
    cf.yieldzparam is not yield opz&Mismatched yield operands_source sizesz8Mismatched if op_results size with yield operands_sourceFN)	r   r   rH   r   r   r   r   r   r   )Zif_opZtrue_yield_opZfalse_yield_opr   Z
stop_grad1Z
stop_grad2r   r   r   update_if_output_stopgradient  s$   
r   c                 C  s   |  dkr
tdt|  d t| kr+tdt|  d t| f tdt| D ]}||j}|sFd| |d _q4dS )z
    Update while_op's stop_gradient based on yield_op.

    Args:
    yield_op: The yield operation associated with the while loop.
    while_op: The while operation whose op_results()'s stop_gradient needs to be updated.
    r   z!yield_op is not a yield operationr   zDMismatched while op_results  size %d with yield operands_source %d. FN)	r   r   rH   r   r   r   r   r   r   )r   yield_opr   Z	stop_gradr   r   r    update_while_output_stopgradient  s   	 r   c                 C  s,   t | D ]\}}|| r|  S qdS )Nry   )	enumerater   r!   )r   r   r   ru   r   r   r   find_index_of_yiled   s
   
r   c                 C  s   | g kr| S | d d   }| dksJ |d  }|d   }g }|D ].}|   dkrU|  }t||}|dksIJ ||	 j
| q,|| q,|dd  S )Nr   zcf.tuple_popr   r   ry   )r   r   r   r   Z	first_useownerr   r   r   get_parent_block	parent_op)Ztuple_pop_outputsr{   Zstack_opZtuple_push_inputsZtuple_push_inputs_with_ifr   r   r   r   r   r   update_tuple_pop_origin_inputs  s"   
r   c                 C  sJ   |    }|j dkr||krdS |j}|j dks||kr#dS dS )Nzbuiltin.moduleTF)r   r   r   r   r   )r   ri   Zvalue_blockr   r   r   value_in_block  s   r   )r   )r   rM   )7
__future__r   rm   r   r   collections.abcr   	functoolsr   typingr   Zpaddler   Zpaddle.baser   Zpaddle.base.libpaddle.pirr   Zpaddle.base.wrapped_decoratorr	   r   r
   r)   rV   rh   r}   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   <module>   sb   WM:A


E	
%