
    yj                      d dl mZ d dlZd dlZd dlZd dlZd dlZd dlZd dlm	Z	 d dl
mZmZ d dlZddlmZmZmZmZ ddlmZ ddlmZ dd	lmZ erd d
lmZ d dlmZ d dlmZ d dlmZ g Z ej         e!ej"        d          Z# G d d          Z$d Z%	 dYdZ&dYdZ'd Z(dZdZ)d Z*d Z+d Z,d Z-d Z.d Z/d Z0	 d[dZ1	 	 d\d Z2	 	 	 d]d!Z3dg fd"Z4d# Z5d$ Z6	 dYd%Z7	 dYd&Z8d' Z9d( Z:d) Z;d* Z<	 	 	 	 	 	 d^d+Z=d, Z>d- Z?d. Z@d/ ZAd0 ZBd1 ZCd2 ZDd3 ZEd4 ZFe	 	 	 	 	 d_d`dD            ZGe	 	 	 	 	 d_dadG            ZGejH        	 	 	 	 	 dbdH            ZGdI ZIdJ ZJdK ZKdL ZL	 dcdNZM	 dZdOZNdP ZOdZdQZPejH        	 	 dZdddW            ZQejH        dZdX            ZRdS )e    )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                  D    e Zd Zd Zd Zd Zd Zd Zd Zd Z	d Z
d	 Zd
S )ProgramStatsc                >    || _         || _        i | _        i | _        d S N)blockopsop_depsvar_op_deps)selfr   r   s      d/lsinfo/ai/hellotax_ai/data_center/backend/venv/lib/python3.11/site-packages/paddle/base/backward.py__init__zProgramStats.__init__2   s%    
    c                   g }| j         D ]}t          | j         |         d                   dk    rYt          | j         |         d                   dk    r5| j                            |          j        rj|                    |           | j        D ]K}|j                                        dk    r,|	                    |j        
                                           L|S )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_nodeszProgramStats.get_input_nodes8   s    $ 	) 	)DD$T*+>?@@AEE(./ABCCaGG:>>$''3 ""4(((( 	? 	?Bw||~~''""27#;#;#=#=>>>r   c                    g }| j         D ]K}|j                                        dk    r,|                    |j                                                   L|S )Nseed)r   r(   r)   r*   r+   )r   var_namer.   s      r   get_reserved_varszProgramStats.get_reserved_varsG   sS    ( 	< 	<Bw||~~'' 8 8 : :;;;r   c                   g }t          ||d          D ]}| j        |         j                                        D ]<}|| j        v r1| j        |         d         D ]}||k    r|                    |           =| j        |         j                                        D ]<}|| j        v r1| j        |         d         D ]}||k     r|                    |           =|S )Nr   r"   r!   )ranger   r(   r+   r   r'   input_arg_names)r   begin_op_idx
end_op_idxr2   ir-   idxs          r   get_out_of_subgraph_varsz%ProgramStats.get_out_of_subgraph_varsN   s
   |Z33 
	2 
	2A(99;; 2 24+++#/56HI 2 2*,,$OOD111(88:: 2 24+++#/56IJ 2 2--$OOD111	2
 r   c                V   t          | j                  }d}|D ]}|| j        vrd||fc S |D ]}|| j        vrd||fc S |D ]*}| j        |         d         }|D ]}t          ||          }+|D ]*}| j        |         d         }|D ]}t	          ||          }+||k    rd||fS d||fS )NFr"   r!   T)r$   r   r   minmax)r   
var_group1
var_group2
min_op_idx
max_op_idxr-   op_idxr:   s           r   is_subgraphzProgramStats.is_subgraph]   s3    ]]

 	5 	5D4+++j*4444 , 	5 	5D4+++j*4444 , 	2 	2D%d+,>?F 2 2 S11

2 	2 	2D%d+,?@F 2 2 S11

2##*j00Z++r   c                J     fd}|dz
  }|}||k    r | j         |                   rrt                              d j         |         j                                         d j         |         j                                        d                     |}|dz  }nn||k    |S )zZ
        persist vars of amp-related cast should be included in recompute segment
        c                    | j                                         dk    o;j                            | j                                         d                   j        S )Ncastr   )r(   r)   r   r%   r6   r&   )r.   r   s    r   is_amp_castz7ProgramStats._update_segment_start.<locals>.is_amp_cast{   sG    &( MJNN27#:#:#<#<Q#?@@Lr   r   zfound amp-cast op: z, : r   )r   _loggerinfor(   r)   r6   )r   min_idxpre_segment_end_idxrI   idx_updated_min_idxs   `     r   _update_segment_startz"ProgramStats._update_segment_startv   s    
	 	 	 	 	 {!((({48D>** t$(4.*=*B*B*D*Dtt$(SW.J]JmJmJoJopqJrtt   #'	 ((( r   c                   t          | j                  D ]\  }}g g d| j        |<   t          |j                                                  D ]E\  }}|| j        v r7| j        |         d                             | j        |         d                    Ft          |j                                                  D ]a\  }}|| j        v r(| j        |         d                             |g           6i | j        |<   |g| j        |         d<   g | j        |         d<   bt          |j                                                  D ]a\  }}|| j        v r(| j        |         d                             |g           6i | j        |<   g | j        |         d<   |g| j        |         d<   b| j        |         d         D ])}| j        |         d                             |g           *d S )N)in_opsout_opsrR   r!   r"   rS   )	enumerater   r   r(   r6   r   r*   r+   )r   r9   r.   jr-   rD   s         r   build_statszProgramStats.build_stats   s   tx(( 	< 	<EAr)+;;DLO$RW%<%<%>%>??  44+++LOH-44(./BC   %RW%<%<%>%>?? E E44+++$T*+=>EEqcJJJJ-/D$T*BCD$T*+=>BDD$T*+>??$RW%=%=%?%?@@ F F44+++$T*+>?FFsKKKK-/D$T*ACD$T*+=>CD#D$T*+>??,q/(3 < <V$Y/66s;;;;</	< 	<r   c                d   g }|D ]}|| j         vrt                              d| d           *| j         |         d         g k    r|                    |df           Y|                    |t	          | j         |         d                   f           t          |d           }d |D             S )NzRecompute Optimizer: deleted z< from checkpoints, because it is not used in paddle program.r!   r=   c                    | d         S )Nr    xs    r   <lambda>z/ProgramStats.sort_checkpoints.<locals>.<lambda>   s
    ad r   keyc                    g | ]
}|d          S )r   rY   .0r[   s     r   
<listcomp>z1ProgramStats.sort_checkpoints.<locals>.<listcomp>   s    111!111r   )r   rJ   rK   r'   r?   sorted)r   checkpoints_namesorted_checkpointsr-   s       r   sort_checkpointszProgramStats.sort_checkpoints   s    $ 	 	D4+++vDvvv    !$'(;<BB"))4*5555"))3t/56IJKKL    $$6NNKKK1101111r   c           
        d | j         D             }d|vrd S d}|t          | j                   k     r?| j         |         }|j                                        dk    r|dz  }I|                    d          ,t          |                    d                    dk    r|dz  }t          j        d          }t          j        d                    |dg                    }| j	        
                    |d	t          j        j        j        d
d
          }|                    d          d
u rdn!t!          |                    d                    }t          j                                        }d}	|j                            |          r|j                            |          }	| j	                            |j        di d|gi||	dd          }
| j                             ||
           |j                            d|g           |j                            d           |j                            d           | j	                                         |dz  }|t          | j                   k     =d S d S )Nc                @    g | ]}|j                                         S rY   )r(   r)   )ra   r.   s     r   rb   zBProgramStats.modify_forward_desc_for_recompute.<locals>.<listcomp>   s"    666rBGLLNN666r   dropoutr   r   Seedr1   .tmpint32F)r-   dtyper)   r&   stop_gradientfix_seed OutT)r1   	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   op_typesrD   r.   op_unique_namevar_unique_name	added_varr1   op_device_attr_namers   added_ops              r   !modify_forward_desc_for_recomputez.ProgramStats.modify_forward_desc_for_recompute   sq   66TX666H$$Fs48}}$$&!Bw||~~**!xx+BHHV4D4D0E0E0J0J!(1&99N)E.%011 O 
