
    ͑i                      S SK Jr  S SKrS SKrS SKrS SKrS SKrS SKrS SKJ	r	  S SK
JrJr  S SKrSSKJrJrJrJr  SSKJr  SSKJr  SS	KJr  \(       a  S S
KJr  S SKJr  S SKJr  S SKJr  / r\R@                  " \!\RD                  SS9r# " S S5      r$S r% SAS jr&SAS jr'S r(SBS jr)S r*S r+S r,S r-S r.S r/S r0 SCS jr1  SDS jr2   SES  jr3S/ 4S! jr4S" r5S# r6 SAS$ jr7 SAS% jr8S& r9S' r:S( r;S) r<      SFS* jr=S+ r>S, r?S- r@S. rAS/ rBS0 rCS1 rDS2 rES3 rF\     SG             SHS4 jj5       rG\     SG             SIS5 jj5       rG\R                       SJS6 j5       rGS7 rIS8 rJS9 rKS: rL SKS; jrM SBS< jrNS= rOSBS> jrP\R                    SB         SLS? jj5       rQ\R                  SBS@ j5       rRg)M    )annotationsN)Sequence)TYPE_CHECKINGoverload   )core	framework
log_helperunique_name)
check_type)program_guard)framework_pb2)Callable)Tensor)Block)DistributedContextz&%(asctime)s-%(levelname)s: %(message)s)fmtc                  J    \ rS rSrS rS rS rS rS rS r	S r
S	 rS
 rSrg)ProgramStats1   c                8    Xl         X l        0 U l        0 U l        g N)blockopsop_depsvar_op_deps)selfr   r   s      T/var/www/html/banglarbhumi/venv/lib/python3.13/site-packages/paddle/base/backward.py__init__ProgramStats.__init__2   s    
    c                   / nU R                    H  n[        U R                   U   S   5      S:X  d  M$  [        U R                   U   S   5      S:  d  ME  U R                  R                  U5      R                  (       a  Mq  UR                  U5        M     U R                   HL  nUR                  R                  5       S:X  d  M#  UR                  UR                  R                  5       5        MN     U$ )Nvar_as_output_opsr   var_as_input_opsread)r   lenr   varpersistableappendr   desctypeextendoutput_arg_names)r   input_namesnameops       r   get_input_nodesProgramStats.get_input_nodes8   s    $$DD$$T*+>?@AE((./ABCaG::>>$'33""4( % ((Bww||~'""277#;#;#=>  r!   c                    / nU R                    HL  nUR                  R                  5       S:X  d  M#  UR                  UR                  R	                  5       5        MN     U$ )Nseed)r   r*   r+   r,   r-   )r   var_namer0   s      r   get_reserved_varsProgramStats.get_reserved_varsG   sG    ((Bww||~' 8 8 :;  r!   c                   / n[        XS5       H  nU R                  U   R                  R                  5        HE  nXPR                  ;   d  M  U R                  U   S    H  nXb:  d  M
  UR                  U5        M     MG     U R                  U   R                  R                  5        HE  nXPR                  ;   d  M  U R                  U   S    H  nXa:  d  M
  UR                  U5        M     MG     M     U$ )Nr   r$   r#   )ranger   r*   r-   r   r)   input_arg_names)r   begin_op_idx
end_op_idxr5   ir/   idxs          r   get_out_of_subgraph_vars%ProgramStats.get_out_of_subgraph_varsN   s    |3A((99;+++#//56HI,$OOD1  J <
 ((88:+++#//56IJ-$OOD1  K ; 4 r!   c                ~   [        U R                  5      nSnU H  nXPR                  ;  d  M  SX44s  $    U H  nXPR                  ;  d  M  SX44s  $    U H)  nU R                  U   S   nU H  n[        X75      nM     M+     U H)  nU R                  U   S   nU H  n[	        XG5      nM     M+     X4:  a  SX44$ SX44$ )NFr$   r#   T)r&   r   r   minmax)r   
var_group1
var_group2
min_op_idx
max_op_idxr/   op_idxr>   s           r   is_subgraphProgramStats.is_subgraph]   s     ]

D+++j44  D+++j44  D%%d+,>?F 1
   D%%d+,?@F 1
   #*00Z++r!   c                T  ^  U 4S jnUS-
  nUnXB:  a  U" T R                   U   5      (       ap  [        R                  ST R                   U   R                  R	                  5        ST R                   U   R                  R                  5       S    35        UnUS-  nO U$ XB:  a  M  U$ )zJ
persist vars of amp-related cast should be included in recompute segment
c                   > U R                   R                  5       S:H  =(       a@    TR                  R                  U R                   R	                  5       S   5      R
                  $ )Ncastr   )r*   r+   r   r'   r:   r(   )r0   r   s    r   is_amp_cast7ProgramStats._update_segment_start.<locals>.is_amp_cast{   sH    &( MJJNN277#:#:#<Q#?@LLr!   r   zfound amp-cast op: z, : r   )r   _loggerinfor*   r+   r:   )r   min_idxpre_segment_end_idxrO   idx_updated_min_idxs   `     r   _update_segment_start"ProgramStats._update_segment_startv   s    
	 {!(488D>**)$((4.*=*=*B*B*D)ET$((SW.J]J]JmJmJopqJrIst #'	 ( r!   c                   [        U R                  5       GH  u  p/ / S.U R                  U'   [        UR                  R	                  5       5       HG  u  p4X@R
                  ;   d  M  U R                  U   S   R                  U R
                  U   S   5        MI     [        UR                  R	                  5       5       Hl  u  p4X@R
                  ;   a$  U R
                  U   S   R                  U/5        M8  0 U R
                  U'   U/U R
                  U   S'   / U R
                  U   S'   Mn     [        UR                  R                  5       5       Hl  u  p4X@R
                  ;   a$  U R
                  U   S   R                  U/5        M8  0 U R
                  U'   / U R
                  U   S'   U/U R
                  U   S'   Mn     U R                  U   S    H%  nU R                  U   S   R                  U/5        M'     GM     g )N)in_opsout_opsrZ   r#   r$   r[   )	enumerater   r   r*   r:   r   r,   r-   )r   r=   r0   jr/   rI   s         r   build_statsProgramStats.build_stats   s   txx(EA)+;DLLO$RWW%<%<%>?+++LLOH-44((./BC @
 %RWW%<%<%>?+++$$T*+=>EEqcJ-/D$$T*BCD$$T*+=>BDD$$T*+>? @ %RWW%=%=%?@+++$$T*+>?FFsK-/D$$T*ACD$$T*+=>CD#D$$T*+>? A ,,q/(3V$Y/66s; 4/ )r!   c                d   / nU H  nX0R                   ;  a  [        R                  SU S35        M-  U R                   U   S   / :X  a  UR                  US45        MX  UR                  U[	        U R                   U   S   5      45        M     [        US S9nU Vs/ s H  oDS   PM	     sn$ s  snf )NzRecompute Optimizer: deleted z< from checkpoints, because it is not used in paddle program.r#   rB   c                    U S   $ )Nr    xs    r   <lambda>/ProgramStats.sort_checkpoints.<locals>.<lambda>   s    adr!   keyr   )r   rQ   rR   r)   rD   sorted)r   checkpoints_namesorted_checkpointsr/   rd   s        r   sort_checkpointsProgramStats.sort_checkpoints   s    $D+++3D69uv !!$'(;<B"))4*5"))3t//56IJKL % $$6NK010!0111s   B-c           
     L   U R                    Vs/ s H  oR                  R                  5       PM     nnSU;  a  g SnU[        U R                   5      :  GaI  U R                   U   nUR                  R                  5       S:w  a  US-  nMN  UR	                  S5      b%  [        UR	                  S5      5      S:X  a  US-  nM  [
        R                  " S5      n[
        R                  " SR                  US/5      5      nU R                  R                  US[        R                  R                  R                  S	S	S
9nUR                  S5      S	L a  SO[!        UR                  S5      5      n[        R"                  R%                  5       nSn	UR                  R'                  U5      (       a  UR                  R                  U5      n	U R                  R)                  UR*                  S0 SU/0XySS.S9n
U R                   R-                  X:5        UR                  R/                  SU/5        UR                  R1                  S5        UR                  R1                  S5        U R                  R3                  5         US-  nU[        U R                   5      :  a  GMH  g g s  snf )Ndropoutr   r   Seedr4   .tmpint32F)r/   dtyper+   r(   stop_gradientfix_seed OutT)r4   	op_device	force_cpu)indexr+   inputsoutputsattrs   )r   r*   r+   r&   inputr   generategenerate_with_ignorable_keyjoinr   
create_varr   VarDescVarTypeDENSE_TENSORattrintop_proto_and_checker_makerkOpDeviceAttrNamehas_attr
_insert_opr>   insert	set_inputremove_attr_sync_with_cpp)r   r0   op_typesrI   op_unique_namevar_unique_name	added_varr4   op_device_attr_namery   added_ops              r   !modify_forward_desc_for_recompute.ProgramStats.modify_forward_desc_for_recompute   s3   -1XX6XrGGLLNX6H$s488}$&!Bww||~*!xx+BHHV4D0E0J!(11&9N)EE.%01O 

--$\\))66!# . I 
+u41#bggfo:ND //AAC   Iww 344GGLL)<=	 zz,,ff,#$O - H HHOOF-GGf&78GG
+GG'JJ%%'aKF[ s488}$$ 7s   #J!)r   r   r   r   N)__name__
__module____qualname____firstlineno__r   r1   r6   r?   rJ   rW   r^   rl   r   __static_attributes__rb   r!   r   r   r   1   s/    ,22<62"3r!   r   c                    SR                  US-   [        U R                  5       5      US-   SR                  U R	                  5       5      US-   SR                  U R                  5       5      5      nU$ )Nz3{}	name:[{}]
{}    	inputs:[{}]
{}    	outputs:[{}]_op_input _output)formatstrr+   r   r:   r-   )op_descprefixout_ss      r   _pretty_op_desc_r      sh    FMMGLLN((*+))+,E Lr!   c                b   [        U 5      S:X  a  / $ / n[        R                  R                  5       n[        R                  R                  R
                  nU  GHR  nUn	Sn
[        U[        R                  5      (       a  UR                  nSn
[        U[        5      (       a  US   nSnUR                  5        HD  nUR                  U5      (       a"  UR                  U5      R                  (       a  M;  X;  d  MB  SnMF     U(       d  M  U
(       a  Ub  XUR                  5       '   UR                  R!                  5       nUR#                  U5        UR%                  Xg5        UR'                  S5      (       a!  UR%                  SUR)                  S5      5        UR+                  U5        GMU     U$ )Nr   FTry   )r&   r   r   kOpRoleAttrNameOpRoleBackward
isinstancer	   Operatorr*   tupler-   has_varr'   r(   original_id	append_op	copy_from	_set_attrr   r   r)   )descsr   
main_blockin_memory_varsgrad_op_id_to_fwd_opresult_descsop_role_attr_namebackwardr*   origin_descorigin_is_operator	is_neededr/   new_op_descs                 r   _add_needed_descs_to_blockr      sh    5zQ	L77GGI..55>>H"dI..//99D!%dE""7D	))+D!!$''JNN4,@,L,L) 		 ,
 9!&:&F;FT%5%5%78**..0K!!$'!!"3>}}[))%%k499[3IJ,- . r!   c                   [        U 5      S:X  a  / $ / n[        R                  R                  5       n[        R                  R                  R
                  nU  H  n[        U[        R                  5      (       a+  Ub  XbUR                  R                  5       '   UR                  n[        U[        5      (       a  US   nUR                  R                  5       nUR                  U5        UR                  XE5        UR                  S5      (       a!  UR                  SUR!                  S5      5        UR#                  U5        M     U$ )Nr   ry   )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   s           r   _add_descs_to_blockr     s   
5zQ	L77GGI..55>>HdI..//#/@DTYY%:%:%<=99DdE""7Djj**,d#/:==%%!!+tyy/EFK(  r!   c                B   [        U R                  R                  5       Hd  n[        U[        R
                  5      (       d   e[        UR                  5      S:X  d  M?  UR                  S   U R                  :X  d  M^  Xl	          O   U R                  c  [        S5      eg )Nr   r   z"loss.op is None. Should not happen)reversedr   r   r   r	   r   r&   r-   r/   r0   
ValueError)lossr0   s     r   _find_loss_op_r   6  s    tzz~~&"i001111##$)##A&$))3G ' ww=>> r!   c                   Uc  SnUc  [        U 5      n[        U [        [        45      (       aR  [	        X45       HC  nX   n[        U[        5      (       a  US   nUR                  X5        UR                  X5        ME     [        U [        R                  5      (       ab  U R                  5        HM  u  px[        U[        [        45      (       d  M"  U H%  nUR                  X5        UR                  X5        M'     MO     gg)z{
Traverse all ops in op_descs[begin_idx : end_idx],
if any op has inputs/outputs named "old_name", rename it as 'new_name'
Nr   )
r&   r   listr   r9   _rename_input_rename_outputcollectionsOrderedDictitems)	op_descsold_namenew_name	begin_idxend_idxr=   r   rh   values	            r   _rename_arg_r   C  s    
 	h-(T5M**y*AkG'5))!!*!!(5""86 + (K3344"..*JC%$//$G))(=**8>  % + 5r!   c                   [         R                  " 5       nUR                  U 5        UR                  5        HM  u  pVUR	                  UU Vs/ s H*  n[        U[        5      (       a  UR                  5       OUPM,     sn5        MO     UR                  5        HM  u  pVUR                  UU Vs/ s H*  n[        U[        5      (       a  UR                  5       OUPM,     sn5        MO     [         R                  R                  5       n[         R                  R                  5       n	X;  a&  [         R                  R                  R                  X8'   X;  a  SX9'   UR                  5        HR  u  p[        U[        R                  5      (       a  UR!                  XR"                  5        MA  UR%                  X5        MT     U$ s  snf s  snf )zK
Create a C++ OpDesc object with specified inputs, outputs and attributes.
rw   )r   OpDescset_typer   r   r   bytesdecode
set_outputr   r   r   r   r   r	   r   set_block_attrr*   r   )op_typer|   r}   r~   r   paraargsargr   r   r/   vals               r   _create_op_desc_r   [  sl    kkmGWlln
HLMZU33SZZ\<M	
 %
 mmo
HLMZU33SZZ\<M	
 &
 77GGI99KKM%++22;; 	  '%'"[[]	c9??++""42d(	 #
 N+ N
 Ns   1G-1Gc                x   [        U R                  5      S:X  d  SU R                  ;   a  U R                  nOS/n[        S0 S[        U R                  5      /0SUSSSU R
                  S	S
[        R                  R                  5       [        [        R                  R                  R                  5      [        [        R                  R                  R                  5      -  [        R                  R                  5       U R                  R                  [        R                  R                  5       5      05      nU$ )Nr   r   fill_constantrx   shaper         ?rt   rz   F)r&   r   r   _append_grad_suffix_r/   rt   r   r   r   r   r   r   Lossr   r0   r   )r   create_shaper   s      r   _create_loss_op_desc_r   |  s    
4::!qDJJzzs
	%dii012\STZZ++;;=s//66??@ $1188==>@? ++==?//AACB	
	G$ Nr!   c                2   UR                   R                  U R                  5       5      n[        U 5      nUR                   R	                  UR                  5       5      (       ah  UR                   R                  UR                  5       5      nUR                  UR                  5       5        UR                  UR                  5       5        g[        R                  " SU  S35        UR                  [        R                  R                  R                  5        g)z6
Infer the data type and shape of given grad variable
zSet grad var: zC dtype to default FP32, since we can't find its related forward varN)r*   find_varencode_strip_grad_suffix_has_var_recursivefind_var_recursive	set_dtypert   	set_shaper   warningswarnr   r   r   FP32)grad_var_namer   grad_varfwd_namefwd_vars        r   _infer_var_data_type_shape_r     s     zz""=#7#7#9:H"=1Hzz##HOO$566**//0AB7==?+7==?+ 	]O+no	
 	4<<//445r!   c                D    [        U 5      S:X  a  gU  H
  nX!;  d  M
    g   g)z0
Test if all elements of 'cands' are in set 's'
r   FTr&   candsscs      r   _all_in_set_r    s)     5zQ:  r!   c                D    [        U 5      S:X  a  gU  H
  nX!;   d  M
    g   g)z1
Test if some elements of 'cands' are in set 's'
r   FTr   r   s      r   _some_in_set_r    s)     5zQ6  r!   c                4   [         R                  " [        R                  " 5        S3U 5      =(       d-    [         R                  " [        R                  " 5        S3U 5      nUb  U SUR	                  5        OU nU R                  S5      nUS:w  a  X#S-   S $ U$ )z
Strip the grad suffix from the given variable name
e.g. x@GRAD ==> x
     x@GRAD@GRAD ==> x
     y@GRAD@RENAME@1 ==> y
     z@GRAD_slice_0@GRAD ==> z@GRAD_slice_0
     grad/grad/z@GRAD@RENAME@block0@1@GRAD ==> z
z+@$Ngrad/rB      )researchr   grad_var_suffixstartrfind)r/   posr   new_poss       r   r   r     s     ))t++-.b14
8 BII!
"!$d=C '*otMciik"4Hjj!G&-m8aKM"AAr!   c                2    U [         R                  " 5       -   $ )zA
Append grad suffix to the given variable name
e.g. x ==> x@GRAD
r   r  r/   s    r   r   r     s    
 $&&(((r!   c           	         X2R                  5       ;  a  / X#'   X#   R                  [        SSX   0SU /0SU05      5        U /X'   g)zO
Use sum op to accumulate_gradients, the gradients are stored in renamed_vars.
sumXrx   ry   N)keysr)   r   )r5   renamed_varspending_sum_opsrI   ry   s        r    _accumulate_gradients_by_sum_op_r    s`     ))++"$"",()XJ)$		
 'ZLr!   c           
     f   X2R                  5       ;  a  / X#'   X   S   n[        S[        X   5      5       Hs  nUnX   U   n	U[        X   5      S-
  :w  a  U S-   [        U5      -   nOU nX#   R	                  [        SU/U	/S.SU/0SU05      5        Uc  Mb  X;   a  XP   XV'   Mo  XU'   Mu     U /X'   g)	z_
Use several inplace add op to accumulate_gradients, the gradients are stored in renamed_vars.
r   r   z@ADD@grad_add)r  Yrx   ry   N)r  r9   r&   r   r)   r   )
r5   r  r  rI   ry   grad_var_to_varout_namer=   x_namey_names
             r   !_accumulate_gradients_by_add_ops_r!    s     ))++"$%a(H1c,012'*L*+a//')CF2HH&&hfX.
#i(		
 &*,;,E),4)) 3* 'ZLr!   c                j
  ^^^  [         R                  " 5       S   n0 m [        R                  " 5       n[        R                  " [
        5      n[        R                  " [        5      m[        R                  " [        5      n[        R                  " [        5      n	UUU 4S jn
[        U 5       GH  u  p[        R                  R                  5       nSnUR                  U5      (       a  UR                  U5      nUR                  5        Hf  nSU;  a  M  [        TU   5      S:  d  M  [        TU   5      U:  a  U
" U5        [!        UTUUX   5        ML  U
" U5        [#        UTUUX   U5        Mh     [        UR%                  5       5       GH'  u  nnUR'                  U5      n[        U5       GH  u  nnSU;  a  M  U[        R(                  " 5       :X  d  XR                  5       ;   a  M=  [        TU   5      S:X  a#  U/TU'   XU'   T(       a  UT;   a  TU   OST U'   Mr  [        TU   5      S:X  a  US-   [        U5      -   S-   [        X   5      -   nX==   S-  ss'   Ub  X;   a	  UU   UU'   OXU'   T U   T U'   UTU   S'   [+        U UUX   U5        [+        XoU5        UR%                  5       S	U  HG  nUR'                  U5      nUU;   d  M  UR-                  UU Vs/ s H  nUU:X  a  UOUPM     sn5        MI     US	U  Vs/ s H  nUU:X  a  UOUPM     snUUS	 -   nUS-   [        U5      -   S-   [        X   5      -   nX==   S-  ss'   Ub  X;   a	  UU   UU'   OXU'   UUU'   UR-                  UU5        TU   R/                  U5        XU'   T(       a  UT;   a  TU   OST U'   GM     GM*     GM     TR1                  5        Hr  u  nn[        TU   5      S:  d  M  [        TU   5      U:  a$  U
" U5        [!        UTU[        U 5      X   5        MP  U
" U5        [#        UTU[        U 5      X   5        Mt     [        U 5      n[        R                  " [3        [        UR1                  5       5      5      5      R1                  5        H  u  nnUn[        U5       Hz  u  nnUU:X  a  US-
  OUU-   nUbL  UR5                  U U   R7                  5       S	5       b'  UU U   R7                  5          UUR7                  5       '   U R9                  UU-   U5        M|     M     U $ s  snf s  snf )
a  
In backward part, an variable may be the output of more than one ops.
And one op may yield its multiple outputs to the same variable.
In these cases, the variable should be the accumulation of all the outputs.
`sum_op`s are added to implement the accumulate.

Args:
    grad_var_to_var(dict): used to build the mapping between grad var name and forward var name.
    Only for auto parallel.
FLAGS_max_inplace_grad_addc                >   > Tc  g TU    nUR                  U4S jS9  g )Nc                   > TU    $ r   rb   )rd   topo_order_for_grad_names    r   re   Q_addup_repetitive_outputs_.<locals>._change_order_by_topo_order.<locals>.<lambda>2  s    (@(Cr!   rg   )sort)r5   origin_namesr  topo_order_for_backwardr&  s     r   _change_order_by_topo_order?_addup_repetitive_outputs_.<locals>._change_order_by_topo_order.  s(    "*#H-CDr!   rw   @GRADr   r   z@RENAME@block@N)r	   _global_flagsr   r   defaultdictr   r   r   r\   r   r   r   r   r   r:   r&   r  r!  output_namesoutputempty_var_namer   r   r)   r   r   getr   r   )!r   	block_idxr  r   r*  _MAX_ADD_NUM_r  var_rename_countrenamed_var_start_idx
var_devicer+  r>   r   r   ry   r5   	param_idx
param_name	arg_namesarg_idxr   pp_arg_namesrd   r|   op_descs_lenrh   r   r=   r0   
target_idxr  r&  s!       `                          @@r   _addup_repetitive_outputs_rB    s   $ ++-.JKM!!--/O"..s3**40L'33D9((-JE "(+++==? 	 	/00%89I//1Hh&<)*Q.|H-.>/94 $'", 095 $'",' 20 &/w/C/C/E%F!Izz2I%.y%9!(*  3 3 55#:#:#<< |H-.!3.6ZL*69(3 3#'>> 08 	 -X6 <12a7$-.!)n- "" ""2"<=	> ! )2a72*6':<K$,=" 9 =E 9 5X> 1: 5=X.q1
 %$$$1; %_I!(!5!5!7
!CA*1..*;K';6 ' 2 2$% 2=%&1<A 56Mq(H1<%&!" "D &/x%8%%8 )*XH1<%8% &gh/%0	 !)*i.)  .89	:  %.!3.&2#68G (9OH5 9AH5)1Ig&&&z9= *11(;+4x( 3#'>> 08 	 -X6} &: &G? ,L )..0&|H%&*<)*]:+H50 #M( ,H51 #M( 1* x=L!--o++-./eg
U u%EAr$'<$7qS1WJ$0(,,Z(446 
 :NZ(446:$R^^%56 OOC!GR( &. Ok%&%s   $T+
T0
c           
        ^ U4S jnU Vs1 s H$  oUR                   [        R                  " 5       -   iM&     snmU  Vs/ s H  nU" Xa5      (       a  M  UPM     n n/ n[        R                  " 5       (       d  [	        U 5       H  u  pUR                  5        H  n	[        R                  " 5       U	;   d  M  X;   d  M%  [        U	5      n
[        SSU
/0SU	/0SSS.5      nUbD  UR                  UR                  5       S5       b"  X&R                  5          X+R                  5       '   UR                  X45        M     M     [        U5       Vs/ s H  oR                  US	   US   5      PM       nU $ s  snf s  snf s  snf )
z
Remove unnecessary grad ops
A grad op can be removed in two cases:
    1. all outputs of the grad op are in 'no_grad_set'
    2. all grad inputs of the grad op are in 'no_grad_set'
NOTE: we will skip target_vars's grad name.
c           	     `  > U R                  5       n[        U5      S:X  d  [        X!5      (       a  g[        U R                  5        Vs/ s H/  nUR	                  [
        R                  " 5       5      S:w  d  M-  UPM1     snU5      (       a  UR                  [        U5      T-
  5        ggs  snf )Nr   TrB   F)	r-   r&   r  r:   findr   r  updateset)r   no_grad_setout_arg_namesr/   target_grad_var_namess       r   _op_can_be_removed_4_remove_no_grad_branch_.<locals>._op_can_be_removed_  s    002}"l=&N&N $3355D99T1134: 5
 
 
 s=14IIJs   	,B+9B+fill_any_liker  rx   r   rB   r   rt   Nr   )r/   r   r  _is_bwd_prim_enabledr\   r:   r   r   r4  r   r)   r   r   )r   rH  r   target_varsrK  r'   r   	to_insertr>   r   x_inr   r>  rJ  s                @r   _remove_no_grad_branch_rS    s   $ 6A5@c4''))[
  G"78 	   I$$&&%h/LC..0'')S0S5G.s3D #3'tf"#b1	#K -8044#//14  $$ 11D1D1FG --D-D-FG $$k%78/ 1 04 +39*=>*=Q__QqT1Q4 *=>OOD ?s   +E1E6E6!E;c                  ^^^^^  " U4S jS5      m " U4S jS5      m0 mUU4S jmUU4S jmUUU4S jnUc
  [        5       O
[        U5      nU HU  nUR                  UR                  R                  5       5        UR                  UR                  R	                  5       5        MW     [        5       n[        5       nU  Hu  n[        UR                  5       5      n	X-
  U-
  n
UR                  UR	                  5       5        U" U5      n[        U
5      [        U	5      :X  d  Md  UR                  U5        Mw     / nU GH
  nU/n[        UR                  5      nSnU/n[        U5      S	:  a  UR                  S	5      n[        UR                  U5      (       ae  UR                   H9  nUR                  UR                  5        UR                  UR                  5        M;     UR                  UR                  5        OS
nO[        U5      S	:  a  M  U(       d  M  UR                  U Vs/ s H  nUR                  PM     sn5        GM     [        U5      n[        U 5      nUU:X  a
  [        5       $ U$ s  snf )a  
Pruning Program with Structural Analysis Method of Computational Graph.
The nodes of the computational graph composed of backward OPS should be
interconnected. If there are unconnected sub-graphs in the computational graph,
these sub-graphs should be cut off.

Args:
    grad_op_descs(list[core.OpDesc]): The candidate backward OpDescs.
    forward_ops(list[Operator]): The forward ops.
    input_grad_names_set(set): this set is used to store the gradients' name
        which is generated by backward ops, and input_grad_names_set can help
        to prune the unnecessary backward ops.

Return:
    (set[core.OpDesc]): A set of OpDescs which should be pruned.
c                  4   > \ rS rSrS rU 4S jrU 4S jrSrg)_find_not_need_ops.<locals>.VariC  c                ,    Xl         S U l        / U l        g r   )r5   gen_oppending_ops)r   r5   s     r   r   (_find_not_need_ops.<locals>.Var.__init__D  s    $MDK!Dr!   c                V   > [        UT5      (       d   eU R                  b   eXl        g r   )r   rX  )r   rX  Ops     r   
set_gen_op*_find_not_need_ops.<locals>.Var.set_gen_opI  s+    fb))));;&&& Kr!   c                b   > [        UT5      (       d   eU R                  R                  U5        g r   )r   rY  r)   )r   r0   r\  s     r   add_pending_op._find_not_need_ops.<locals>.Var.add_pending_opN  s*    b"%%%%##B'r!   )rX  rY  r5   N)r   r   r   r   r   r]  r`  r   )r\  s   r   VarrV  C  s    	"
	!
	( 	(r!   rb  c                  4   > \ rS rSrS rU 4S jrU 4S jrSrg)_find_not_need_ops.<locals>.OpiR  c                ,    Xl         / U l        / U l        g r   )r   r|   r}   )r   r   s     r   r   '_find_not_need_ops.<locals>.Op.__init__S  s    "LDKDLr!   c                b   > [        UT5      (       d   eU R                  R                  U5        g r   )r   r|   r)   r   r'   rb  s     r   insert_input+_find_not_need_ops.<locals>.Op.insert_inputX  s(    c3''''KKs#r!   c                b   > [        UT5      (       d   eU R                  R                  U5        g r   )r   r}   r)   rh  s     r   insert_output,_find_not_need_ops.<locals>.Op.insert_output\  s(    c3''''LL$r!   )r|   r   r}   N)r   r   r   r   r   ri  rl  r   )rb  s   r   r\  rd  R  s    	
	$	% 	%r!   r\  c                   > U TR                  5       ;  a  T" U 5      /TU '   OTU    R                  T" U 5      5        TU    S   $ NrB   )r  r)   r/   rb  var_versionss    r   _create_node(_find_not_need_ops.<locals>._create_nodeb  sK    |((**"%d)L%%c$i0D!"%%r!   c                T   > U TR                  5       ;  a  T" U 5      /TU '   TU    S   $ ro  )r  rp  s    r    _create_or_get_last_version_node<_find_not_need_ops.<locals>._create_or_get_last_version_nodei  s4    |((**"%d)LD!"%%r!   c                  > T" U 5      nU R                  5        H+  nT" US9nUR                  U5        UR                  U5        M-     U R                  5        H+  nT" US9nUR	                  U5        UR                  U5        M-     U$ )Nr  )r:   r`  ri  r-   r]  rl  )r   op_noder   r'   r2  r\  rr  ru  s        r   _create_op_node+_find_not_need_ops.<locals>._create_op_noden  s    W+,,.E2>Cw'  % / ..0FF+CNN7#!!#& 1 r!   Tr   F)rG  rF  r*   r:   r-   r&   addr|   popr  r}   r,   rY  r   )grad_op_descsforward_opsinput_grad_names_setry  forward_vars_setr0   backward_vars_setspecial_op_nodesr   	input_setnew_varsrx  not_need_op_descsspecial_op_nodeop_list
ready_vars
remove_opscandidate_opsout_varnodenot_need_op_descs_setgrad_op_descs_setr\  rb  rr  ru  rq  s                         @@@@@r   _find_not_need_opsr  1  s)   $( (% % L&&

 &-37K3L   7 7 9: 8 8 :; 
 u //12	/2CC  !9!9!;<!'*x=C	N*  ) !  ,"#//0

()- 1$#''*GGNNJ77&G!(()<)<=NN7#6#67  / !!'//2"
 - 1$ :$$w%Gwtdllw%GH! ,"   12M* 11u   &Hs   +I5
c                    U R                  5       n[        R                  R                  [	        U5      5      nUR                  5       $ r   )serialize_to_stringr   r   
FromStringr   __str__)r   protostrprotos      r   serialize_op_decsr    s6    **,H  ++E(O<E==?r!   c                   U Vs/ s H  oR                   PM     n	n[        [        U	5      5      n	U R                  R	                  5       n
U R                  R	                  5       n[        X5      nUR                  5         UR                  5         UR                  U	5      n	/ n[        U	5      S:X  ag  SnU	S   /nU H<  nUUR                  ;  a    O+UR                  U   S   nU H  n[        UU5      nM     M>     US:  a  UR                  SUS-   /5        OSnSn U[        U	5      S-
  :  a  OwUR                  U	U   /U	US-      /5      u  nnnU(       a)  UR                  UU5      nUR                  UUS-   /5        O[        R!                  SU SUS-    S35        US-  nM  U/ :w  a  US   S   S:w  a  SUS   S   //UQnOUn[#        U5       H  u  nu  nn[        R!                  SU S	35        [        R!                  S
UU   R$                  R'                  5        SUU   R$                  R)                  5        S	35        [        R!                  SUUS-
     R$                  R'                  5        SUUS-
     R$                  R)                  5        S	35        M     / nU H*  nUR+                  UR-                  US   US   5      5        M,     [        U5      [        U	5      -
  n[        R!                  S[        U5       SU S35        UR+                  UR/                  5       5        UR+                  UR1                  5       5        [        [        U5      5      n/ n0 n UU	-   n![        U5      n"[2        R4                  R7                  5       n#U/ :X  Ga1  USU" n$[9        U$5       GH  n%U%R;                  S5      (       a.  [=        SR?                  [A        U%R$                  S5      5      5      e[2        RB                  " U%R$                  X@RD                     / 5      u  n&n'Ub  U& H  n(U%UU(RG                  5       '   M     U%R$                  R;                  U#5      (       a6  U%R$                  RI                  U#5      n)U& H  n(U(RK                  U#U)5        M     [M        U&X5      n*UR+                  U*5        URO                  U'5        GM     [#        USSS2   5       GH  u  nnUUS   U" n$US   n"[9        U$5       GH  n%U%R;                  S5      (       a.  [=        SR?                  [A        U%R$                  S5      5      5      e[2        RB                  " U%R$                  X@RD                     / 5      u  n&n'Ub  U& H  n(U%UU(RG                  5       '   M     U%R$                  R;                  U#5      (       a6  U%R$                  RI                  U#5      n)U& H  n(U(RK                  U#U)5        M     [M        U&X5      n*UR+                  U*5        URO                  U'5        GM     UUS   US    n+SU 3n,U+ GHW  n%U%R;                  S5      (       a.  [=        SR?                  [A        U%R$                  S5      5      5      e/ n-U-R+                  U%R$                  R)                  5       5        U-R+                  U%R$                  RQ                  5       5        U- H  nU RS                  U5      RT                  (       d  UU	;   a  M+  UU;   a  M3  UU ;  d  M;  UU,-   U U'   U R                  RW                  5       RS                  U5      n.U RY                  U U   U.RZ                  U.R\                  U.R&                  U.RT                  U.R^                  S9  M     GMZ     [a        U+XU!U5      n/[M        U+X5      n*U  H  n0[c        U/U0U U0   5        M     UR+                  U/5        [9        U*5       H  n([2        RB                  " U(X@RD                     / 5      u  n&n'Ub-  U& H'  n1UU(RG                  5          UU1RG                  5       '   M)     U(R;                  U#5      (       a,  U(RI                  U#5      n)U& H  n1U1RK                  U#U)5        M     U  H  n0[c        U&U0U U0   5        M     UR+                  U&5        URO                  U'5        M     GM     [e        UU RD                  US9n[g        UX@RD                     UU5      n[M        UX75      n*UU	UU4$ s  snf )aP  
Create grad ops with forward ops, and insert them into given block

Args:
    block(Block): the block where forward ops are
    ops(Op): the forward operators whose forward recomputation backward ops need to be added
    target_vars(list[Tensor]): the loss vars we want to calculate gradient.
    target_block(Block): the block which is going to hold new generated grad ops
    no_grad_dict(dict):
        key(int) block index
        val(str): corresponding forward variable name
    checkpoints: variables that a user defined as checkpoint for forward recomputation

Algorithms:
    0) deal with forward recomputing program descs
    1) find ops between checkpoints, i.e. recompute_segments
    2) go through all forward ops and induct all variables that will be hold in memory
        a. variables that are used across segments will be held in memory
        b. output of dropout op will be held in memory
        c. input variables will be held in memory
    3) go through each recompute_segments, add backward ops with forward recomputation
        a. add ops in current recompute_segment as forward recomputation ops
        b. rename all non-checkpoint variables in recomputation ops
        c. add backward ops of current recomputation ops
        d. add sum op for repetitive_outputs
    4) remove no grad branch as it is in _remove_no_grad_branch_
    5) Note1: all appended ops' OpRole are Backward
    6) Note2: all variables with new name should be returned so that _append_backward_vars_ can be called
    7) Note3: current forward recomputation backpropagation does not handle programs with subblock
r   rB   r   r#   zCould not recompute op range [z] - [z] zrecompute segment[]zsegment start op: [z]: [zsegment end op: [zfound [z'] vars which cross recompute segment: [z7], better checkpoints might be set to reduce those vars	sub_blockz7Recompute don't support ops with sub_blockinvoke op: {}with_sub_blockNz	.subprog_)r/   r   rt   r+   r(   ru   r   )4r/   r   rG  program_create_blockr   r   r^   rl   r&   r   rD   r)   rJ   rW   rQ   rR   r\   r*   r+   r:   r,   r?   r6   r1   r   r   r   r   r   	Exceptionr   r   get_grad_op_descr>   r   r   r   r   rF  r-   r'   r(   global_blockr   r   rt   ru   r   r   rB  rS  )2r   r   rP  target_blockno_grad_dictgrad_to_varcheckpointsr   rd   rj   local_blockbuffer_blockprogram_statsegmentsrH   	var_groupr/   rI   r>   	start_idxrT   flagrS   max_idxrecompute_segmentsr=   idx1idx2vars_should_be_holdsegment
cross_varsr}  var_name_dictvars_in_memorymax_calculated_op_positiondevice_attr_namegap_opsr0   grad_op_descop_grad_to_varr   ry   added_descsff_ops
var_suffixinput_and_output_namesref_varbuffer_descsrh   	g_op_descs2                                                     r   &_append_backward_ops_with_checkpoints_r    s
	   R )4414C 012----/K==..0L+L224 $445EFH
!
%a()	D<333!--d34GHF S1
   >OOQ
Q/0	 C 01A55 &2%=%=!),-0@Q0O/P&"D'7 &<<0 'A+ 674WIU7Q;-rR NI' * 2~(1+a.A- (1+a.1=H=%$%78<D$)!A./!#d).."5"5"7!8SY^^=[=[=]<^^_`	
 	D1H 2 2 7 7 9:$s4!8}?Q?Q?a?a?c>ddef	
 9 %""11'!*gajI	
 &
 ()C0@,AAJLL
#j/""I*  VM  	N
 |==?@|;;=>s#678 MM(+;;N!$S66HHJRa237#B{{;''$$*F(2BC%  ,0+@+@ii0",(L.
 $/+GBD()<)<)>?  , ww 011GGLL)9:	+G%%&6	B  ,-kK   -~.5 $8   24R4 89
7gaj#=>%,QZ"7#B{{;''$$*F(2BC%  ,0+@+@ii0",(L.
 $/+GBD()<)<)>?  , ww 011GGLL)9:	+G%%&6	B  ,-kK   -~.5 $8 WQZ'!*- _
B{{;''$$*F(2BC%  &(""))"''*A*A*CD"))"''*B*B*DE.99T?..$:J2J..},*.*;M$' $mm88:>>tDG$$*40%mm%mm$\\$+$7$7&-&;&; %  / > 2L9M
 *K

 !CsM#,>? ! 	\*  ,G+/+@+@ii0",(L.
 $/!-I,W-@-@-BC ))>)>)@A ".  011#LL)9:	!-I''(8)D ". %\3c0BC %  .~.+ -a :P /uyy7KM ,YY	M &|K 		 ] 5s   c=c                R   UR                  S5      (       a  U R                  UR                  S5      :X  d   e[        U[        [        S5      45      (       d   eUc  UR                  nUR
                  S;   a  U Vs/ s H  oPR                  U5      PM     nnU HZ  nU R                   HG  nXWR                  ;   d  M  UR                   H#  nUR                  U R                  U5      5        M%     MI     M\     UR
                  S;   n	[        X/ X#U	5      n
U
$ U R                  $ s  snf )ap  
Get output vars in subblock which will be assigned to parent block.
It is used to find the grad path in subblock.

Args:
    sub_block(Block): The sub-block in which to get op path.
    sub_block_op_desc: The op desc of the sub-block op such as 'while', 'conditional_block'.
    no_grad_set(set): The set of no grad var name. no_grad_set will be changed.
    op_path_dict(dict): op_path_dict will be changed.
        key(int) block index
        val(list) the op path of block(index)
    sub_block_target_names(set): Target var names of sub-block.
Return:
    The forward op path of sub-block corresponding to backward op.
r  N)conditional_blockwhile)r  )r   r>   _block_attr_idr   rG  r+   r-   _var_recursiver   r:   r)   _find_op_path_)r  sub_block_op_descrH  op_path_dictsub_block_target_namesr'   sub_outputsr   r/   is_whilesub_block_op_paths              r   _get_sub_block_pathr    s5   . %% 
--,;;KH
HI I ,sDJ.?@@@@%!2!C!C !?? 6L
5Kc$$S)5K 	 
 *C$==222 ' 7 7#**9+C+CD+IJ !8 ) * %))Y6*B8
 ! ==
s   =D$c                   [         R                  n[         R                  R                  R                  nUR	                  5       U R
                  ;   a8  [        U R                  5       UR                  5          5      [        U5      :X  a  gg)NTF)	r   r   r   r   kOpRoleVarAttrName
attr_namesr   	all_attrsr   )r0   op_makerr   s      r   _is_grad_op_r    sk    ..H..55>>H""$5#
x//12;	X; r!   c                    SU-  U -   $ )Nr  rb   )r/   
grad_orders     r   _rename_grad_name_r    s    Z$&&r!   c                   0 nU R                    H  nUR                   H  nX2U'   M	     M     0 nU Vs/ s H  ofR                  PM     nnU Vs1 s H  ofR                  iM     nnSn	[        U5      S:  ay  UR	                  S5      n
X;  a  M'  X*   nXU'   U	S-  n	UR
                   H3  nX;   d  M
  X;  d  M  UR                  U5        UR                  U5        M5     [        U5      S:  a  My  U$ s  snf s  snf )z?Analysis forward block and build a mapping from:
OpDesc -> Int
r   r   )r   r-   r/   r&   r|  r:   r)   r{  )r   rP  get_defined_opr0   r  topo_order_mapr'   queuevisitedtopo_order_countercur_var_namecur_opinps                r   _topo_order_mapr    s     Nii++H')8$ ,  N!,-#XXE-#./;Cxx;G/
e*q.yy|--!3va))C$);S!C  * e*q.  ./s   C1C6c                    0 nU R                  5        VVs0 s H  u  p4UR                  U_M     n nnUR                  5        H  u  pVXP;  a  M  U H	  nX   X''   M     M     U$ s  snnf r   )r   r*   )topo_fwd_mapbackward_op_maptopo_bwd_mapr0   orderfwd_opbwd_opsbwd_ops           r   _topo_bwd_order_mapr  0  sq    L4@4F4F4HI4HyrBGGUN4HLI*002%F#/#7L   3
  Js   A#c                  ^^+^, U+U,4S jnUbA  [        U[        [        45      (       d   eU H  n[        U5      (       a  M  [	        S5      e   / nU R
                  n0 nU