--$\)6!# .  I 
++u4411#bggfoo:N:ND /AACC   Iw 344 >GLL)<==	 z,,f,#)$OO -  H HOOFH---Gf&7888G
+++G'''J%%'''aKF[ s48}}$$$$$$r   N)__name__
__module____qualname__r   r/   r3   r;   rE   rP   rV   rf   r   rY   r   r   r   r   1   s                , , ,2  2< < <62 2 2"3 3 3 3 3r   r   c                   d                     |dz   t          |                                           |dz   d                    |                                           |dz   d                    |                                                     }|S )Nz3{}	name:[{}]
{}    	inputs:[{}]
{}    	outputs:[{}]_op_input _output)formatstrr)   r}   r6   r+   )op_descprefixout_ss      r   _pretty_op_desc_r      s~    FMMGLLNN((**++))++,, E Lr   c                8   t          |           dk    rg S g }t          j                                        }t          j        j        j        }| D ]J}|}	d}
t          |t          j                  r	|j	        }d}
t          |t                    r|d         }d}|                                D ]8}|                    |          r|                    |          j        r2||vrd}9|r|
r||	||                                <   |j	                                        }|                    |           |                    ||           |                    d          r)|                    d|                    d                     |                    |           L|S )Nr   FTrs   )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      s    5zzQ	L7GGII.5>H - -"dI.// 	&9D!%dE"" 	7D	))++ 	! 	!D!!$'' JNN4,@,@,L >)) 	 	-! G&:&F;F$T%5%5%7%78*..00K!!$'''!!"3X>>>}}[)) K%%k499[3I3IJJJ,,,r   c                   t          |           dk    rg S g }t          j                                        }t          j        j        j        }| D ]}t          |t          j                  r%||||j	        
                                <   |j	        }t          |t                    r|d         }|j	                                        }|                    |           |                    ||           |                    d          r)|                    d|                    d                     |                    |           |S )Nr   rs   )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     s5   
5zzQ	L7GGII.5>H ) )dI.// 	#/@D$TY%:%:%<%<=9DdE"" 	7Dj**,,d###/:::==%% 	G!!+tyy/E/EFFFK((((r   c                   t          | j        j                  D ]U}t          |t          j                  sJ t          |j                  dk    r|j        d         | j        k    r	|| _	         nV| j	        t          d          d S )Nr   r   z"loss.op is None. Should not happen)reversedr   r   r   r	   r   r$   r+   r-   r.   
ValueError)lossr.   s     r   _find_loss_op_r   6  s    tz~&&  "i011111#$$))#A&$)33DGEw=>>> r   c                6   |d}|t          |           }t          | t          t          f          rdt	          ||          D ]S}| |         }t          |t                    r|d         }|                    ||           |                    ||           Tt          | t          j                  rg| 	                                D ]T\  }}t          |t          t          f          r1|D ].}|                    ||           |                    ||           /SdS dS )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   r5   _rename_input_rename_outputcollectionsOrderedDictitems)	op_descsold_namenew_name	begin_idxend_idxr9   r   r^   values	            r   _rename_arg_r   C  s<   
 	h--(T5M** 7y'** 	7 	7AqkG'5)) %!!*!!(H555""8X6666(K344 ?"..** 	? 	?JC%$// ?$ ? ?G))(H===**8X>>>>? ?	? 	?r   c                   t          j                    }|                    |            |                                D ]%\  }}|                    |d |D                        &|                                D ]%\  }}|                    |d |D                        &t           j                                        }t           j                                        }||vrt           j        j	        j
        ||<   ||vrd||<   |                                D ]Q\  }	}
t          |
t          j                  r|                    |	|
j                   ;|                    |	|
           R|S )zS
    Create a C++ OpDesc object with specified inputs, outputs and attributes.
    c                d    g | ]-}t          |t                    r|                                n|.S rY   r   bytesdecodera   args     r   rb   z$_create_op_desc_.<locals>.<listcomp>d  3    MMMZU33<SZZ\\\MMMr   c                d    g | ]-}t          |t                    r|                                n|.S rY   r   r   s     r   rb   z$_create_op_desc_.<locals>.<listcomp>i  r   r   rq   )r   OpDescset_typer   r   
set_outputr   r   r   r   r   r   r	   r   set_block_attrr(   r   )op_typerv   rw   rx   r   paraargsr   r   r-   vals              r   _create_op_desc_r   [  s    kmmGWllnn 
 

dMMMMM	
 	
 	
 	
 mmoo 
 

dMMMMM	
 	
 	
 	
 7GGII9KKMM%%+2; 	  %''%'!"[[]] ) )	cc9?++ 	)""42222dC((((Nr   c                0   t          | j                  dk    s	d| j        v r| j        }ndg}t          di dt          | j                  gid|ddd| j        d	d
t          j                                        t          t          j        j
        j                  t          t          j        j
        j                  z  t          j                                        | j                            t          j                                                  i          }|S )Nr   r   fill_constantrr   shaper         ?rn   rt   F)r$   r   r   _append_grad_suffix_r-   rn   r   r   r   r   r   r   Lossr   r.   r   )r   create_shaper   s      r   _create_loss_op_desc_r   |  s    
4:!qDJzs
	%di0012\STZ+;;==s/6?@ @ $18=>>@? +==??/AACCB B	
	 G$ Nr   c                N   |j                             |                                           }t          |           }|j                             |                                          r||j                             |                                          }|                    |                                           |                    |	                                           dS t          j        d|  d           |                    t          j        j        j                   dS )z>
    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_dtypern   	set_shaper   warningswarnr   r   r   FP32)grad_var_namer   grad_varfwd_namefwd_vars        r   _infer_var_data_type_shape_r     s     z""=#7#7#9#9::H"=11Hz##HOO$5$566 	6*//0A0ABB7==??+++7==??+++++ 	o]ooo	
 	
 	
 	4</455555r   c                H    t          |           dk    rdS | D ]	}||vr dS 
dS )z8
    Test if all elements of 'cands' are in set 's'
    r   FTr$   candsscs      r   _all_in_set_r     sA     5zzQu  A::55 4r   c                H    t          |           dk    rdS | D ]	}||v r dS 
dS )z9
    Test if some elements of 'cands' are in set 's'
    r   FTr   r   s      r   _some_in_set_r     sA     5zzQu  6644 5r   c                :   t          j        t          j                     d|           p(t          j        t          j                     d|           }|| d|                                         n| }|                     d          }|dk    r||dz   d         n|S )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/r=      )researchr   grad_var_suffixstartrfind)r-   posr   new_poss       r   r   r     s     )t+--1114
8
8 BI!!$$$d= =C '*otMciikkM""4Hjj!!G&-mm8GaKMM""Ar   c                .    | t          j                    z   S )zM
    Append grad suffix to the given variable name
    e.g. x ==> x@GRAD
    r   r  r-   s    r   r   r     s    
 $&((((r   rq   c           	         ||                                 vrg ||<   ||                             t          dd||          id| gid|i                     | g|| <   dS )zW
    Use sum op to accumulate_gradients, the gradients are stored in renamed_vars.
    sumXrr   rs   N)keysr'   r   )r2   renamed_varspending_sum_opsrD   rs   s        r    _accumulate_gradients_by_sum_op_r    s     _))++++"$F"",x()XJ)$		
 	
   'ZLr   c           
        ||                                 vrg ||<   ||          d         }t          dt          ||                              D ]}|}||          |         }	|t          ||                    dz
  k    r| dz   t          |          z   }n| }||                             t          d|g|	gdd|gid|i                     || |v r||          ||<   | ||<   | g|| <   dS )	zg
    Use several inplace add op to accumulate_gradients, the gradients are stored in renamed_vars.
    r   r   z@ADD@grad_add)r  Yrr   rs   N)r  r5   r$   r   r'   r   )
r2   r  r  rD   rs   grad_var_to_varout_namer9   x_namey_names
             r   !_accumulate_gradients_by_add_ops_r    s7    _))++++"$H%a(H1c,x01122 5 5h'*L*++a///')CFF2HHH&&hfX..
#i(	 	
 	
 	
 &?**,;H,E)),4)&ZLr   c           
        t          j                    d         }i t          j                    }t          j        t
                    }t          j        t                    t          j        t                    }t          j        t                    }	fd}
t          |           D ]w\  }}t          j
                                        }d}|                    |          r|                    |          }|                                D ]dvrt                             dk    rct                             |k    r% |
           t!          |||	                    ^ |
           t#          |||	         |           t          |                                          D ]l\  }}|                    |          }t          |          D ]@\  }dvrt          j                    k    s|                                v r9t                             dk    rg<   ||<   r|v r|         nd<   qt                             dk    rdz   t          |          z   dz   t          |                   z   |xx         dz  cc<   ||v r|         |<   n|<            <            d<   t+          | |         |           t+          |           |                                d	|         D ]>}|                    |          }|v r#|                    |fd
|D                        ?fd|d	|         D             ||d	         z   }dz   t          |          z   dz   t          |                   z   |xx         dz  cc<   ||v r|         |<   n|<   ||<   |                    ||                                                   ||	<   r|v r|         nd<   Bny                                D ]\  }t                             dk    r|t                             |k    r2 |
           t!          |t          |           |	                    i |
           t#          |t          |           |	                    t          |           }t          j        t3          t          |                                                                                              D ]\  }}|}t          |          D ]\  }}||k    r|dz
  n||z   }|d|                    | |                                         d	          	 5|| |                                                  ||                                <   |                     ||z   |           | S )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                R    d S |          }|                     fd           d S )Nc                    |          S r   rY   )r[   topo_order_for_grad_names    r   r\   zQ_addup_repetitive_outputs_.<locals>._change_order_by_topo_order.<locals>.<lambda>2  s    (@(C r   r]   )sort)r2   origin_namesr  topo_order_for_backwardr"  s     r   _change_order_by_topo_orderz?_addup_repetitive_outputs_.<locals>._change_order_by_topo_order.  s?    "*F#H-CCCCDDDDDr   rq   @GRADr   r   z@RENAME@block@Nc                $    g | ]}|k    rn|S rY   rY   ra   r[   r   r2   s     r   rb   z._addup_repetitive_outputs_.<locals>.<listcomp>  s5     %& %& %&,- 56MMq%& %& %&r   c                $    g | ]}|k    rn|S rY   rY   r*  s     r   rb   z._addup_repetitive_outputs_.<locals>.<listcomp>  s5     % % % ! )*XHH1% % %r   )r	   _global_flagsr   r   defaultdictr   r   r   rT   r   r   r   r   r   r6   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   rs   	param_idx
param_name	arg_namesarg_idxpp_arg_namesrv   op_descs_lenr^   r   r9   r.   
target_idxr   r  r"  r2   s        `                       @@@@r   _addup_repetitive_outputs_r?    s   $ +--.JKM!!-//O".s33*400L'3D99(--JE E E E E E E "(++ D DW+==?? 	 	/00 	:%899I//11 	 	Hh&&<)**Q..|H-..>>//9994 $'"8,    0/9995 $'"8,'   &/w/C/C/E/E%F%F e	 e	!Izz22I%.y%9%9 c c!(**  3 5 5557#:#:#<#<<< |H-..!33.6ZL*69)(3 3#'>>> 088 	 -X66 <122a77$-.!)nn- "" ""28"<==	> ! )222a7222*6'?::<K$,=" 9 9 =E 9 5X> 1: 5=X.q1
 %$$$1(;   %_hIII!(!5!5!7!7

!C 	" 	"A*1..*;*;K';66 ' 2 2$%%& %& %& %& %&1<%& %& %&!" !" !"% % % % %%.xx%8% % % &ghh/%0	 !)*i..)  .x899	:  %X...!3...&2#668G (9OH55 9AOH5)1Ig&&&z9=== *11(;;;+4Jx( 3#'>>> 088 	 -X66}ce	N )..00  &|H%&&**<)**]::++H5550 #MMx(    ,+H5551 #MMx(   x==L!-o++--..// egg) )
U u%% 	) 	)EAr$'<$7$7qS1WJ$0(,,Z(4466  
 :NZ(4466:$R^^%5%56 OOC!GR((((	) Or   c           
     n   
 fd
d |D             
fd D              g }t          j                    st                     D ]\  }}|                                D ]}t          j                    |v r|v rt          |          }t          dd|gid|giddd	          }	|X|                    |                                d
          	 /||                                         ||	                                <   |	                    |	|f           ш fdt          |          D               S )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                    |                                  }t          |          dk    st          ||          rdS t          d |                                 D             |          r'|                    t          |          z
             dS dS )Nr   Tc                f    g | ].}|                     t          j                              d k    ,|/S )r=   findr   r  )ra   r-   s     r   rb   zH_remove_no_grad_branch_.<locals>._op_can_be_removed_.<locals>.<listcomp>  sB       99T13344:: :::r   F)r+   r$   r   r6   updateset)r   no_grad_setout_arg_namestarget_grad_var_namess      r   _op_can_be_removed_z4_remove_no_grad_branch_.<locals>._op_can_be_removed_  s    0022}""l=+&N&N"4 #3355  
 
 
 		 s=114IIJJJ4ur   c                D    h | ]}|j         t          j                    z   S rY   )r-   r   r  ra   r%   s     r   	<setcomp>z*_remove_no_grad_branch_.<locals>.<setcomp>  s5       .14')))  r   c                ,    g | ]} |          |S rY   rY   )ra   r   rJ  rG  s     r   rb   z+_remove_no_grad_branch_.<locals>.<listcomp>
  s<       ""7K88  r   fill_any_liker  rr   r   r=   r   rn   Nc                T    g | ]$}                     |d          |d                   %S )r   r   )r   )ra   r;  r   s     r   rb   z+_remove_no_grad_branch_.<locals>.<listcomp>,  s/    >>>QX__QqT1Q4  >>>r   )r   _is_bwd_prim_enabledrT   r6   r  r   r   r1  r   r'   r   )r   rG  r   target_vars	to_insertr:   r   r   x_inr   rJ  rI  s   ``        @@r   _remove_no_grad_branch_rV    s       " 5@        H I$&& 9%h// 	9 	9LC..00 9 9'))S00SK5G5G.s33D #3'tf"#b11	# #K -8044#//114   $$ 11D1D1F1FG -[-D-D-F-FG $$k3%7888/92 ?>>>(9*=*=>>>>Or   c                    G fdd           G fdd          i fdfdfd}|t                      nt          |          }|D ]Z}|                    |j                                                   |                    |j                                                   [t                      }t                      }| D ]}t          |                                          }	|	|z
  |z
  }
|                    |                                            ||          }t          |
          t          |	          k    r|                    |           g }|D ]}|g}t          |j                  }d	}|g}t          |          d
k    r|                    d
          }t          |j        |          rY|j
        D ]6}|                    |j                   |                    |j                   7|                    |j
                   nd}nt          |          d
k    |r|                    d |D                        t          |          }t          |           }||k    rt                      S |S )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                  *    e Zd Zd Z fdZ fdZdS )_find_not_need_ops.<locals>.Varc                0    || _         d | _        g | _        d S r   )r2   gen_oppending_ops)r   r2   s     r   r   z(_find_not_need_ops.<locals>.Var.__init__D  s    $DMDK!Dr   c                L    t          |          sJ | j        J || _        d S r   )r   r[  )r   r[  Ops     r   
set_gen_opz*_find_not_need_ops.<locals>.Var.set_gen_opI  s2    fb)))));&&& DKKKr   c                `    t          |          sJ | j                            |           d S r   )r   r\  r'   )r   r.   r^  s     r   add_pending_opz._find_not_need_ops.<locals>.Var.add_pending_opN  s6    b"%%%%%##B'''''r   N)r   r   r   r   r_  ra  )r^  s   r   VarrY  C  sV        	" 	" 	"
	! 	! 	! 	! 	!
	( 	( 	( 	( 	( 	( 	(r   rb  c                  *    e Zd Zd Z fdZ fdZdS )_find_not_need_ops.<locals>.Opc                0    || _         g | _        g | _        d S r   )r   rv   rw   )r   r   s     r   r   z'_find_not_need_ops.<locals>.Op.__init__S  s    "DLDKDLLLr   c                `    t          |          sJ | j                            |           d S r   )r   rv   r'   r   r%   rb  s     r   insert_inputz+_find_not_need_ops.<locals>.Op.insert_inputX  s5    c3'''''Ks#####r   c                `    t          |          sJ | j                            |           d S r   )r   rw   r'   rg  s     r   insert_outputz,_find_not_need_ops.<locals>.Op.insert_output\  s5    c3'''''L$$$$$r   N)r   r   r   r   rh  rj  )rb  s   r   r^  rd  R  sV        	 	 	
	$ 	$ 	$ 	$ 	$	% 	% 	% 	% 	% 	% 	%r   r^  c                    |                                  vr |           g| <   n$|                               |                      |          d         S Nr=   )r  r'   r-   rb  var_versionss    r   _create_nodez(_find_not_need_ops.<locals>._create_nodeb  sb    |((****"%#d))L%%cc$ii000D!"%%r   c                j    |                                  vr |           g| <   |          d         S rl  )r  rm  s    r    _create_or_get_last_version_nodez<_find_not_need_ops.<locals>._create_or_get_last_version_nodei  s>    |((****"%#d))LD!"%%r   c                R    |           }|                                  D ]8} |          }|                    |           |                    |           9|                                 D ]8} |          }|                    |           |                    |           9|S )Nr  )r6   ra  rh  r+   r_  rj  )r   op_noderz   r%   r/  r^  ro  rq  s        r   _create_op_nodez+_find_not_need_ops.<locals>._create_op_noden  s    "W++,,.. 	& 	&E22>>>Cw'''  %%%%..00 	' 	'F,F+++CNN7###!!#&&&&r   NTr   Fc                    g | ]	}|j         