c  0 n
[        U
[        5      (       d   e[        R                  " 5       (       a  UR                  5       R                  5       nUR                   H  m,T,R                   H]  nUR                  R                  UR                  5       5      (       a  M3  U[        R                   " 5       :X  a  MN  UR#                  US9  M_     T,R                  R%                  UR                  5        T,R                  R'                  UR                  5        M     [)        U5       GH  m,/ nT,R+                  S5      (       a  UR-                  T,R/                  S5      5      nUR1                  5       nUR3                  UR4                  5        [6        R6                  " T5      nSmUT,R/                  S5         n[9        UUUUUUUTUUS9
  UmUR;                  5         UR=                  UR                  5        / m+0 n[        R                  " 5       (       au  S n[        R>                  " WR                  RA                  U" U R                  T,R                  5      5      UUR4                     U5      u  m+nT+ H  n[C        UU5        M     O1[        R>                  " T,R                  X@R4                     U5      u  m+nT+UT,R                  '   Ub  T+ H  nT,UURE                  5       '   M     U	b  U" U	UURF                  5        O\[I        [J        RL                  RN                  RP                  RR                  SS5      nUb   URT                  n	U" U	UURF                  5        [        RV                  RY                  5       nT,R                  R+                  U5      (       a6  T,R                  R[                  U5      nT+ H  nUR]                  UU5        M     URF                  S	:  Ga!  T+ GH  nT,R                  R_                  5       nUR_                  5        H(  nUU
;   d  M  UU;  d  M  URa                  UU
U   5        M*     UR                  5        H  nS
U;  a  M  U R                  Rc                  UR                  S5      5      (       d  M<  [e        UURF                  5      n URg                  UU 5        U U
U'   UU;   d  Mq  U	b  UU   U	Rh                  URF                     U '   UU   UU '   URk                  U5        M     GM     Tb  U4S jn!Sn"/ n#T+ H6  nU#UR_                  5        Vs/ s H  nU!" U5      (       d  M  UPM     sn-  n#M8     [m        U#5      S:X  a  Sn"GM;  [o        U#T5      (       aD  Sn"T+ H<  nUR=                  U5        UR                  5        H  nTRq                  U5        M     M>     U"(       a  URs                  U5        GM  GM  URu                  T+5        URs                  U5        GM     Sn$U	b  U	Rh                  URF                     n$[v        Rx                  R{                  SS5      S;   a  [}        X5      n%[        U%U5      n&OSn&[        UU R4                  U$UU&S9n[        UX@R4                     UU5      n[        R                  " 5       (       d'  [        XT5      n'U Vs/ s H  nUU';  d  M  UPM     nnO[        R                  " S5        [        RV                  R                  5       n([        RV                  R                  R                  n)U Hv  nUR                  R                  5       n*U*R                  U5        U*R]                  U(U)5        U*US'   Uc  MJ  [        U[        [        45      (       d   eU H	  nU" X5S9  M     Mx     gs  snf s  snf )a  
Create all grad ops, and insert them into given block

Args:
    block(Block): the block where forward ops are
    ops(Op): the forward operators whose backward ops need to be added
    target_vars(list[Tensor]): the loss vars we want to calculate gradient.
    target_block(Block): the block which is going to hold new generated grad ops
    no_grad_dict(dict):
        key(int)  block index
        val(set) a set of variable names. These variables have no gradient
    grad_to_var(dict)(output argument):
        key(str): grad variable name
        val(str): corresponding forward variable name
    callbacks(callable object): a callable object used to decorate new generated grad ops
    input_grad_names_set(set): this set is used to store the gradients' name which is
        generated by backward ops, and input_grad_names_set can help to prune the unnecessary
        backward ops.
    op_path_dict(dict): op_path_dict will be changed.
        key(int) block index
        val(list) the op path of block(index)
    rename_var_map(dict): used to associate target_grad var name with first grad_op input name.
        Only used in for high order gradient.
c                   > U R                   U   R                  U5        T HX  nUR                  5       U R                  ;  d   eTR                  R                  5       U R                  UR                  5       '   MZ     g r   )r  rF  r   grad_op_id_to_op_idr*   )distop_contextr  appending_grad_timesr   r  r0   s       r   update_distop_context4_append_backward_ops_.<locals>.update_distop_contextc  sx     	&&';<CC	
 $G##%^-O-OOO ##% ..w/B/B/DE	 $r!   Nz%'callback' must be a callable object.r  r  r  c                t    [        U R                  5       5       H  nXR                  U5      :X  d  M  Us  $    gro  )r9   op_sizer0   )
block_desccur_op_descr>   s      r   find_op_index,_append_backward_ops_.<locals>.find_op_index  s3     !3!3!56C"mmC&88"
 7 r!   _g_default_distributed_contextr   r-  asciic                j   > U R                  [        R                  " 5       5      S:g  =(       d    U T;   $ ro  )rE  r   r  )r/   r  s    r   re   '_append_backward_ops_.<locals>.<lambda>  s/    TYYt';';'=>"D 0//0r!   Fr   TFLAGS_program_topo_reorderFalse)True1true)r   r*  z8Running backward composite and disable find_not_need_ops__current_op_desc__)r   context)Jr   r   r   callabler   r  dictr   rO  clonecurrent_blockr   r-   r*   r   r   r3  r   infer_var_typeinfer_shaper   r   r   r  r  _set_forward_block_idxr>   copy_append_backward_ops_	_rollbackr)   r  r0   infershape_for_compositer   _appending_grad_timesgetattrpaddledistributedauto_parallelstaticdist_contextdist_op_contextr   r   r   r   r:   r   r   r  r   r  r|  r&   r  r{  rF  r,   osenvironr4  r  r  rB  rS  r  loggingdebugr   r   r   r   r   )-r   r   rP  r  r  r  	callbacksr  r  r  rename_var_mapr   r  cbr}  r  get_backward_op_desccomposite_blockr/   grad_sub_block_listr  grad_sub_blockpre_input_grad_names_setsub_block_pathr  r  r*   r   default_ctxr  ry   forward_op_inputsr   is_grad_nameis_append_gradinput_grad_namesr  
topo_orderr*  not_need_opsr   r   r   r  r0   s-          `                                   @@r   r  r  ;  s   P )dE]3333BB<< !HII 
 MmmGnd++++  ""!--/779 "%%B++#((::4;;=IIt2244#..D.9 , GG""?#7#78GG 4 45 & sm ;;{##b&7&7&DEI$224N11)--@'+yy1E'F$#' )"*;*;K*HIN!$%9 $< &&~':':; $$&& ,0+@+@$$''ejj"''(JK_001#,(L.
 %($? % ,0+@+@ii02E,(L.
 )5RWW%+'>@$W%8%8%:; ( %!0M0M """0077DD0K
 &!,!<!<%""11  ::LLN77,--%56I'!!"2I> ( ((1,'$&GG$;$;$=!#335D~-$>O2O--dN44HI 6 $446Dd* zz**4;;w+?@@#5 '"?"?$  ..tX>/7t,>1-9 /=T.B !/ > >$+$A$A!""*!, 8Fd7KN84*..t4# 7 (8  +0  #N  "'  ' 7 7 9% 9#D)  9%   ( #$)!%-/CDD!%+G!((1 ' 8 8 :,006 !;  ,
 "">2    .~.[ ` O!(88))
 
zz~~2G< A 
 %U8
"5,#
 #'.		1 7M ,YY	M $$&&) 4
 $1
#0G<4OG= 	 
 	F	

 77GGI..55>>H "''113g&/:-8)* i$7777;   ![%D
s   ` 
 ` 

`"`c                2    [         R                  " 5       U ;   $ r   r  )r5   s    r   _is_grad_var_r+  }  s    !X--r!   c                x   U R                   nUS:X  a  g U R                  n[        UR                  5       H  nUR	                  U5      R
                  n[        UR                  5       5       HG  nUR                  U5      nUR                  S5      (       d  M,  UR                  S5      U:X  d  MC  Us  s  $    M     g )Nr   r  )
r>   r  r9   
num_blocksr   r*   r  r0   r   r  )r  sub_block_idr  block_idr  rI   r0   s          r   _find_parent_op_r0    s    ==LqG',,-]]8,11
J..01Fv&BK((%%k2lB	 2 . r!   c                   / n [        U 5      n/ nUbA  UR                  5       nUR                  5       nU H  n	X;   d  M
  UR                  U	5        M     [	        XR
                  R                  5       5       GH  n
U R
                  R                  U
5      nUR                  S5      (       a7  U R                  R                  UR                  S5      5      n[        USX#5        UR                  5        Vs/ s H  n[        U5      (       d  M  UPM     nnUR                  5        Vs/ s H  n[        U5      (       d  M  UPM     nnUR                  5        Vs/ s H   nU[        R                  " 5       :w  d  M  UPM"     nnUR                  5        Vs/ s H   nU[        R                  " 5       :w  d  M  UPM"     nnU(       d  UR                  U
5        GMa   U(       ab  U Vs/ s H:  nU R
                  R!                  UR#                  5       5      (       d  X;   d  M8  UPM<     nnU(       d  UR                  U
5        GM  UR%                  5       S:X  a  / nUR                  5        HD  nU R
                  R!                  UR#                  5       5      (       d  M3  UR                  U5        MF     ['        U5      S:  d   S5       eUR)                  SU5        [+        5       nUR                  5        H  nU R
                  R!                  UR#                  5       5      (       d  U[        R                  " 5       :X  a  ML  U R
                  R-                  UR#                  5       5        UR/                  U5        UU;  a  M  UU 4X2U   '   M     UR1                  5         UR3                  U R
                  5        UR5                  U R
                  5        UR                  5        H  nUU;   d  M  [7        UU 5        M     GM     [9        U5       H!  n
U R
                  R;                  XS-   5        M#     gs  snf s  snf s  snf s  snf s  snf )af  
Create new variables required by backward pass.

Args:
    block(Block): the block where new variables will be created
    start_op_idx(int): Only variables required by ops in block.ops[start_op_idx : ] will be created
    grad_to_var(dict):
        key(str): grad variable name
        val(str): corresponding forward variable name
        In most cases, this dict is generated by _append_backward_ops_()
    grad_info_map(dict)(output argument):
        key(str): forward variable name
        val(tuple): a tuple of (str, Block), str is the corresponding grad name, Block is the block containing grad variable
Nr  r   r  z6After remove invalid variables, sum op have no inputs.r  r   )r0  r:   r-   r)   r9   r*   r  r0   r   r  r   r  _append_backward_vars_r+  r   r3  r   r   r+   r&   r   rG  r'   r{  check_attrsr  r  r   r   
_remove_op)r   start_op_idxr  grad_info_mapops_to_remove	parent_opparent_op_vars
input_argsoutput_argsin_argrI   r   r  r'   grad_var_insgrad_var_outsr|   r}   existing_grad_var_ins
new_inputsr   r  r   s                          r   r2  r2    s    M !'IN..0
002 F$%%f- ! jj&8&8&:;**--'K((++G,B,B;,OPI"9aL #224
4Cc8JC4 	 
 #335
5Cs9KC5 	 
 ..0
0d))++ 0 	 
 //1
1d))++ 1 	 
   (   ,)+zz33CJJLAA, + & ) -!((0 <<>U"J!(!8!8!::://0D0D0FGG%%m4 "; z?Q& H& c:.5$557M

,,]-A-A-CDD D$7$7$99JJNN=//12LL'K/9F8NMm45 8 	uzz*EJJ'++-Ch+C7 .U <\ =)

fqj1 *Q




 )s<   6P5P5(P: P:P?;P?Q6Q%7Q	 Q	c                   [        UR                  5       5      S:X  a  g [        5       nUR                  5        H  nU R                  R	                  UR                  5       5      (       a  M3  U[        R                  " 5       :X  a  MN  U R                  R                  UR                  5       5      nU R                  X4UR                  5       S9  UR                  U5        M     [        R                  R                  5       R                  UR                  5       5      (       GaH  U R!                  UR                  5       UR#                  5       R%                  5        VVVs0 s H&  u  pVXV Vs/ s H  opR'                  U5      PM     sn_M(     snnnUR)                  5       R%                  5        VVVs0 s H&  u  pVXV Vs/ s H  opR'                  U5      PM     sn_M(     snnnUR+                  5       S9nUR                  R-                  [        R.                  R1                  5       [        R.                  R2                  R4                  5        UR7                  UR                  5        OU R                  R!                  5       n	U	R7                  U5        U	R-                  [        R.                  R1                  5       [        R.                  R2                  R4                  5        U	R9                  5         U	R;                  U R                  5        U	R=                  U R                  5        UR7                  U	5        [        R                  R                  5       R                  UR                  5       5      (       d*  UR                  5        H  nXr;   d  M
  [?        Xp5        M     g g s  snf s  snnnf s  snf s  snnnf )Nr   )r/   r*   r+   )r+   r|   r}   r~   ) r&   r-   rG  r*   r   r   r   r3  r'   r   r+   r{  r	   OpProtoHolderinstancehas_op_protor   r|   r   _find_var_recursiver}   get_attr_mapr   r   r   r   r   r   r3  r  r  r   )
r   r  r  r   r*   r/   r   r   r0   r   s
             r   r  r  
  s    <((*+q0 uH%668JJ(()=)=)?@@ 3 3 55 ::>>-"6"6"89D-MLL' 9 '')66|7H7H7JKK__""$ #/"5"5"7"="="?"?JD F#005FF"? #/"6"6"8">">"@"@JD F#005FF"@ ++-  
 	++;;=++22;;	
 	rww' **&&(,'++;;=++22;;	
 	uzz*EJJ'w'""++-::<;L;L;NOO  002C+C7 3 P= G
 Gs0    N.,N)N.3N:?N5N:)N.5N:c                   [         R                   " U5      n[        XR                  R                  5       5       H  nU R                  R	                  U5      nUR                  5        H  nX;   d  M
  UR                  XU   5        M      UR                  5        Hn  nSU;  a  M  U R                  R                  UR                  S5      5      (       d  M<  X;   a  MC  [        R                  " U5      n	UR                  X5        XU'   Mp     M     UR                  5        H#  u  pX;   d  M  X*   X+'   UR                  U
5        M%     g )Nr-  r  )r
  r9   r*   r  r0   r:   r   r-   r   r   r   r   r   r   r|  )r   r5  r  target_grad_mapskip_rename_var_listvar_maprI   r   r/   r   gngs               r   _rename_grad_rM  O  s    ii(Gjj&8&8&:;**--'++-D%%dDM: . ,,.Dd"zz""4;;w#788/&//5&&t6 ( / <  )nKOOOA !r!   c                   0 n[        U [        R                  5      (       d   eU R                   H  n[        U[        R                  5      (       d   e[        5       n[        UR                  R                  5       5       H[  n[        U[        R                  5      (       d   eUR                  (       d  M7  UR                  [        UR                  5      5        M]     X1UR                  '   M     U$ r   )r   r	   Programblocksr   rG  r   varsvaluesVariableru   r{  r   r/   r>   )r  r  r   block_no_grad_setr'   s        r   _get_stop_gradients_rU  i  s    Lgy001111%1111E

))+,Cc9#5#56666   !%%&:388&DE - #4UYY   r!   c                    [         R                  " 5       nUS:  a)  U R                  U5      R                  nX2U'   UnUS:  a  M)  U$ )Nr   )r   r   r   
parent_idx)r  current_block_idxson_parent_block_idx_dictparent_block_idxs       r   _get_son_parent_block_idx_dictr[  w  sP     + 7 7 9
q
 "==):;FF7G"34, q
 
 %$r!   c                   [        5       nU b  [        U [         [        [        45      (       a  [	        U 5       H  u  p#[        U[
        R                  5      (       a  UR                  UR                  5        MA  [        U[        5      (       a  UR                  U5        Mi  [        S[        U5       S35      e   U$ [        S[        U 5       35      eU$ )NzSThe type of no_grad_set's member must be paddle.base.Variable or str, but received rq   EThe type of no_grad_set should be set or list or tuple, but received )rG  r   r   r   r\   r	   rS  r{  r/   r   	TypeErrorr+   )rH  no_grad_set_namer=   no_grad_vars       r   _get_no_grad_set_namera    s    ukCu#566"+K"8k9+=+=>>$(()9)9:S11$((5#mnrs~n  nA  AB  C  #9  WX\]hXiWjk  r!   c                   [         R                  R                  R                  5       nU b  [	        U [
        [        [        45      (       ah  [        U 5       HW  u  p#[	        U[         R                  R                  5      (       a  UR                  U5        MA  [        S[        U5       S35      e   U$ [        S[        U 5       35      eU$ )NzHThe type of no_grad_set's member must be paddle.pir.Value, but received rq   r]  )r  autogradbackward_utilsValueSetr   rG  r   r   r\   pirValuer{  r^  r+   )rH  no_grad_set_valuer=   no_grad_values       r   _get_no_grad_set_valuerj    s    66??AkCu#566$-k$: mVZZ-=-=>>%))-8#bcghucvbwwxy 	 %;  WX\]hXiWjk  r!   c                    g r   rb   r   parameter_listrH  r  r  r  s         r   append_backwardrn    s     #&r!   c                    g r   rb   rl  s         r   rn  rn    s     58r!   c                   [         R                  " 5       (       a*  [        R                  R                  R                  XU5      $ 0 n[        U S[         R                  S5        U R                  c  [        U 5        U R                  R                  [        R                  R                  5       [        [        R                  R                  R                   5      [        [        R                  R                  R"                  5      -  5        Ub  [        US[$        [&        4S5        U R(                  R*                  nUR)                  S5      nUR,                  n	UR)                  U	5      n
U	S:g  nU(       d  U=R.                  S-  sl        Uc  [1        5       nO[3        [4        R4                  " U5      5      n[7        U5      nUS   R9                  [%        [;        [<        U5      5      5        U(       a+  UR?                  U
R@                  S9nURC                  U	5        OUn[E        Xy5      n0 nU H/  nUR)                  U5      RF                  RI                  5       UU'   M1     0 n[K        U 5      nU R                  UURM                  5       '   URF                  RO                  5       RQ                  U5        U GH  nUR)                  U5      n[1        [;        [R        UU   5      5      n0 n[U        UU // UU5      n[W        UUU /U5      nUR9                  U5        UU   R9                  [%        [;        [<        U5      5      5        SnU(       d&  UR.                  S:  a  [=        U RX                  5      1nSnUbA  [[        U[$        5      (       a,  []        U5      S:  a  S	n[_        UUU /UUUUU5      u  nnnnGM  [a        UUU /UUUUUUUUS
9  GM     0 nU(       d  X   OSn[c        UUU0 / 5        [e        UUUU5        Xl        URg                  5         URh                   H^  n URk                  U RF                  RM                  5       S5      c  M0  UU RF                  RM                  5          n!U!Rl                  U l6        M`     Ub  [        US[$        [&        [0        4S5        / n"[o        U5       H  u  n#n$[        U$SU# S3[         R                  [p        4S5        [[        U$[         R                  5      (       a  U"Rs                  U$RX                  5        Mh  [[        U$[p        5      (       d  M  U"Rs                  U$5        M     OMURu                  5       Rw                  5       n%U% V$s/ s H"  n$U$Rx                  (       d  M  U$RX                  PM$     n"n$/ n&[        R                  R{                  5       n'U" H  n$U$U;  a  M  UU$   n(U(S   n)U)R}                  U(S   5      (       d  [        SU(S    SU(S    35      eURu                  5       R                  U$5      n*U)R                  U(S   5      n+U(       dM  U R(                  R}                  U(S   5      (       a  U&Rs                  U*U+45        M  U&Rs                  U*S45        M  U&Rs                  U*U+45        M     U& GH%  u  n,n-U-c  M  U(       a  W)Rh                  OURu                  5       Rh                  n.[        U.5       HG  n [[        U [         R                  5      (       d   eU-RX                  U R                  ;   d  M@  U U-l          O   U-R                  c  [        S5      eU,RX                  U-RX                  /n/U-R                  R                  U'5      (       a*  U/R                  U-R                  R                  U'5      5        U-R                  R                  U'U/5        GM(     W(       a  U&W4$ U&$ s  sn$f )a9  
:api_attr: Static Graph

This function appends backward part to main_program.

A complete neural network training is made up of forward and backward
propagation. However, when we configure a network, we only need to
specify its forward part. This function uses the chain rule to automatically
generate the backward part according to the forward part.

In most cases, users do not need to invoke this function manually.
It will be automatically invoked by the optimizer's `minimize` function.

Parameters:
    loss(Tensor): The loss Tensor of the network.
    parameter_list(list[Tensor|str]|tuple[Tensor|str], optional): List/Tuple of Parameters or Parameter.names
                                       that need to be updated by optimizers.
                                       If it is None, all parameters
                                       will be updated.
                                       Default: None.
    no_grad_set(set[Tensor|str], optional): Set of Tensors or Tensor.names in the :ref:`api_guide_Block_en` 0 whose gradients
                           should be ignored. All Tensors with
                           `stop_gradient=True` from all blocks will
                           be automatically added into this set.
                           If this parameter is not None, the Tensors or Tensor.names in this set will be added to the default set.
                           Default: None.
    callbacks(list[callable object]|tuple[callable object], optional): List/Tuple of callback functions.
                                           The callbacks are used for
                                           doing some custom jobs during
                                           backward part building. All
                                           callable objects in it will
                                           be invoked once each time a
                                           new gradient operator is added
                                           into the program. The callable
                                           object must have two input
                                           parameters: ``block`` and ``context`` .
                                           The ``block`` is the :ref:`api_guide_Block_en` which
                                           the new gradient operator will
                                           be added to. The ``context`` is a
                                           map, whose keys are gradient
                                           Tensor names and values are
                                           corresponding original :ref:`api_guide_tensor_en` .
                                           In addition to this, the ``context``
                                           has another special key-value pair:
                                           the key is string ``__current_op_desc__``
                                           and the value is the op_desc of the
                                           gradient operator who has just
                                           triggered the callable object.
                                           Default: None.

Returns:
    list of tuple ( :ref:`api_guide_tensor_en` , :ref:`api_guide_tensor_en` ): Pairs of parameter and its corresponding gradients.
    The key is the parameter and the value is gradient Tensor.

Raises:
    AssertionError: If ``loss`` is not an instance of Tensor.

Examples:
    .. code-block:: python

        >>> import paddle
        >>> import paddle.nn.functional as F

        >>> paddle.enable_static()

        >>> x = paddle.static.data(name='x', shape=[None, 13], dtype='int64')
        >>> y = paddle.static.data(name='y', shape=[None, 1], dtype='float32')
        >>> x_emb = paddle.static.nn.embedding(x, size=[100, 256])
        >>> y_predict = paddle.static.nn.fc(x=x_emb, size=1, activation=None, name='my_fc')
        >>> loss = F.square_error_cost(input=y_predict, label=y)
        >>> avg_loss = paddle.mean(loss)

        >>> # Get all weights in main_program, not include bias.
        >>> all_weights = [param for param in paddle.static.default_main_program().block(0).all_parameters() if 'w_' in param.name]
        >>> all_weights_name = [w.name for w in all_weights]

        >>> # return all param_grads needed to be updated if parameter_list set default None.
        >>> p_g_list1 = paddle.static.append_backward(loss=avg_loss)
        >>> # output: [(embedding_0.w_0, embedding_0.w_0@GRAD), (my_fc.w_0, my_fc.w_0@GRAD), (my_fc.b_0, my_fc.b_0@GRAD)]

        >>> # return the param_grads corresponding to parameter_list that can be list of param (Tensor).
        >>> p_g_list2 = paddle.static.append_backward(loss=avg_loss, parameter_list=all_weights)
        >>> # output: [(embedding_0.w_0, embedding_0.w_0@GRAD), (my_fc.w_0, my_fc.w_0@GRAD)]

        >>> # parameter_list can be list of param.name (str).
        >>> p_g_list3 = paddle.static.append_backward(loss=avg_loss, parameter_list=all_weights_name)
        >>> # output: [(embedding_0.w_0, embedding_0.w_0@GRAD), (my_fc.w_0, my_fc.w_0@GRAD)]

        >>> # no_grad_set can be set of Tensors that means grad will be cut off from these Tensors.
        >>> p_g_list4 = paddle.static.append_backward(loss=avg_loss, no_grad_set=set([x_emb]))
        >>> # output: [(my_fc.w_0, my_fc.w_0@GRAD), (my_fc.b_0, my_fc.b_0@GRAD)]

        >>> # no_grad_set can be set of Tensor.name when the Tensor is created inside layers and can't be specified explicitly.
        >>> p_g_list5 = paddle.static.append_backward(loss=avg_loss, no_grad_set=set(['my_fc.b_0']))
        >>> # output: [(embedding_0.w_0, embedding_0.w_0@GRAD), (my_fc.w_0, my_fc.w_0@GRAD)]

        >>> # return [] because all param_grads are filtered by no_grad_set.
        >>> p_g_list6 = paddle.static.append_backward(loss=avg_loss, parameter_list=all_weights, no_grad_set=set(all_weights))

r   zpaddle.static.append_backwardNr  r   r   )rW  FT)r  r  r  r   rm  zbase.backward.append_backwardzparameter_list[r  zgrad block[z] did not have grad var zUnexpected branch)Gr	   in_pir_moder  rc  ir_backwardrn  r   rS  r0   r   r   r   r   r   r   r   Forwardr   r   r   r   r  rX  r  rG  ra  r
  rU  rF  mapr   r  rW  r	  r[  r*   r  r   r   r   r   r   r  _find_no_grad_varsr/   r   r&   r  r  rM  r2  r   r   r4  _cuda_graph_attrr\   r   r)   r  all_parameters	trainabler  r   r   r'   r   r   r-   r   r,   r   )0r   rm  rH  r  r  r  r   r  
root_blockrX  r  is_in_control_flowr  target_grad_blockrY  block_fwd_op_num_dictr>   r  r   r5  r   rT  r  op_pathr  is_recomputer  checkpoint_namesr  r  r6  
fwd_op_numr0   r  
parametersr=   paramparamsparams_and_gradsop_role_var_attr_name	grad_info
grad_block	param_varr   r>  rK  r   attr_vals0                                                   r   rn  rn    s>   Z **::+
 	
 fi((*I wwtGG''779D++22::;
d--4499
:	; 5M+		
 jj  Gq!J11MM"34M*a/ %%*%e+DIIk,BC'0L O4$8+ FGH #11$// 2 
 	001BC ' >! (%,]]3%7%<%<%D%D%Fc" ) K $D)G26'',,./$$&009.	i(#\)%<=
  D620,
 )7TF$5
 	  -Y&&)+<=>	
  $ ",,q0(<TYY(G'H$ #;--K 1$L 7$	 #" "!%9)-%9q /L M " 	0  #Zb"E:{M !2  ####BGG$7$7$94@L)"''*=*=*?@F"("9"9B $
 !5#+		
 
!.1HAu!!A&##S)/	 %!3!344!!%**-E3''!!%( 2 %%'668.4HfUjejjf
H ;;NNP%!%(	q\
!!)A,//il^+CIaL>R  ((*..u5	>>)A,/!zz!!)A,// ''H(=> ''D(9:##Y$9:% ( !190JNNg6J6J6L6P6P 	 3-Bb)"4"45555vv,,,	   44<011FFAFF#44==.//OOADDII&;<=	,h7# !& !111] Is   *__c                R    U c  / $ [        U [        5      (       a  [        U 5      $ U /$ r   )r   r   r   rc   s    r   _as_listr  '	  s)    y	 H--476A36r!   c                    UR                   nU R                  nUR                  nUS:w  a)  XC:X  a  gUR                  U5      R                  nUS:w  a  M)  g)NrB   TF)r  r>   rW  r   )ancestor_blockr   progancestor_idxrW  s        r   _is_ancestor_blockr  -	  sU    ==D!%%L!!J

%ZZ
+66
 

 r!   c                   U(       a  US   R                   OU nU Vs1 s H  o3R                  iM     nnUR                  U R                  :X  d  [        X 5      (       a  U$ U R                  nUR                  U R                  :w  GaB  UR
                  S:w  d   eUR                  UR
                  5      n[        5       n[        UR                  5       H  n[        UR                  R                  5       U5      (       d  M.  UR                  R                  5        H  n	UR                  U	5        UR                  R                  U	R                  5       5      (       a  MD  UR                  R                  U	R                  5       5      (       d  Mt  UR                  U	5        M     M     UnUnUR                  U R                  :w  a  GMB  U$ s  snf )aH  
In `cur_block`, get output names those linked to targets.
NOTE:
1. `targets` can be in `cur_block`;
Usually, `targets` is in `cur_block`. However, considering control flow,
2. `targets` may be in sub-block but `cur_block` is an ancestor of `targets[0].block`;
3. `targets` may be in the block which is ancestor of `cur_block`.
r   rB   )r   r/   r>   r  r  rW  rG  r   r   r  r*   r-   r:   r{  r   r   )
	cur_blocktargetsr   outcurrent_output_namesr  parent_blockparent_block_output_namesr0   r/   s
             r   _get_output_namesr  :	  sh    !(GAJYE078HH8 yyIMM!%7%I%I## D
))y}}
$2%%%zz%"2"23$'E!599%BRWW5579MNNGG335D(,,T2 ::.. &++44T[[]CC155d; 6 & 8 ))y}}
$"  3 9s   Gc                   [        X5      n/ n[        [        [        U5      5      5       H  u  pgUR	                  S5      (       dx  UR
                  R                  5        HZ  nX;  d  M
  XR
                  R                  5       ;  d  M)  U R                  U   R                  (       a  MI  UR                  U5        M\     UR
                  R                  5        H  n	X;  d  M
  UR                  U	5        M     M     [        U5      $ )zW
Find the vars which is not used in the program, and
those vars belong to no_grad_var.
r  )r  r   r   r\   r   r*   r-   r:   rQ  ru   r)   r{  rG  )
r   r}  r  rH  r1  r`  r=   r0   r  r/   s
             r   ru  ru  a	  s    
 %U4LK$y123{{;''77335/ww'>'>'@@!JJw/===&&w/ 6 GG++-D&  & . 4 {r!   c                h   U Vs1 s H  ofR                   iM     nn[        X5      nUc  0 nS/[        U R                  5      -  n	U(       a  [	        U R                  5       H  u  p[        UR                  R                  5       U5      (       a`  [        R                  " UR                  5      (       d;  UR                  R                  5        H  nX;  d  M
  UR                  U5        M     M  SX'   M     [        [        [	        U R                  5      5      5       GH  u  pUR                  S5      (       a]  UR!                  S5      nU R"                  R%                  U5      nU['        UR                  5      -  n[)        X['        5       XO5      nUXM'   [        UR                  R                  5       U5      (       aa  [        R                  " UR                  5      (       d<  UR                  R                  5        H  nX;  d  M
  UR                  U5        M     GM  SX'   GM
     U(       a  [        [        [	        U R                  5      5      5       H  u  pX   SL d  M  [        UR                  R                  5       U5      (       d  M9  SX'   [        R                  " UR                  5      (       a  Md  UR                  R                  5        H  nX;  d  M
  UR                  U5        M     M     [+        [        U R                  5      5       V
s/ s H  oU
   (       d  M  U R                  U
   PM     nn
U(       ab  U H\  nUR                  R                  5        H;  nX;  d  M
  U R,                  U   R.                  (       d  M*  UR                  U5        M=     M^     U$ s  snf s  sn
f )a>  
It is used to find the grad path in `block`.

Args:
    block(Block): The block in which to get op path.
    targets(list[Variable]): The target variables.
    inputs(list[Variable]): The input variables.
    no_grad_set(set): The set of no grad var name. no_grad_set will be changed.
    op_path_dict(dict): op_path_dict will be changed. op_path_dict will be changed.
        key(int) block index
        val(list) the op path of block(index)
    is_while(bool): Whether or not `block` is while block
Return:
    The forward op path of block corresponding to backward op.
TFr  )r/   r  r&   r   r\   r  r*   r:   r   has_empty_grad_op_makerr+   r-   r{  r   r   r   r  r  r   rG  r  r9   rQ  ru   )r   r  r|   rH  r  r  r  r.   r1  relevant_op_flagsr=   r0   r/   r.  r  r  r"  r}  s                     r   r  r  x	  s   & (..v88vK.$U4LUYY/ uyy)EA''); 22277;;GG446D.#- 7 (-!$ * $y345;;{##,,[9L++L9I%1C8K8K4L%L"0sulN *8L&GG$$&
 
..rww77//1* $$T* 2 $) # 6&  d9UYY#789EA #u,((*L2 2 (,!$33BGG<< " 7 7 92(,,T2 !: : $C		N337K		!3   B//1*uzz$/?/M/M/MOOD) 2 
 N{ /fs   N*N/*N/c                D   [        U 5      n [        U5      n[        U5      nU S   R                  nUR                  nU=R                  S-  sl        UR                  nU(       d  S/[        U 5      -  n[        U 5      [        U5      :w  a  [        S5      eUc  [        5       nO[        [        R                  " U5      5      n[        U5      nUS   R                  [        [        [        U5      5      5        UR                  R!                  5       n[        5       n	0 n
0 n/ n[        5       n[#        U5       GH  u  pX   n[        UR$                  5      nUc  ['        SSUR$                  /0SU/0SUR(                  S	.5      nUR                  R+                  5       R-                  U5        UR                  R/                  5         U	R1                  U5        UR3                  U5        OUR                  R                  U:w  d  UR                  R                  U:w  a  [        S
5      eUR4                  UR4                  :w  a%  [        SUR$                   SUR$                   35      eUR$                  U
[        UR$                  5      '   U	R1                  UR$                  5        UR$                  UU'   UR1                  U5        GM     [6        R8                  " 5       (       a  [6        R:                  " U
5        UR                  S:X  a  Sn	0 nU H(  nUR                  R                  U:w  d  M  [        S5      e   [        [        [<        US   5      5      n0 n[?        X@UUU5      nU n[6        R8                  " 5       (       Ga  [A        URB                  5       GH\  nURD                  S:X  a  M  / nURD                  [6        RF                  RI                  5       ;   ai  [6        RF                  URD                     n[K        U[        5      (       a  UnOU" U5      nU H&  nUR3                  URM                  U5      S   5        M(     UR                  RO                  5        H  nU(       a  UU;   a  M  [        U5      nUU;  d  M%  ['        SSU/0SU/0SU S   R(                  S	.5      nUR                  R+                  5       R-                  U5        UR3                  URQ                  U5      5        M       O   UR                  R/                  5         [S        UUUU5      nUR                  U5        US   R                  [        [        [        U5      5      5        0 n0 n [U        UUU UUUU	UUS9	  [W        XHUX5        [Y        XHUU 5        UR/                  5         U $ )z-
Calculate gradient and return grad_info_map
r   r   Nz:Should have the same number of target_gradients as targetsrM  r  rx   r   rN  z%all targets must be in the same blockz-The shapes of target and grad are different: r   z,input must be in the same program as targets)r  r  r  )-r  r   r  r  r>   r&   r   rG  ra  r
  rU  rF  r   rt  r   r*   r  r\   r/   r   rt   r   r   r   r{  r)   r   r   rO  _set_prim_target_grad_namer   r  r   r   r+   ops_contain_noner  r   r2  r-   r'   ru  r  rM  r2  )!r  r|   target_gradientsrH  r   r  r5  r  r  r  rH  r  rI  grad_name_setr=   gradtarget	grad_namer   r   rT  r  r}  tmp_targetsr0   keep_var_listrR  	none_varsnone_var_namer5   r   r  r6  s!                                    r   calc_gradient_helperr  	  s    wGfF 01AJE==D!#		I 6CL0
7|s+,,H
 	
 e+DIIk,BC'-LO4$8+ FGH##%J5ONEM-.(5	<&v{{m$$ #\\	G JJ  ",,W5MM((* $$Y/ ''	2||9,0D0D0L !HII||tzz) CFKK=PQRVR[R[Q\]  BFO0=> $$TYY/(,		N9%)$9 /<   ""''8 !!Q&#;;$&KLL  C 3\!_EFL 1<G K  ""599%Bww/) Mww$//4466..rww7fd++ &I &r
I%.M!((=)A!)DE &/ GG446 h-&? 4X > 5.'xj)0"#gaj.>.>?	G JJ((*44W=&&uyy':; 7 9 &: 	$$& %w%6K [)O4$8:K LMNKM1!%
 ; 5k=Ir!   c                    [        U5      n/ nU H^  nUR                  U ;  a  UR                  S 5        M&  XR                     nUS   nUR                  US   5      nUR                  U5        M`     U$ )Nr   r   )r  r/   r)   r'   )r6  r|   	grad_vars	input_varr  r  r   s          r   _get_grad_varsr  k
  sr    fFI	>>.T"%nn5I"1J!~~il3HX&  r!   c                    [         R                  " 5       (       a*  [        R                  R                  R                  XX#5      $ [        U UUUS9n[        XA5      n[        U5      S:X  a  US   $ U$ )a
  
Backpropagate the gradients of targets to inputs.

Args:
    targets(Tensor|list[Tensor]|tuple[Tensor]): The target Tensors
    inputs(Tensor|list[Tensor]|tuple[Tensor]): The input Tensors
    target_gradients (Tensor|list[Tensor]|tuple[Tensor], optional): The gradient Tensors
        of targets which has the same shape with targets, If None, ones will
        be created for them.
    no_grad_set(set[Tensor|str], optional): Set of Tensors or Tensor.names in the :ref:`api_guide_Block_en` 0 whose gradients
                           should be ignored. All Tensors with
                           `stop_gradient=True` from all blocks will
                           be automatically added into this set.
                           If this parameter is not None, the Tensors or Tensor.names in this set will be added to the default set.
                           Default: None.

Return:
    (list[Tensor]): A list of gradients for inputs
    If an input does not affect targets, the corresponding gradient Tensor
    will be None
)r  rH  r   r   )	r	   rq  r  rc  rr  calc_gradientr  r  r&   )r  r|   r  rH  r6  r  s         r   r  r  y
  sv    , **88-
 	
 ))	M }5I
9~|r!   c                   [         R                  " 5       (       Ga(  [        U S[        R                  R
                  [        [        4S5        [        US[        R                  R
                  [        [        4S5        [        US[        R                  R
                  [        [        [        S5      4S5        [        US[        R                  R
                  [        [        [        [        S5      4S5        [        U 5      n [        U5      n[        U5      nSSKJn  SS	KJn  Uc  U" 5       nOU" U5      nU" XX#5      nU$ [        U S[         R                  [        [        4S
5        [        US[         R                  [        [        4S
5        [        US[         R                  [        [        [        S5      4S
5        [        XX#5      n[        U5      $ )a  

Backpropagate the gradients of targets to inputs.

Args:
    targets (Tensor|list[Tensor]|tuple[Tensor]): The target Tensors.
    inputs (Tensor|list[Tensor]|tuple[Tensor]): The input Tensors.
    target_gradients (Tensor|list[Tensor]|tuple[Tensor]|None, optional): The gradient Tensor
        of targets which has the same shape with targets, If None, ones will
        be created for them.
    no_grad_set (set[Tensor|str]|None, optional): Set of Tensors or Tensor.names in the :ref:`api_guide_Block_en` 0 whose gradients
        should be ignored. All Tensors with ``stop_gradient=True`` from all blocks will
        be automatically added into this set. If this parameter is not None, the Tensors or Tensor.names
        in this set will be added to the default set. Default: None.

Return:
    (list[Tensor]): A list of gradients for inputs
    If an input does not affect targets, the corresponding gradient Tensor
    will be None.

Examples:

    .. code-block:: python

        >>> # doctest: +SKIP("This has diff in xdoctest env")
        >>> import paddle
        >>> import paddle.nn.functional as F

        >>> paddle.enable_static()

        >>> x = paddle.static.data(name='x', shape=[None, 2, 8, 8], dtype='float32')
        >>> x.stop_gradient=False
        >>> y = paddle.static.nn.conv2d(x, 4, 1, bias_attr=False)
        >>> y = F.relu(y)
        >>> z = paddle.static.gradients([y], x)
        >>> print(z)
        [var x@GRAD : DENSE_TENSOR.shape(-1, 2, 8, 8).dtype(float32).stop_gradient(False)]
r  z paddle.autograd.ir_backward.gradr|   r  NrH  r   )re  )r  zpaddle.static.gradients)r	   rq  r   r  rf  rg  r   r   r+   rG  r  paddle.autograd.backward_utilsre  paddle.autograd.ir_backwardr  rS  )r  r|   r  rH  re  pir_calc_gradient
input_gradoutss           r   	gradientsr  
  s   Z ZZtU+.		
 	ZZtU+.		
 	ZZtUDJ7.		
 	

  T
 /	
 7#&!#$45;	
 "*K";/K&-

 			T5)!	 			T5)!	 			T5$t*5!	 *:HDD>r!   c           	        [        U S[        R                  R                  S5        [        US[        R                  R
                  S5        Ub  Uc  [        5       n[        5       nU R                   Hx  nUR                   He  nUR                   H!  nUR                  UR                  U   5        M#     UR                   H!  nUR                  UR                  U   5        M#     Mg     Mz     Uc  [        UR                  U5      5      nUc  [        UR                  U5      5      n[        X25      n	[!        U S5         [#        X)5       V
Vs/ s HB  u  p[%        U
[        R                  R&                  R(                  5      (       d  M:  Uc  M?  X4PMD     nn
nUR+                  U5      nSSS5        X4$ s  snn
f ! , (       d  f       WW4$ = f)a  
:api_attr: Static Graph

Backpropagate the gradients of the program and apply the gradients with the given optimizer.

Args:
    program (Program): The input program.
    optimizer (Optimizer): The optimizer to apply the gradients.
    inputs (Tensor|list[Tensor]|tuple[Tensor], optional): The input Tensors.
        If None, the inputs will be created from the input variables in the given program. Default:None.
    outputs (Tensor|list[Tensor]|tuple[Tensor], optional): The output Tensors.
        If None, the outputs will be created from the output variables in the given program. Default: None.

Return:
    tuple: tuple (optimize_ops, params_grads), A list of operators appended
        by gradients_with_optimizer and a list of (param, grad) variable pairs, param is
        ``Parameter``, grad is the gradient value corresponding to the parameter.
        The returned tuple can be passed to ``fetch_list`` in ``Executor.run()`` to
        indicate program pruning. If so, the program will be pruned by ``feed`` and
        ``fetch_list`` before run, see details in ``Executor``.

Examples:
    .. code-block:: python

        >>> import paddle
        >>> import paddle.static as static

        >>> paddle.enable_static()

        >>> img = static.data(name='image', shape=[None, 784])
        >>> pred = static.nn.fc(x=img, size=10, activation='relu')
        >>> loss = paddle.mean(pred)
        >>> opt = paddle.optimizer.SGD(learning_rate=1e-3)
        >>> opt_ops, pram_grads = paddle.base.backward.gradients_with_optimizer(static.default_main_program(), opt)
        >>> print(opt_ops)
        [{ParamOut=['fc_0.b_0']} = sgd(inputs={Grad=['fc_0.b_0@GRAD'],
        LearningRate=['learning_rate_0'],
        MasterParam=[],
        ...
        with_quant_attr = False)]

r  z&paddle.static.gradients_with_optimizer	optimizerN)r   r  baserO  r  	OptimizerrG  rP  r   r:   r{  rQ  r-   r   
differencer  r   zipr   r	   	Parameterapply_gradients)r  r  r|   r}   in_setout_setr   r0   r/   gradspramr  
pram_gradsoptimize_opss                 r   gradients_with_optimizerr    s   X 0	 ""0	 ~%^^Eii..DJJuzz$/0 ///DKK

4 01 0   $ >&++G45F?7--f56Gg&E	w	% "&0
0
$ 5 5 ? ?@   TL0 	 
 !00< 
& ##
 
&	% ##s*    F=9F7F7F7F=7F==
Gr   )NN)rw   )rw   N)NNN)NNNNNN).....)r   r   rm  Sequence[Tensor | str] | NonerH  set[Tensor | str] | Noner  ISequence[Callable[[Block, dict[str, Tensor | core.OpDesc]], None]] | Noner  Noner  DistributedContext | Nonereturnzlist[tuple[Tensor, Tensor]])r   r   rm  r  rH  r  r  r  r  list[Tensor]r  r  r  z-tuple[list[tuple[Tensor, Tensor]], list[str]])NNNNN)NF)
r  Tensor | Sequence[Tensor]r|   r  r  z Tensor | Sequence[Tensor] | NonerH  r  r  r  )S
__future__r   r   r
  r  r  r	  r   collections.abcr   typingr   r   paddle.baser  rw   r   r	   r
   r   data_feederr   r   r  r   r   r   paddle.base.frameworkr   4paddle.distributed.auto_parallel.static.dist_contextr   __all__
get_loggerr   INFOrQ   r   r   r   r   r   r   r   r   r   r  r  r   r   r  r!  rB  rS  r  r  r  r  r  r  r  r  r  r+  r0  r2  r  rM  rU  r[  ra  rj  rn  static_onlyr  r  r  ru  r  r  r  r  r  r  rb   r!   r   <module>r     s&   #    	 	  $ *  6 6 # $  (+ 


gll H
} }@	 DHD.
??0B66$		B") @B(0 #(R  Ur 15"CLz!z \H	  1h'6$ <D
.
,o2dB8J4%($ 
 58,/ 	03
&

&1
& *
&
	
& 
& .
& !
& 

& 
 58,/ 	 #03
8

81
8 *
8
	
8 
8 .
8 3
8 

8  `  ` F7
$ N0 FKPh 9=]@*Z  :>,0	r&r%r 7r *	r
 r rj R$ R$r!   