S rY   )r   )ra   nodes     r   rb   z&_find_not_need_ops.<locals>.<listcomp>  s    %G%G%Gtdl%G%G%Gr   )rF  rE  r(   r6   r+   r$   addrv   popr   rw   r*   r\  )grad_op_descsforward_opsinput_grad_names_setrt  forward_vars_setr.   backward_vars_setspecial_op_nodesr   	input_setnew_varsrs  not_need_op_descsspecial_op_nodeop_list
ready_vars
remove_opscandidate_opsout_varnot_need_op_descs_setgrad_op_descs_setr^  rb  ro  rq  rn  s                        @@@@@r   _find_not_need_opsr  1  sJ   $( ( ( ( ( ( ( ( ( (% % % % % % % % % % L& & & & & && & & & & &

 
 
 
 
 
 
 &-37K3L3L   < < 7 7 9 9::: 8 8 : :;;;; uu  * *//1122	//2CC  !9!9!;!;<<<!/'**x==C	NN**  ))) , I I"#/00

()-  1$$#''**GGNJ77 & 8 8G!(()<===NN7#67777!!'/2222"
 -  1$$  	I$$%G%Gw%G%G%GHHH 122M** 111uu  r   c                    |                                  }t          j                            t	          |                    }|                                S r   )serialize_to_stringr   r   
FromStringr   __str__)r   protostrprotos      r   serialize_op_decsr    s=    **,,H ++E(OO<<E==??r   c                Z   d |D             }t          t          |                    }| j                                        }	| j                                        }
t	          | |          }|                                 |                                 |                    |          }g }t          |          dk    rdd}|d         g}|D ]5}||j	        vr n)|j	        |         d         }|D ]}t          ||          }6|dk    r|                    d|dz   g           nd}d}	 |t          |          dz
  k    rn|                    ||         g||dz            g          \  }}}|r1|                    ||          }|                    ||dz   g           n$t                              d| d|dz    d	           |dz  }|g k    r&|d         d         dk    rd|d         d         gg|}n|}t!          |          D ]\  }\  }}t                              d
| d           t                              d||         j                                         d||         j                                         d           t                              d||dz
           j                                         d||dz
           j                                         d           g }|D ]7}|                    |                    |d         |d                              8t          |          t          |          z
  }t                              dt          |           d| d           |                    |                                           |                    |                                           t          t          |                    }g }i }||z   } t          |          }!t0          j                                        }"|g k    r9|d|!         }#t7          |#          D ]}$|$                    d          r5t;          d                    t?          |$j        d                              t1          j         |$j        || j!                 g           \  }%}&||%D ]}'|$||'"                                <   |$j                            |"          r5|$j        #                    |"          }(|%D ]}'|'$                    |"|(           tK          |%|	|          })|                    |)           |&                    |&            t!          |ddd                   D ]\  }}||d         |!         }#|d         }!t7          |#          D ]}$|$                    d          r5t;          d                    t?          |$j        d                              t1          j         |$j        || j!                 g           \  }%}&||%D ]}'|$||'"                                <   |$j                            |"          r5|$j        #                    |"          }(|%D ]}'|'$                    |"|(           tK          |%|	|          })|                    |)           |&                    |&            ||d         |d                  }*d| }+|*D ]B}$|$                    d          r5t;          d                    t?          |$j        d                              g },|,                    |$j                                                   |,                    |$j        '                                           |,D ]}| (                    |          j)        s||v r!||v r&||vrn||+z   ||<   | j        *                                (                    |          }-| +                    ||         |-j,        |-j-        |-j        |-j)        |-j.                   Dt_          |*|
| | |          }.tK          |*|	|          })|D ]}/ta          |.|/||/                    |                    |.           t7          |)          D ]}'t1          j         |'|| j!                 g           \  }%}&|4|%D ]1}0||'"                                         ||0"                                <   2|'                    |"          r0|'#                    |"          }(|%D ]}0|0$                    |"|(           |D ]}/ta          |%|/||/                    |                    |%           |&                    |&           tc          || j!        |          }te          ||| j!                 ||          }tK          |||          })||||fS )a  
    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
    c                    g | ]	}|j         
S rY   r  r`   s     r   rb   z:_append_backward_ops_with_checkpoints_.<locals>.<listcomp>  s    4441444r   r   r=   r   r!   Tz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   rn   r)   r&   ro   r   )3r   rF  program_create_blockr   r   rV   rf   r$   r   r?   r'   rE   rP   rJ   rK   rT   r(   r)   r6   r*   r;   r3   r/   r   r   r   r   r   	Exceptionr   r   get_grad_op_descr:   r   r   r   r   rE  r+   r%   r&   global_blockr~   r   rn   ro   r   r   r?  rV  )1r   r   rS  target_blockno_grad_dictgrad_to_varcheckpointsr   rd   local_blockbuffer_blockprogram_statsegmentsrC   	var_groupr-   rD   r:   	start_idxrM   flagrL   max_idxrecompute_segmentsr9   idx1idx2vars_should_be_holdsegment
cross_varsry  var_name_dictvars_in_memorymax_calculated_op_positiondevice_attr_namegap_opsr.   grad_op_descop_grad_to_varr   rs   added_descsff_ops
var_suffixinput_and_output_namesref_varbuffer_descsr^   	g_op_descs1                                                    r   &_append_backward_ops_with_checkpoints_r    sl   R 54444C 01122---//K=..00Ls++L22444 $445EFFH
!!
%a()	 	2 	2D<333!-d34GHF 2 2 S11

2>>OOQ
Q/000	 	C 011A555 &2%=%=!),-0@Q0O/P& &"D'7  	&<<0  'A+ 67777RWRR7Q;RRR   NI'	* 2~~(1+a.A-- (1+a.1=H=%$%788 
 
<D$.!...///`#d)."5"5"7"7``SY^=[=[=]=]```	
 	
 	
 	fD1H 2 7 7 9 9ffs4!8}?Q?a?a?c?cfff	
 	
 	
 	

 % 
 
""11'!*gajII	
 	
 	
 	
 ())C0@,A,AAJLL 	N#j//  	N  	N*  	N  	N  	N  
 |==??@@@|;;==>>>s#67788 MM(+;;N!$S6HHJJRa2237## 	/ 	/B{{;'' $$*F(2BCC% %   ,0+@ei0", ,(L.
 $/+ E EGBD()<)<)>)>?? w 011 CGLL)9::	+ C CG%%&6	BBBB-k+? K   ---~.... 244R4 899 e/ e/
7gaj#==>%,QZ"7## 	/ 	/B{{;'' $$*F(2BCC% %   ,0+@ei0", ,(L.
 $/+ E EGBD()<)<)>)>?? w 011 CGLL)9::	+ C CG%%&6	BBBB-k+? K   ---~....WQZ'!*,-$__
 	 	B{{;'' $$*F(2BCC% %   &(""))"'*A*A*C*CDDD"))"'*B*B*D*DEEE.  99T??. $:J2J2J...},,*.*;M$' $m88::>>tDDG$$*40%m%m$\$+$7&-&; %   ( 2L%9M
 
 *K!5
 

 ! 	@ 	@CsM#,>???? 	\***  ,, 	/ 	/G+/+@ei0", ,(L.
 $/!-  I,W-@-@-B-BC ))>)>)@)@AA
  011 E#LL)9::	!- E EI''(8)DDDD$ D D\3c0BCCCC  ...~....+	/0 /uy7K  M ,UY	 M &|%9 K 		 r   c                    |                     d          r j        |                    d          k    sJ t          |t          t          d          f          sJ ||j        }|j        dv rw fd|D             }|D ]G} j        D ]=}||j        v r2|j        D ]*}|	                     
                    |                     +>H|j        dv }	t           |g |||	          }
|
S  j        S )a  
    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whilec                :    g | ]}                     |          S rY   )_var_recursive)ra   r%   r  s     r   rb   z'_get_sub_block_path.<locals>.<listcomp>  s4     
 
 
.1I$$S))
 
 
r   )r  )r   r:   _block_attr_idr   rF  r)   r+   r   r6   r'   r  _find_op_path_)r  sub_block_op_descrG  op_path_dictsub_block_target_namessub_outputsr%   r   r-   is_whilesub_block_op_paths   `          r   _get_sub_block_pathr    sb   . %%  I
-,;;KHH
H
H
HI ,sDJJ.?@@@@@%!2!C !???
 
 
 
5K
 
 
 * 	K 	KC$= K K'222 ' 7 K K#**9+C+CD+I+IJJJJK %)Y6*{B\8
 
 ! =r   c                   t           j        }t           j        j        j        }|                                | j        v rLt          |                                 |                                                   t          |          k    rdS dS )NTF)	r   r   r   r   kOpRoleVarAttrName
attr_namesr   	all_attrsr   )r.   op_makerr   s      r   _is_grad_op_r    sx    .H.5>H""$$55#
x//112; ;	X; ; t5r   c                    d|z  | z   S )Nr  rY   )r-   
grad_orders     r   _rename_grad_name_r    s    Z$&&r   c                   i }| j         D ]}|j        D ]}|||<   i }d |D             }d |D             }d}t          |          dk    r{|                    d          }	|	|vr-||	         }
|||
<   |dz  }|
j        D ]4}||v r.||vr*|                    |           |                    |           5t          |          dk    {|S )zGAnalysis forward block and build a mapping from:
    OpDesc -> Int
    c                    g | ]	}|j         
S rY   r  rL  s     r   rb   z#_topo_order_map.<locals>.<listcomp>  s    ---#SX---r   c                    h | ]	}|j         
S rY   r  rL  s     r   rM  z"_topo_order_map.<locals>.<setcomp>   s    ///Csx///r   r   r   )r   r+   r$   rx  r6   r'   rw  )r   rS  get_defined_opr.   r  topo_order_mapqueuevisitedtopo_order_countercur_var_namecur_opinps               r   _topo_order_mapr    s!    Ni * *+ 	* 	*H')N8$$	* N-----E//;///G
e**q..yy||~---!3va) 	! 	!Cn$$G););S!!!C    e**q.. r   c                    i }d |                                  D             } |                                 D ]\  }}|| vr
|D ]}| |         ||<   |S )Nc                $    i | ]\  }}|j         |S rY   )r(   )ra   r.   orders      r   
<dictcomp>z'_topo_bwd_order_map.<locals>.<dictcomp>2  s     IIIyr5BGUIIIr   )r   )topo_fwd_mapbackward_op_maptopo_bwd_mapfwd_opbwd_opsbwd_ops         r   _topo_bwd_order_mapr  0  s    LIIL4F4F4H4HIIIL*0022 8 8%% 	8 	8F#/#7L  	8r   c                   )*+, ),fd}|At          |t          t          f          sJ |D ] }t          |          st	          d          !g }| j        }i }|
i }
t          |
t                    sJ t          j                    r|	                                
                                }|j        D ],,j        D ][}|j                            |                                          s-|t          j                    k    s|                    |           \,j                            |j                   ,j                            |j                   t)          |          D ],g },                    d          r|                    ,                    d                    }|                                }|                    |j                   t7          j                  }d|,                    d                   }t9          |||||||||
  
         ||                                 |                    |j                   g )i }t          j                    rid }t          j        |j                              || j        ,j                            ||j                 |          \  )})D ]}tC          ||           n)t          j        ,j        || j                 |          \  )})|,j        <   |)D ]},||"                                <   |	 ||	||j#                   nEtI          tJ          j&        j'        j(        j)        dd          }||j*        }	 ||	||j#                   t          j+        ,                                },j                            |          r5,j        -                    |          })D ]}|.                    ||           |j#        d	k    r)D ]},j        /                                }|/                                D ]&}||
v r ||vr|0                    ||
|                    '|                                D ]}d
|vr| j        1                    |                    d                    rqte          ||j#                  } |3                    ||            | |
|<   ||v r=|	||         |	j4        |j#                 | <   ||         || <   |5                    |           fd*d}!g }")D ]%}|"*fd|/                                D             z  }"&tm          |"          dk    rd}!to          |"          rHd}!)D ]C}|                    |           |                                D ]}8                    |           D|!r|9                    |           ^|:                    )           |9                    |           d}#|	|	j4        |j#                 }#tv          j<        =                    dd          dv r!t}          | |          }$t          |$|          }%nd}%t          || j        |#||%          }t          ||| j                 ||          }t          j                    s t          ||          ++fd|D             }nt          jD        d           t          j+        E                                }&t          j+        jF        jG        }'|D ]}}|j        H                                }(|(I                    |           |(.                    |&|'           |(|d<   |0t          |t          t          f          sJ |D ]} |||           ~dS )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                    | j         |                             |           D ]R}|                                | j        vsJ j                                        | j        |                                <   Sd S r   )r  rE  r   grad_op_id_to_op_idr(   )distop_contextr  appending_grad_timesr   r  r.   s       r   update_distop_contextz4_append_backward_ops_.<locals>.update_distop_contextc  s     	&';<CC	
 	
 	
 $ 	 	G##%%^-OOOOO ##%% .w/B/B/D/DEE		 	r   Nz%'callback' must be a callable object.r  r  r  c                    t          |                                           D ]}||                     |          k    r|c S  dS rl  )r5   op_sizer.   )
block_desccur_op_descr:   s      r   find_op_indexz,_append_backward_ops_.<locals>.find_op_index  sO     !3!3!5!566 # #C"jmmC&8&888"


 9rr   _g_default_distributed_contextr   r'  asciic                `    |                      t          j                              dk    p| v S rl  rC  )r-   r{  s    r   r\   z'_append_backward_ops_.<locals>.<lambda>  s2    TYYt';'='=>>"D 0// r   Fc                *    g | ]} |          |S rY   rY   )ra   r-   is_grad_names     r   rb   z)_append_backward_ops_.<locals>.<listcomp>%  s9     % % %#|D))%% % %r   r   TFLAGS_program_topo_reorderFalse)True1true)r   r%  c                    g | ]}|v|	S rY   rY   )ra   r   not_need_opss     r   rb   z)_append_backward_ops_.<locals>.<listcomp>g  s*     
 
 
G<4O4OG4O4O4Or   z8Running backward composite and disable find_not_need_ops__current_op_desc__)r   context)Jr   r   r   callabler   r  dictr   rR  clonecurrent_blockr   r+   r(   r   r   r0  r~   infer_var_typeinfer_shaper   r   r   r  r  _set_forward_block_idxr:   copy_append_backward_ops_	_rollbackr'   r  r.   infershape_for_compositer   _appending_grad_timesgetattrpaddledistributedauto_parallelstaticdist_contextdist_op_contextr   r   r   r   r6   r   r   r  r   r  rx  r$   r   rw  rE  r*   osenvironr1  r  r  r?  rV  r  loggingdebugr   r   r   r   r   )-r   r   rS  r  r  r  	callbacksr{  r  r  rename_var_mapr   r  cbry  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  rs   forward_op_inputsr   is_append_gradinput_grad_namesr  
topo_orderr%  r   r   r   r  r  r  r.   s-          `                                 @@@@r   r  r  ;  sQ	   P      )dE]33333 	J 	JBB<< J !HIIIJ MmGnd+++++ "" 6!--//7799 "% 	6 	6B+ : :#(::4;;==II:t24444#..D.999G""?#7888G 45555 smm m/ m/ ;;{## 	<b&7&7&D&DEEI$2244N11)-@@@'+y1E'F'F$#' )"*;*;K*H*HIN!$%9    $< &&~':;;; $&& 	   ,0+@$''ej"'(J(JKK_01#, ,(L.
 % @ @($????@ ,0+@ei02E, ,(L.
 )5RW%+' A A>@$W%8%8%:%:;; %!!0M    ""07D0 K
 &!,!<%%""1    :LLNN7,-- 	?%566I' ? ?!!"2I>>>> (1,,' 5 5$&G$;$;$=$=!#3355 J JD~--$>O2O2O--dN44HIII#4466 5 5Dd** z**4;;w+?+?@@ 5#5 '"?$ $  ..tX>>>/7t,>11-9 /=T.B !/ >$+$A!""*!, 8Fd7KN84*..t444#5.  +0 0 0 0  #N  "'    % % % % ' 7 7 9 9% % %    #$$))!%-/CDD 7!%+ 7 7G!((111 ' 8 8 : : 7 7,0066667  3"">222  ...~.... O!(8)
 
z~~2G<< A  
 %UK88
"5,#
 #
 #'.	1 7  M ,UY	 M $&& 

)3 4
 

 
 
 
#0
 
 
 	F	
 	
 	

 7GGII.5>H  < <"'1133g&&&/:::-8)* i$77777 < <{;;;;;< <r   c                ,    t          j                    | v S r   r  )r2   s    r   _is_grad_var_r+  }  s    !!X--r   c                n   | j         }|dk    rd S | j        }t          |j                  D ]}|                    |          j        }t          |                                          D ]K}|                    |          }|                    d          r|	                    d          |k    r|c c S Ld S )Nr   r  )
r:   r  r5   
num_blocksr   r(   r  r.   r   r  )r  sub_block_idr  block_idr  rD   r.   s          r   _find_parent_op_r0    s    =LqtG',--  ]]8,,1
J..0011 	 	Fv&&BK((%%k22lBB						 4r   c                v    g }	 t                     }g |F|                                }|                                }|D ]}||v r                    |           t	          | j                                                  D ]}	 j                            |	          }
|
                    d          r? j	        
                    |
                    d                    }t          |d||           d |
                                D             }d |
                                D             }d |
                                D             }d |
                                D             }|s|                    |	           	 |r( fd|D             }|s|                    |	           -|
                                d	k    rg }|
                                D ]C} j                            |                                          r|                    |           Dt!          |          dk    s
J d
            |
                    d|           t%                      }|
                                D ]} j                            |                                          s|t'          j                    k    rF j                            |                                           |                    |           ||vr| f|||         <   |
                                 |
                     j                   |
                     j                   |
                                D ]}||v rt5          |            t7          |          D ] }	 j                            |	|	dz              !dS )a  
    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   c                0    g | ]}t          |          |S rY   r+  rL  s     r   rb   z*_append_backward_vars_.<locals>.<listcomp>  s5     
 
 
c8J8J

 
 
r   c                0    g | ]}t          |          |S rY   r3  rL  s     r   rb   z*_append_backward_vars_.<locals>.<listcomp>  s5     
 
 
s9K9K

 
 
r   c                @    g | ]}|t          j                    k    |S rY   r   r0  rL  s     r   rb   z*_append_backward_vars_.<locals>.<listcomp>  s6     
 
 
d)++++ +++r   c                @    g | ]}|t          j                    k    |S rY   r6  rL  s     r   rb   z*_append_backward_vars_.<locals>.<listcomp>  s6     
 
 
d)++++ +++r   c                t    g | ]4}j                             |                                          s|v 2|5S rY   )r(   r   r   )ra   r%   r   parent_op_varss     r   rb   z*_append_backward_vars_.<locals>.<listcomp>  sR     ) ) )z33CJJLLAA) n,,  -,,r   r  z6After remove invalid variables, sum op have no inputs.r  r   )r0  r6   r+   r'   r5   r(   r  r.   r   r  r   r  _append_backward_vars_r)   r   r   r$   r   rF  r   r0  r%   rw  check_attrsr	  r
  r   r   
_remove_op)r   start_op_idxr  grad_info_mapops_to_remove	parent_op
input_argsoutput_argsin_argrD   r   r  grad_var_insgrad_var_outsrv   rw   existing_grad_var_ins
new_inputsr   r  r   r9  s   `                    @r   r:  r:    sF    M !''IN..00
0022  	. 	.F$$%%f---ej&8&8&:&:;; L8 L8*--''K(( 	M++G,B,B;,O,OPPI"9amLLL
 
"2244
 
 

 
"3355
 
 

 
..00
 
 


 
//11
 
 
  	  (((  	) ) ) ) )+) ) )% - !((000 <<>>U""J!(!8!8!:!: 5 5://0D0D0F0FGG 5%%m444z??Q&&&H '&& c:...55$5577 
	O 
	OM
,,]-A-A-C-CDD D$7$9$999JNN=//11222LL'''K//9F8NM+m455uz***EJ'''++-- 	8 	8Ch+C777	8 =)) 2 2
ffqj11112 2r   c                    t          |                                          dk    rd S t                      }|                                D ]} j                            |                                          s|t          j                    k    sk j                            |                                          } 	                    |||
                                           |                    |           t          j                                                            |
                                          r                     |
                                 fd|                                                                D              fd|                                                                D             |                                          }|j                            t          j                                        t          j        j        j                   |                    |j                   nщ j                                        }|                    |           |                    t          j                                        t          j        j        j                   |                                 |                     j                   |                     j                   |                    |           t          j                                                            |
                                          s+|                                D ]}||v rt=          |            d S d S )Nr   )r-   r(   r)   c                4    i | ]\  }}|fd |D             S )c                :    g | ]}                     |          S rY   _find_var_recursivera   r   r   s     r   rb   z7infershape_for_composite.<locals>.<dictcomp>.<listcomp>$  '    FFF#u0055FFFr   rY   ra   r-   r   r   s      r   r  z,infershape_for_composite.<locals>.<dictcomp>#  sD       D$ FFFFFFF  r   c                4    i | ]\  }}|fd |D             S )c                :    g | ]}                     |          S rY   rK  rM  s     r   rb   z7infershape_for_composite.<locals>.<dictcomp>.<listcomp>(  rN  r   rY   rO  s      r   r  z,infershape_for_composite.<locals>.<dictcomp>'  sD       D$ FFFFFFF  r   )r)   rv   rw   rx   )r$   r+   rF  r(   r   r   r   r0  r%   r~   r)   rw  r	   OpProtoHolderinstancehas_op_protor   rv   r   rw   get_attr_mapr   r   r   r   r   r   r;  r	  r
  r   )r   r  r  r   r(   r.   r   r   s   `       r   r  r  
  sI    <((**++q00 uuH%6688 ( (J(()=)=)?)?@@	( 3 5 555 :>>-"6"6"8"899D-dMMMLL'''
 ''))66|7H7H7J7JKK  (__""$$   "."5"5"7"7"="="?"?     "."6"6"8"8">">"@"@   ++--  
 
 	+;;==+2;	
 	
 	
 	rw'''' *&&((,'''+;;==+2;	
 	
 	
 	uz***EJ'''w'''"++--::<;L;L;N;NOO 
8  0022 	8 	8Ch+C777
8 
8	8 	8r   c                   t          j         |          }t          || j                                                  D ]}| j                            |          }|                                D ]"}||v r|                    |||                    #|                                D ]h}d|vr| j                            |	                    d                    r4||v r9t          j        |          }	|                    ||	           |	||<   i|                                D ])\  }
}|
|v r ||
         ||<   |                    |
           *d S )Nr'  r  )r  r5   r(   r  r.   r6   r   r+   r   r   r   r{   r   r   rx  )r   r=  r  target_grad_mapskip_rename_var_listvar_maprD   r   r-   r   gngs               r   _rename_grad_r\  O  so    i((Gej&8&8&:&:;; ) )*--''++-- 	; 	;Dw%%dGDM:::,,.. 	) 	)Dd""z""4;;w#7#788 )///&/55&&tX666 (	)   2)!nKOOOA r   c                   i }t          | t          j                  sJ | j        D ]}t          |t          j                  sJ t                      }t          |j                                                  D ]L}t          |t          j	                  sJ |j
        r'|                    t          |j                             M|||j        <   |S r   )r   r	   Programblocksr   rF  r   varsvaluesVariablero   rw  r   r-   r:   )r  r  r   block_no_grad_setr%   s        r   _get_stop_gradients_rd  i  s    Lgy011111 4 4%11111EE
))++,, 	F 	FCc9#566666  F!%%&:38&D&DEEE"3UYr   c                    t          j                    }|dk    r'|                     |          j        }|||<   |}|dk    '|S )Nr   )r   r   r   
parent_idx)r  current_block_idxson_parent_block_idx_dictparent_block_idxs       r   _get_son_parent_block_idx_dictrj  w  sY     + 7 9 9
q
 
 "==):;;F7G!"34, q
 
 
 %$r   c                   t                      }| t          | t           t          t          f          rt	          |           D ]\  }}t          |t
          j                  r|                    |j                   :t          |t                    r|                    |           et          dt          |           d          nt          dt          |                      |S )NzSThe type of no_grad_set's member must be paddle.base.Variable or str, but received rk   EThe type of no_grad_set should be set or list or tuple, but received )rF  r   r   r   rT   r	   rb  rw  r-   r   	TypeErrorr)   )rG  no_grad_set_namer9   no_grad_vars       r   _get_no_grad_set_namerp    s
   uukCu#566 	"+K"8"8  ;k9+=>> $(()9::::S11 $((5555# Cnrs~nn  C  C  C   kX\]hXiXikk   r   c                   t           j        j                                        }| t	          | t
          t          t          f          rjt          |           D ]Y\  }}t	          |t           j	        j
                  r|                    |           :t          dt          |           d          nt          dt          |                      |S )NzHThe type of no_grad_set's member must be paddle.pir.Value, but received rk   rl  )r  autogradbackward_utilsValueSetr   rF  r   r   rT   pirValuerw  rm  r)   )rG  no_grad_set_valuer9   no_grad_values       r   _get_no_grad_set_valuery    s    6??AAkCu#566 	$-k$:$:   =mVZ-=>> %))-8888#ycghucvcvyyy  	 kX\]hXiXikk   r   .r   r   parameter_listSequence[Tensor | str] | NonerG  set[Tensor | str] | Noner  ISequence[Callable[[Block, dict[str, Tensor | core.OpDesc]], None]] | Noner  Noner  DistributedContext | Nonereturnlist[tuple[Tensor, Tensor]]c                    d S r   rY   r   rz  rG  r  r  r  s         r   append_backwardr    s	     #&#r   list[Tensor]-tuple[list[tuple[Tensor, Tensor]], list[str]]c                    d S r   rY   r  s         r   r  r    s	     58Cr   c                |   t          j                    r&t          j        j                            | ||          S i }t          | dt           j        d           | j        t          |            | j        
                    t          j                                        t          t          j        j        j                  t          t          j        j        j                  z             |t          |dt$          t&          fd           | j        j        }|                    d          }|j        }	|                    |	          }
|	dk    }|s|xj        dz  c_        |t1                      }n!t3          t5          j        |                    }t7          |          }|d                             t%          t;          t<          |                               |r1|                    |
j                   }|!                    |	           n|}tE          ||	          }i }|D ]1}|                    |          j#        $                                ||<   2i }tK          |           }| j        ||&                                <   |j#        '                                (                    |           |D ]D}|                    |          }t1          t;          tR          ||                             }i }tU          || gg ||          }tW          ||| g|          }|                    |           ||                             t%          t;          t<          |                               d}|s |j        dk    rt=          | j,                  h}d}|Ht[          |t$                    r3t]          |          dk    r d	}t_          ||| g|||||          \  }}}})ta          ||| g||||||||
           Fi }|s||	         nd}tc          |||i g            te          ||||           |	|_        |3                                 |j4        D ]Z} |5                    | j#        &                                d          +|| j#        &                                         }!|!j6        | _6        [|t          |dt$          t&          t0          fd           g }"to          |          D ]\  }#}$t          |$d|# dt           j        tp          fd           t[          |$t           j                  r|"9                    |$j,                   at[          |$tp                    r|"9                    |$           n2|:                                ;                                }%d |%D             }"g }&t          j        <                                }'|"D ]}$|$|vr||$         }(|(d         })|)=                    |(d                   s!t}          d|(d          d|(d                    |:                                ?                    |$          }*|)?                    |(d                   }+|sP| j        =                    |(d                   r|&9                    |*|+f           |&9                    |*df           |&9                    |*|+f           |&D ]\  },}-|-|r|)j4        n|:                                j4        }.t          |.          D ]5} t[          | t           jA                  sJ |-j,        | jB        v r	| |-_         n6|-j        t}          d          |,j,        |-j,        g}/|-j        C                    |'          r-|/D                    |-j        E                    |'                     |-j        
                    |'|/           |r|&|fS |&S )a}  
    :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   )rf  FT)r{  r  r  r   rz  zbase.backward.append_backwardzparameter_list[r  c                *    g | ]}|j         	|j        S rY   )	trainabler-   )ra   params     r   rb   z#append_backward.<locals>.<listcomp>  s!    HHHUHejHHHr   zgrad block[z] did not have grad var zUnexpected branch)Fr	   in_pir_moder  rr  ir_backwardr  r   rb  r.   r   r   r   r   r   r   r   Forwardr   r   r   r   r  rg  r  rF  rp  r  rd  rE  mapr   r  rf  r  rj  r(   r  r   r   r   r   r   r  _find_no_grad_varsr-   r   r$   r  r  r\  r:  r   r   r1  _cuda_graph_attrrT   r   r'   r  all_parametersr  r   r   r%   r   r   r+   r   r*   r   )0r   rz  rG  r  r  r  r   r  
root_blockrg  r  is_in_control_flowr  target_grad_blockrh  block_fwd_op_num_dictr:   r  r   r2  r   rc  r  op_pathr{  is_recomputer  checkpoint_namesr  r  r>  
fwd_op_numr.   r  
parametersr9   r  paramsparams_and_gradsop_role_var_attr_name	grad_info
grad_block	param_varr   r;  rZ  r   attr_vals0                                                   r   r  r    s   Z  
*::.+
 
 	
 fi(*I   wtG'7799D+2:;;
d-49
:
:	;   5M+		
 	
 	
 j Gq!!J1MM"344M*a/  +%%*%%ee+DIk,B,BCC'00L O4$8+ F FGGHHH  '#11$/ 2 
 
 	001BCCCC ' >"! ! ( G G%,]]3%7%7%<%D%D%F%Fc""K $D))G26',,../$$&&00999. D D	i((#\)%<==
 
  D620,
 
 )7TF$5
 
 	  ---Y&&)+<==>>	
 	
 	
  $ " 	I,q00(<TY(G(G'H$ #;-- $K  1$$L 7$	 	 #"" "!%9)-%9     M "	/00  #Zb"EEE:{M   !2G  # : :##BG$7$7$9$94@@L)"'*=*=*?*?@F"("9B!5#+		
 	
 	
 
!.11 
	) 
	)HAu&!&&&#S)/	   %!344 )!!%*----E3'' )!!%(((
	) %%''6688HHfHHH
 ;NNPP ; ;%%!%(	q\
!!)A,// 	RilRRIaLRR   ((**..u55	>>)A,//! 	;z!!)A,// ; ''H(=>>>> ''D(9::::##Y$9::::  8 8190PJNNg6J6J6L6L6P 	 3-- 	 	Bb)"455555v,,, - 4<0111FAF#4==.// 	>OOADII&;<<===	,h7777  !111r   c                X    | g S t          | t                    rt          |           n| gS r   )r   r   r   rZ   s    r   _as_listr  '	  s-    y	 H--64777A36r   c                    |j         }| j        }|j        }|dk    r(||k    rdS |                    |          j        }|dk    (dS )Nr=   TF)r  r:   rf  r   )ancestor_blockr   progancestor_idxrf  s        r   _is_ancestor_blockr  -	  s\    =D!%L!J


%%4ZZ
++6
 


 5r   c                    |r|d         j         n| }d |D             }|j        | j        k    st          ||           r|S | j        }|j        | j        k    r&|j        dk    sJ |                     |j                  }t                      }t          |j                  D ]}t          |j	        
                                |          r|j	                                        D ]}|                    |           |j	                            |                                          sA|j	                            |                                          r|                    |           |}|}|j        | j        k    &|S )ad  
    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   c                    h | ]	}|j         
S rY   r  )ra   outs     r   rM  z$_get_output_names.<locals>.<setcomp>E	  s    888CH888r   r=   )r   r:   r  r  rf  rF  r   r   r   r(   r+   r6   rw  r   r   )		cur_blocktargetsr   current_output_namesr  parent_blockparent_block_output_namesr.   r-   s	            r   _get_output_namesr  :	  s    !(6GAJYE88888 yIM!!%7y%I%I!## D
)y}
$
$2%%%%zz%"233$'EE!59%% 	< 	<BRW55779MNN <G3355 < <D(,,T222 :..  <&+44T[[]]CC< 255d;;;8 )y}
$
$"  r   c                   t          | |          }g }t          t          t          |                              D ]\  }}|                    d          sb|j                                        D ]H}||vrB||j                                        vr'| j        |         j	        s|
                    |           I|j                                        D ]}	|	|vr|                    |	           t          |          S )zc
    Find the vars which is not used in the program, and
    those vars belong to no_grad_var.
    r  )r  r   r   rT   r   r(   r+   r6   r`  ro   r'   rw  rF  )
r   r  r  rG  r.  ro  r9   r.   r  r-   s
             r   r  r  a	  s   
 %UG44LK$y112233 ' '2{{;'' 	073355 0 0<//rw'>'>'@'@@@!Jw/= A  &&w///G++-- 	' 	'D;&&  &&&	' {r   Fc                t    d |D             }t           |          }|i }dgt           j                  z  |rt           j                  D ]\  }}	t	          |	j                                        |          rOt          j        |	j	                  s6|	j        
                                D ]}
|
|vr|                    |
           {d|<   t          t          t           j                                      D ] \  }}	|	                    d          rj|	                    d          } j                            |          }|t%          |	j
                  z  }t'          ||	t%                      ||          }|||<   t	          |	j        
                                |          rOt          j        |	j	                  s6|	j                                        D ]}
|
|vr|                    |
           d|<   |rt          t          t           j                                      D ]\  }}	|         du rzt	          |	j        
                                |          rSd|<   t          j        |	j	                  s5|	j                                        D ]}
|
|vr|                    |
            fdt)          t           j                            D             }|rL|D ]I}	|	j                                        D ]-}
|
|vr' j        |
         j        r|                    |
           .J|S )ar  
    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.
    c                    h | ]	}|j         
S rY   r  )ra   r  s     r   rM  z!_find_op_path_.<locals>.<setcomp>	  s    ...38...r   NTFr  c                :    g | ]}|         
j         |         S rY   )r   )ra   r9   r   relevant_op_flagss     r   rb   z"_find_op_path_.<locals>.<listcomp>	  s:       7H7K	!  r   )r  r$   r   rT   r   r(   r6   r   has_empty_grad_op_makerr)   r+   rw  r   r   r   r  r  r   rF  r  r5   r`  ro   )r   r  rv   rG  r  r  r,   r.  r9   r.   r-   r.  r  r  r$  r  r  s   `               @r   r  r  x	  s   & /.v...K$UG44LUY/  	-uy)) 	- 	-EAr''));  -227;;- G4466 . .D;..#---. (-!!$$$y334455 ) )2;;{## 	8,,[99L++L99I%1C8K4L4L%L"02suul4J N *8L&G$$&&
 
 	).rw77	) //11 + +{** $$T***+ $)a   3 d9UY#7#78899 	3 	3EAr #u,,((**L2 2, (,!!$3BG<< 3 " 7 7 9 9 3 3{22(,,T222    #C	NN33  G  * 	* 	*B//11 * *{**uz$/?/M*OOD)))* Nr   c                p   t          |           } t          |          }t          |          }| d         j        }|j        }|xj        dz  c_        |j        }|sdgt          |           z  }t          |           t          |          k    rt          d          |t                      }n!t          t          j	        |                    }t          |          }|d                             t          t          t          |                               |j                                        }t                      }	i }
i }g }t                      }t#          |          D ]l\  }}| |         }t          |j                  }|t'          dd|j        gid|gid|j        d	          }|j                                                            |           |j                                         |	                    |           |                    |           n|j        j        |k    s|j        j        |k    rt          d
          |j        |j        k    rt          d|j         d|j                   |j        |
t          |j                  <   |	                    |j                   |j        ||<   |                    |           nt7          j                    rt7          j        |
           |j        dk    rd}	i }|D ]!}|j        j        |k    rt          d          "t          t          t<          |d                             }i }t?          || |||          }| }t7          j                    rtA          |j!                  D ]R}|j"        dk    rg }|j"        t6          j#        $                                v rmt6          j#        |j"                 }tK          |t                    r|}n ||          }|D ]0}|                    |&                    |          d                    1|j        '                                D ]}|r||v r	t          |          }||vrzt'          dd|gid|gid| d         j        d	          }|j                                                            |           |                    |(                    |                      |j                                         tS          ||||          }|                    |           |d                             t          t          t          |                               i }i } tU          ||| ||||	||	  	         tW          ||||
|           tY          ||||            |                                 | S )z5
    Calculate gradient and return grad_info_map
    r   r   Nz:Should have the same number of target_gradients as targetsrO  r  rr   r   rP  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   rF  rp  r  rd  rE  r   r  r   r(   r  rT   r-   r   rn   r   r   r   rw  r'   r   r   rR  _set_prim_target_grad_namer   r  r   r   r)   ops_contain_noner  r   r/  r+   r%   r  r  r\  r:  )!r  rv   target_gradientsrG  r   r  r2  r  r  r{  rW  r  rX  grad_name_setr9   gradtarget	grad_namer   rz   rc  r  r  tmp_targetsr.   keep_var_listra  	none_varsnone_var_namer2   r   r  r>  s!                                    r   calc_gradient_helperr  	  s    wGfF 011AJE=D!#	I 1 6CLL0
7||s+,,,,H
 
 	
 ee+DIk,B,BCC'--LO4$8+ F FGGHHH##%%J55ONEEM-.. % %4(55	<&v{m$$ #\ 	 G J  "",,W555M((*** $$Y/// ''	2222|9,,0D0L0L !HIII|tz)) ]FK]]RVR[]]   BFO0==> $$TY///(,	N9%)$$$$ "" 9'888 !Q&&# M M;$&&KLLL 'C 3\!_EEFFLw 1< G K "" '59%% 	 	Bw/)) Mw$/446666.rw7fd++ + &II &r

I%. F FM!((=)A)A!)DEEEEG4466 < <  h-&?&? 4X > > 55.'xj)0"#gaj.>??	 G J((**44W===&&uyy':':;;;$$&&& %w%6 K [)))O4$8:K L LMMNNNKM1!%
 
 
 
 z;9M   5*k=IIIr   c                    t          |          }g }|D ]f}|j        | vr|                    d            !| |j                 }|d         }|                    |d                   }|                    |           g|S )Nr   r   )r  r-   r'   r%   )r>  rv   	grad_vars	input_varr  r  r   s          r   _get_grad_varsr  k
  s    fFI ' '	>..T""""%in5I"1J!~~il33HX&&&&r   c                    t          j                    r't          j        j                            | |||          S t          | |||          }t          ||          }t          |          dk    r|d         S |S )aR  
    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  rG  r   r   )	r	   r  r  rr  r  calc_gradientr  r  r$   )r  rv   r  rG  r>  r  s         r   r  r  y
  s    ,  
*88V-{
 
 	
 ))	  M }f55I
9~~|r   r  Tensor | Sequence[Tensor]rv   r   Tensor | Sequence[Tensor] | Nonec                   t          j                    r;t          | dt          j        j        t          t          fd           t          |dt          j        j        t          t          fd           t          |dt          j        j        t          t          t          d          fd           t          |dt          j        j        t          t          t          t          d          fd           t          |           } t          |          }t          |          }ddlm} dd	lm} | |            }n ||          } || |||          }|S t          | dt           j        t          t          fd
           t          |dt           j        t          t          fd
           t          |dt           j        t          t          t          d          fd
           t          | |||          }t          |          S )af  

    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.gradrv   r  NrG  r   )rt  )r  zpaddle.static.gradients)r	   r  r   r  ru  rv  r   r   r)   rF  r  paddle.autograd.backward_utilsrt  paddle.autograd.ir_backwardr  rb  )r  rv   r  rG  rt  pir_calc_gradient
input_gradoutss           r   	gradientsr  
  s'   Z  1ZtU+.		
 	
 	
 	ZtU+.		
 	
 	
 	ZtUDJJ7.		
 	
 	
 	
 T

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

 		T5)!	   		T5)!	   		T5$t**5!	   &*:KHHDD>>r   c                   t          | dt          j        j        d           t          |dt          j        j        d           ||t                      }t                      }| j        D ]`}|j        D ]V}|j	        D ]"}|
                    |j        |                    #|j        D ]"}|
                    |j        |                    #Wa|"t          |                    |                    }|"t          |                    |                    }t          ||          }	t!          | d          5  d t#          ||	          D             }
|                    |
          }ddd           n# 1 swxY w Y   ||
fS )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	optimizerNc                h    g | ]/\  }}t          |t          j        j        j                  r|+||f0S r   )r   r  baser	   	Parameter)ra   pramr  s      r   rb   z,gradients_with_optimizer.<locals>.<listcomp>f  sN     
 
 
d$ 5 ?@@
   4L !  r   )r   r  r  r^  r  	OptimizerrF  r_  r   r6   rw  r`  r+   r   
differencer  r   zipapply_gradients)r  r  rv   rw   in_setout_setr   r.   r-   grads
pram_gradsoptimize_opss               r   gradients_with_optimizerr    s   X 0	   "0	   ~%%^ 	2 	2Ei 2 2. 1 1DJJuz$/0000/ 2 2DKK
4 0111122
 >&++G4455F?7--f5566Ggv&&E	w	%	% = =
 
!&%00
 
 

 !00<<= = = = = = = = = = = = = = = ##s   30E//E36E3r   )NN)rq   )rq   N)NNN)NNNNNN).....)r   r   rz  r{  rG  r|  r  r}  r  r~  r  r  r  r  )r   r   rz  r{  rG  r|  r  r}  r  r  r  r  r  r  )NNNNN)NF)
r  r  rv   r  r  r  rG  r|  r  r  )S
__future__r   r   r  r  r  r  r   collections.abcr   typingr   r   paddle.baser  rq   r   r	   r
   r   data_feederr   r   r  r   r   r   paddle.base.frameworkr   4paddle.distributed.auto_parallel.static.dist_contextr   __all__
get_loggerr   INFOrJ   r   r   r   r   r   r   r   r   r   r   r   r   r   r  r  r?  rV  r  r  r  r  r  r  r  r  r  r+  r0  r:  r  r\  rd  rj  rp  ry  r  static_onlyr  r  r  r  r  r  r  r  r  r  rY   r   r   <module>r     s   # " " " " "       				 				  $ $ $ $ $ $ * * * * * * * *     6 6 6 6 6 6 6 6 6 6 6 6 # # # # # # $ $ $ $ $ $             ((((((++++++      
*
gl H  
} } } } } } } }@	 	 	 DH   D   .
? 
? 
?? ? ? ?0  B  66 6 6$	 	 		 	 	B B B") ) ) @B( ( ( (0 #( #( #( #(R  U U U Ur 15"C C C CLz! z! z!z   \ \ \ \H	  1 1 1 1h  ' ' '  6  $ < < < <D
. . .
  ,o2 o2 o2dB8 B8 B8J  4  % % %  (  $ 
 58,/ 	03
& 
& 
& 
& 

& 
 58,/ 	 #03
8 
8 
8 
8 

8  `  `  `  ` F7 7 7
 
 
$  $  $ N  0 FKP P P Ph 9=] ] ] ]@  * * * *Z  :>,0	r r r r rj R$ R$ R$ R$ R$ R$r   