o
    "jb                     @   s   d dl Z d dlZd dlZd dlm  mZ d dlmZ d dl	m
Z
mZ d dlmZ d dlmZmZ d dlmZ d dlmZmZ d dlmZ d d	lmZ d d
lmZmZmZ ddlmZmZ g Z G dd dZ!G dd dZ"G dd dZ#G dd dZ$G dd dZ%G dd dZ&dddZ'dS )    N)_legacy_C_ops)_in_amp_guard_in_pure_fp16_guard)grad)core	framework)BuildStrategy)
check_typeconvert_dtype)switch_to_static_graph)LRScheduler)OpResultfake_op_resultis_fake_op_result   )RETURN_NO_VALUE_MAGIC_NUMbackend_guardc                   @   s    e Zd ZdZdd Zdd ZdS )cached_propertyzB
    Descriptor to implement lazy initialization of property.
    c                 C   
   || _ d S N)function)selfr    r   i/var/www/html/Deteccion_Ine/venv/lib/python3.10/site-packages/paddle/jit/dy2static/pir_partial_program.py__init__)      
zcached_property.__init__c                 C   s   |  |}t|| j j| |S r   )r   setattr__name__)r   instanceclsvalr   r   r   __get__,   s   
zcached_property.__get__N)r   
__module____qualname____doc__r   r!   r   r   r   r   r   $   s    r   c                   @   s<   e Zd ZdZdd Zedd Zdd Zdd	 Zd
d Z	dS )NestSequencea  
    A wrapper class that easily to flatten and restore the nest structure of
    given sequence. It also remove the duplicate variables in the sequence.
    For example:
    >>> t = [v1, v2, v1]
    >>> m = tolist(t)
    [v1, v2]
    >>> m.restore([t1, t2])
    [t1, t2, t1]
    c                 C   s   || _ |  \| _| _d S r   )
_raw_input_tolist_var_map	_var_list)r   	raw_inputr   r   r   r   >   s   zNestSequence.__init__c                 C   s   | j S r   r)   r   r   r   r   var_listB   s   zNestSequence.var_listc                 C   sP   i }g }t j| jD ]}t|tsq||v rqt|||< || q||fS )zx
        Flattens the nested sequences into single list and remove duplicate variables + non-variable elements.
        )paddleutilsflattenr&   
isinstancer   lenappend)r   Zvariable_mapZvariable_listvaluer   r   r   r'   F   s   
zNestSequence._tolistc              	      sH   t  jt ksJ  fdd}tj jtt|tj jS )z?
        Restores the nested sequence from value list.
        c                    s   t | tr j|   S | S r   )r1   r   r(   xr   
value_listr   r   to_value\   s   
z&NestSequence.restore.<locals>.to_value)	r2   r)   r.   r/   Zpack_sequence_asr&   listmapr0   )r   r8   r9   r   r7   r   restoreV   s   zNestSequence.restorec                 C   s
   | j | S r   r+   )r   itemr   r   r   __getitem__f   r   zNestSequence.__getitem__N)
r   r"   r#   r$   r   propertyr-   r'   r<   r>   r   r   r   r   r%   2   s    
r%   c                   @   s   e Zd ZdZedd Zedd Zedd Zdd	 Z	ed
d Z
edd Zedd Zedd Zedd Zedd Z			d)ddZdd Zdd Zdd Zedd  Zed!d" Zed#d$ Zed%d& Zed'd( ZdS )*RunablePrograma  a pir program ready for run_program_op to run. constructed by 3 parts:
    - pir program (pir::Program)
    - in_out_values
        - input_x values ([string | pir::OpResult])
        - input_param values ([string | pir::OpResult])
        - output values ([string | pir::OpResult])
    - forward_backward_ranges
        - forward_range (tuple(Int, Int)) | None
        - backward_range (tuple(Int, Int)) | None
    c                 C   s   |  | jS r   ) _get_value_name_map_from_programprogramr,   r   r   r   get_value_name_mapv      z!RunableProgram.get_value_name_mapc                 C   s   i }d|t  < | jD ]7}| dkr| d ||d< | dkr2| d ||d < | dkrC| d ||d< q|S )NZFakeVar
pd_op.datanamer   builtin.set_parameterZparameter_namebuiltin.parameter)r   global_blockopsrF   attrsresultoperandsource)r   rB   retopr   r   r   rA   z   s   
z/RunableProgram._get_value_name_map_from_programc                 C   s   dd | j  D S )Nc                 S      i | ]\}}||qS r   r   .0kvr   r   r   
<dictcomp>       z5RunableProgram.get_name_value_map.<locals>.<dictcomp>)rC   itemsr,   r   r   r   get_name_value_map      z!RunableProgram.get_name_value_mapc                    s4   t |dkrg S t|d tr|S  fdd|D S )Nr   c                       g | ]} j | qS r   )rC   rS   rU   r,   r   r   
<listcomp>   rW   z/RunableProgram.convert_name.<locals>.<listcomp>)r2   r1   str)r   valuesr   r,   r   convert_name   s
   zRunableProgram.convert_namec                        fdd j D S )Nc                    r[   r   rY   r\   r,   r   r   r]      rW   z+RunableProgram.x_values.<locals>.<listcomp>)x_namesr,   r   r,   r   x_values   rZ   zRunableProgram.x_valuesc                    ra   )Nc                    r[   r   rb   r\   r,   r   r   r]      rW   z/RunableProgram.param_values.<locals>.<listcomp>)param_namesr,   r   r,   r   param_values   rZ   zRunableProgram.param_valuesc                    ra   )Nc                    r[   r   rb   r\   r,   r   r   r]      rW   z-RunableProgram.out_values.<locals>.<listcomp>)	out_namesr,   r   r,   r   
out_values   rZ   zRunableProgram.out_valuesc                    ra   )Nc                    r[   r   rb   r\   r,   r   r   r]      rW   z0RunableProgram.x_grad_values.<locals>.<listcomp>)x_grad_namesr,   r   r,   r   x_grad_values   rZ   zRunableProgram.x_grad_valuesc                    ra   )Nc                    r[   r   rb   r\   r,   r   r   r]      rW   z4RunableProgram.param_grad_values.<locals>.<listcomp>)p_grad_namesr,   r   r,   r   param_grad_values   rZ   z RunableProgram.param_grad_valuesc                    ra   )Nc                    r[   r   rb   r\   r,   r   r   r]      rW   z2RunableProgram.out_grad_values.<locals>.<listcomp>)o_grad_namesr,   r   r,   r   out_grad_values   rZ   zRunableProgram.out_grad_valuesNc                 C   s  t |ts	J dt|dksJ dt |d tsJ d|| _| |d | _| |d | _| |d | _|| _	|| _
d| _d| _| j	d u rUdt| j jf| _	| j
d u rkt| j jt| j jf| _
|d u rtg g g f}| |d | _| |d | _| |d | _d S )Nz)in_out_values must be tuple with len == 3   r   r      F)r1   tupler2   r:   rB   r`   rc   re   rg   forward_rangebackward_rangehas_splitedfinish_passrI   rJ   ri   rk   rm   )r   rB   in_out_valuesZgrad_in_out_valuesrr   rs   r   r   r   r      s@   


zRunableProgram.__init__c                 C   s6   t jjj| j\}}t|| j| j| j	fd | j
| jS r   )r.   base	libpaddlepirclone_programrB   r@   rc   re   rg   rr   rs   )r   Zcloned_program_r   r   r   clone   s   
zRunableProgram.clonec                 C   sf   | j du s	J dd| _ tjjj| j| j| j| j	| j
| j| jt| jt| j	\\}}}||g|fS )NFzJPlease ensure only split once! don't call split_forward_backward manually.T)rt   r.   rw   rx   ry   Zsplit_programrB   rd   rf   rh   rj   rl   rn   r:   rr   rs   )r   Zfwd_progZbwd_progZ	prog_attrr   r   r   split_forward_backward   s(   
z%RunableProgram.split_forward_backwardc                 C   s.   | j }| j}| j}|| j| j|\| _| _dS )a  
        Main entries for pass function, without considering any input/output and forward segmentation.
        pass_fn' signature is:

        1. This function will change forward and backward program.
        2. call self.program_attr means start to run.
        so we can't call this function after program_attr is called.

        def pass_fn(forward_program, backward_program):
            return forward_program, backward_program
        N)program_name_attrforward_programbackward_program)r   pass_fnr~   Z
origin_fwdZ
origin_bwdr   r   r   apply_pir_program_pass   s   
z%RunableProgram.apply_pir_program_passc                 C   s   |   S r   )r}   r,   r   r   r   _forward_backward_program  s   z(RunableProgram._forward_backward_programc                    s   | j du s	J dd| _ dd | | j D dd | | j D  i }| j D ];\}}|dr@fdd	|D }n$|d
rO fdd	|D }n|dkr]fdd	|D }ntd| |||< q-|S )NFzgprogram_attr() is called by PartialProgramLayer, don't call it matually, use program_name_attr instead.Tc                 S   rQ   r   r   rR   r   r   r   rV         z/RunableProgram.program_attr.<locals>.<dictcomp>c                 S   rQ   r   r   rR   r   r   r   rV     r   fc                       g | ]} | qS r   r   rS   nfwd_mapr   r   r]         z/RunableProgram.program_attr.<locals>.<listcomp>bc                    r   r   r   r   bwd_mapr   r   r]   !  r   no_need_buffersc                    r   r   r   r   r   r   r   r]   #  r   Unknown program attr: )ru   rA   r   rX   r   r~   
startswith
ValueError)r   Zvalue_program_attrrT   nsr_   r   r   r   r   program_attr	  s6   


zRunableProgram.program_attrc                    s   | j d }| | j| | j i }| D ];\}}|dr*fdd|D }n$|dr9 fdd|D }n|dkrGfdd|D }ntd	| |||< q|S )
Nr   r   c                    r   r   r   r\   r   r   r   r]   1  r   z4RunableProgram.program_name_attr.<locals>.<listcomp>r   c                    r   r   r   r\   r   r   r   r]   3  r   r   c                    r   r   r   r\   r   r   r   r]   5  r   r   )r   rA   r   r   rX   r   r   )r   Zorigin_attrZ_program_attrrT   vsnamesr   r   r   r~   )  s   



z RunableProgram.program_name_attrc                 C   s   | j d d S )Nr   r   r,   r   r   r   r   ;     zRunableProgram.forward_programc                 C   s   | j d d S )Nr   r   r   r,   r   r   r   r   ?  r   zRunableProgram.backward_programNNN)r   r"   r#   r$   r   rC   classmethodrA   rY   r`   rd   rf   rh   rj   rl   rn   r   r|   r}   r   r   r   r~   r   r   r   r   r   r   r@   j   sL    









&



r@   c                   @   s4   e Zd ZdZdZdZdZedd Zedd Z	d	S )
PirPassContextz
    PirPassContext is a class that only has staticmethod currently.
    It will create a new RunableProgram after calling apply method.
    rE   rH   rG   c                 C   sT   |j s|S t stdtjjj|j\}}tjjj	| | 
|}t||S )NzcPlease install PaddlePaddle compiled with CINN while setting build_strategy.build_cinn_pass = True.)build_cinn_passr.   Zis_compiled_with_cinnRuntimeErrorrw   rx   ry   rz   r   apply_pir_pass_prepare_attrr@   )r   Zrunable_programbuild_strategyZfwd_programr{   rv   r   r   r   applyN  s   


zPirPassContext.applyc                 C   s   g g g }}}|  jD ]1}| }|| jkr!||d q|| jkr/||d q|| jkr>||d	  q|||fS )a   
        After applying Pass, we need to update the Input/Parameter/Output Value
        that refer to the new program.

        NOTE: We assume that Inputs come from INPUT_OP, Params come from
              PARM_OP and Output come from OUTPUT_OP.
        r   )
rI   rJ   rF   INPUT_OP_NAMEr3   rL   PARM_OP_NAMEOUTPUT_OP_NAMErM   rN   )r   rB   inputsparamsoutputsrP   Zop_namer   r   r   r   `  s   	



zPirPassContext._prepare_attrN)
r   r"   r#   r$   r   r   r   r   r   r   r   r   r   r   r   D  s    
r   c                   @   s$   e Zd Zdd Zdd Zdd ZdS )PartialProgramLayerHookc                 C      d S r   r   )r   r   src_varsr   r   r   before_append_backwardv     z.PartialProgramLayerHook.before_append_backwardc                 C   r   r   r   )r   Zwhole_programr   Zbackward_start_idxr   r   r   after_append_backwardy  s   z-PartialProgramLayerHook.after_append_backwardc                 C   r   r   r   )r   infer_programr   r   r   after_infer~  r   z#PartialProgramLayerHook.after_inferN)r   r"   r#   r   r   r   r   r   r   r   r   u  s    r   c                       sN  e Zd ZdZ	dD fdd	Zdd Zdd Zed	d
 Zdd Z	dd Z
dEddZedFddZedd Zedd Zedd Zedd Zedd Zedd Zd d! Zd"d# Zed$efd%d&Zd'd( Zd)d* Zd+d, Zd-d. ZdEd/d0Zd1d2 Zd3d4 Zd5d6 Z ed7d8 Z!d9d: Z"d;d< Z#d=efd>d?Z$d@dA Z%dBdC Z&  Z'S )GPartialProgramLayera^  
    PartialProgramLayer wraps all the ops from layers decorated by `@to_static`
    and execute them as a static subgraph.

    .. note::
        **1. This is a very low level API. Users should not use this API
             directly. Please use `partial_program_from(concrete_program)`
             to create it.
        **2. TensorArray is not currently supported in the output.

    Args:
        main_program(Program): The main program that contains ops need to be executed.
        inputs(list[Variable]): The input list of the decorated function by `@to_static`.
        outputs(list[Variable]): The output list of the decorated function by `@to_static`.
        parameters(list[Tensor]|None): All trainable parameters included in the program. Default None.

    Returns:
        Layer: A Layer object that run all ops internally in static graph mode.
    Nc           
         s  t    t|| _t|| _|d ur|ng g f\| _| _|dt | _	t
| j	ts-J | || _|  | _d| _d| _d| _i | _d\}}}t }	|	rX|	 \}}|	j}|d url|dv rltjjjj|||d| _i | _d | _|dd | _i | _ d | _!d S )	Nr    r   Tr   )Zfloat16Zbfloat16)custom_white_listcustom_black_listdtypebackend)"superr   r%   _inputs_outputs_params_param_valuesgetr   _build_strategyr1   _verify_program_origin_main_program_create_cuda_graph_vec_cuda_graph_vec_cuda_graph_capture_mode_cuda_graph_pool_idtrainingZ_program_extra_infor   Z_dygraph_tracerZ_get_amp_op_listZ
_amp_dtyper.   ZstaticampZ
fp16_listsZAutoMixedPrecisionListsZ	_amp_list_scope_cache_hooker_backendZ_grad_var_namesZ_debug_name)
r   main_programr   r   
parameterskwargsZ	amp_dtyper   r   Ztracer	__class__r   r   r     s<   






	
zPartialProgramLayer.__init__c                 C   sj   |  |}|  }|  }tj| || | j| || j| jdd| j	g|R   | 
|}| |S )zQ
        Execute static graph by Interpreter and Return dynamic Tensors.
        T
program_iduse_scope_cache)_prepare_inputs_prepare_outputs_prepare_attributesr   pir_run_program_valid_varsr   _create_scope_vecr   r   _restore_out_remove_no_value)r   r   Zin_varsout_varsrK   Zrestored_nest_outr   r   r   __call__  s    




zPartialProgramLayer.__call__c                 C   s
   |  |S )zz
        In sot, inputs and outputs of partial program only contain tensors, so we can skip some step to speed up
        )
r   r   r   r   r   r   r   r   r   r   )r   r   r   rK   r   r   r   sot_call  s   
zPartialProgramLayer.sot_callc                 C   sT   t | jj}t | jj}| j}tjjj	| j
|t| j
 jd t| j
|||fS )NZoutput_)r:   r   r-   r   r   r.   rw   rx   ry   append_set_parametersr   r2   rI   rJ   r@   )r   r   r   r   r   r   r   origin_runable_program  s   
z*PartialProgramLayer.origin_runable_programc                 C   sr   | j }t|dr5t|dr7|j}|j}t|tsJ d| j j}| }t|t	|j
}|| dS dS dS )z4Update lr_var value with calculated by lr_scheduler.lr_schedulerlr_varzmust be LRSchedulerN)r   hasattrr   r   r1   r   nparrayZastyper
   r   	set_value)r   r   r   r   Zlr_valuedatar   r   r   _sync_lr_value_with_scheduler  s   z1PartialProgramLayer._sync_lr_value_with_schedulerc                 C   r   r   )r   )r   Zhookerr   r   r   
set_hooker  r   zPartialProgramLayer.set_hookerFc                 C   sX   |st  S || jvrg | j|< | j| }|D ]	}|jr |  S qt  }|| |S r   )r   ZScoper   Z_can_reusedr3   )r   r   r   Zcached_scopesscoper   r   r   
_get_scope
  s   



zPartialProgramLayer._get_scopec                    sn   |r j  } jr j| t| j}|S  j  } |}  j	|  fdd}|
| |S )Nc                    s`   t jjj| \}} jjrt jjj| t jjj|\}} jjr,t jjj| ||fS r   )r.   rw   rx   ry   rz   r   r   r   )r   r   Z	name_attrZfwdr{   Zbwdr,   r   r   r   *  s   

z4PartialProgramLayer._create_program.<locals>.pass_fn)r   r|   r   r   r   r   r   _append_backward_desc_set_grad_typer   r   )r   is_infer_moder   train_programr   r   r,   r   _create_program  s   



z#PartialProgramLayer._create_programc                 C   s"   t j| j| }t|| j |S r   )r.   r/   _hash_with_idr   r   Z#_set_cached_executor_build_strategyr   )r   r   r   r   r   _train_program_id>  s
   z%PartialProgramLayer._train_program_idc                 C   s   t j| j| S r   )r.   r/   r   r   r,   r   r   r   _infer_program_idF  s   z%PartialProgramLayer._infer_program_idc                 C   s   | j r| jS | jS )z7
        Return current train or eval program.
        )r   r   r   r,   r   r   r   rB   J  s   zPartialProgramLayer.programc                 C   s&   t  st r
td| jr| jS | jS )z?
        Return current train or eval program hash id.
        not implement error.)r   r   NotImplementedErrorr   r   r   r,   r   r   r   r   T  s
   zPartialProgramLayer.program_idc                 C   s   t  st r
td|  S )Nr   r   r   r   r   r,   r   r   r   r   `  s   z!PartialProgramLayer.train_programc                 C   s    t  st r
td| jddS )Nr   T)r   r   r,   r   r   r   r   f  s   z!PartialProgramLayer.infer_programc                 C   s   |  | | | |S )z
        Verify that the program parameter is initialized, prune some unused params,
        and remove redundant op callstack.
        )_check_params_all_inited_prune_unused_paramsr   r   r   r   r   r   l  s   

z#PartialProgramLayer._verify_programc                    sB    fdd}fdd}t t|| jj}|D ]}||| qdS )a  
        Why we need add gradient aggregation operation ?
        In some cases, if non leaf nodes are used as output, gradient overwriting will occur, such as
        def forward(self, in):
            x = 2 * in  # <---- x is a non-leaf node in program.
            y = x + 3
            return x, y

        loss = forward(in)[0].sum()
        loss.backward()  # <----- x@grad will be overwrited by elementwise_add_grad Op
        c                    sf   | j tjjjtjjjfvrdS | jtjtj	fvrdS  
 jD ]}|jD ]}|| jkr/  dS q$qdS )zM
            if exist a op whose inputs is var, then return True
            FT)typer   VarDescVarType
LOD_TENSORSELECTED_ROWSr   r.   Zfloat32Zfloat64rI   rJ   Zinput_arg_namesrF   )varrP   Zin_arg)r   r   r   _need_aggregation  s   

zKPartialProgramLayer.prepare_gradient_aggregation.<locals>._need_aggregationc                    s   d}|j  |j| d }tt fddt|  j}t|dkr%d S |  j||j	|j
|jd |D ]\}}| | | | q5|  j|d d d d	d
 |gid id d S )Nz
@dy2staticz@GRADc                    s(   | d  kot fdd| d jD S )Nr   c                 3   s    | ]}| kV  qd S r   r   )rS   Zout_argvar_grad_namer   r   	<genexpr>  s
    
z~PartialProgramLayer.prepare_gradient_aggregation.<locals>._insert_aggregation_ops_for_var.<locals>.<lambda>.<locals>.<genexpr>r   )anyZoutput_arg_namesr5   )	start_idxr   r   r   <lambda>  s    zkPartialProgramLayer.prepare_gradient_aggregation.<locals>._insert_aggregation_ops_for_var.<locals>.<lambda>r   )rF   r   r   shaper   sumXZOut)r   r   r   )Z	grad_namerF   r:   filter	enumeraterI   rJ   r2   Z
create_varr   r   r  Z_rename_inputZ_rename_outputZ
_insert_op)target_programr   suffixZnew_grad_nameZ
finded_opsidxrP   )r  r   r   _insert_aggregation_ops_for_var  s6   
zYPartialProgramLayer.prepare_gradient_aggregation.<locals>._insert_aggregation_ops_for_varN)r:   r  r   r-   )r   r  r   r
  r   r  Zto_processed_varsZ_varr   )r   r  r   prepare_gradient_aggregationx  s   (z0PartialProgramLayer.prepare_gradient_aggregationtrain_runnable_programc              	   C   s\  |j }|j}| jr| j||\}}|j}|j}tt||}t	|
 j}d gt	| }t| j t|dtttfd t|d d g }	|D ]}
|
jdu rW|	t  qItj|
d|
jd}|	| qItjjj||	t	|
 jd t	|
 j| }t	ttdd |d	krt|ttd
d |ttdd |	d}W d    n1 sw   Y  | jr| j|||\}}}W d    n1 sw   Y  dd }t	|}tt ||d	| }tt |||d  }tt ||	}ttdd |}ttdd || }t	|
 j}tjjj|||d || }t!||||f|||fd	|f||fS )Ntargetszpaddle.static.gradientsTg      ?)Z
fill_valuer   Zgrad_input_c                 S   
   | j du S NFstop_gradientr5   r   r   r   r       
 z;PartialProgramLayer._append_backward_desc.<locals>.<lambda>r   c                 S   r  r  r  r5   r   r   r   r    r  c                 S   
   t |  S r   r   r5   r   r   r   r    r  )r   r   Zgrad_outputsc                 S   s   t | tr| S t S r   )r1   r   r   r5   r   r   r   r    r   c                 S   r  r   r  r5   r   r   r   r  !  r  c                 S   r  r   r  r5   r   r   r   r  %  r  Zgrad_output_)"rB   rh   r   r   rd   rf   r:   	itertoolschainr2   rI   rJ   r   r   r	   r   rq   	ir_staticZprogram_guardr  r3   r   r.   Z	full_liker   rw   rx   ry   r   r  r   r   r;   r@   )r   r  rB   r  r   r   Zcombined_inputsZforward_end_idxZgrad_info_mapZforward_outputs_gradsZout_op_resultr4   Zop_between_forward_and_backwardZmapping_op_resultZinputs_sizeZx_grad_valueZp_grad_valueZo_grad_valueZinput_grads_to_appendZoutput_grads_to_appendZbackward_end_op_indexZbackward_start_op_indexr   r   r   r     s   

-B
z)PartialProgramLayer._append_backward_descc                 C   sd   g }g }|  }t| j| jD ]\}}| s"|| || q||  q|| _|| _dS )a'  
        Prune the parameters not used anywhere in the program.
        The `@to_static` may only decorated a sub function which
        contains some unused parameters created in `__init__`.
        So prune these parameters to avoid unnecessary operations in
        `run_program_op`.
        N)rI   zipr   r   Z	use_emptyr3   Z	remove_opZget_defining_op)r   rB   Zrequired_paramsZrequired_param_valuesblockparamZparam_valuer   r   r   r   <  s   

z(PartialProgramLayer._prune_unused_paramsc                 C   st   d| j j d| j j d| j d| jg}| j j D ]\}}|| || q| j	r8|
d| j	d| jf |S )NZforward_global_blockZbackward_global_blockZis_testr   Zcuda_graph_capture_modeZcuda_graph_pool_id)rB   r   rI   r   r   r   r   rX   r3   r   extendr   )r   rK   keyr    r   r   r   r   Q  s*   



z'PartialProgramLayer._prepare_attributesc                 C   s   t |ttfs	J tj|}g }t }t|D ]:\}}t |t	j
r0d}tjj|d|dd}nt |tjjrM|jrJ|j|sJ||d}d|_n|}nq|| q|S )z1
        Prepare inputs, outputs, attrs.
        NFT)r4   ZpersistableplaceZ	zero_copy)r1   rq   r:   r.   r/   r0   r   Z_current_expected_placer	  r   Zndarrayr   eagerTensorr  r   Z_equalsZ_copy_tor3   )r   r   Zflatten_inputsZ
input_varsZexpected_placeir4   r   r   r   r   r   k  s.   z#PartialProgramLayer._prepare_inputsc                 C   s   t jj| jjS r   )r.   r   r   Z$create_empty_tensors_with_op_resultsr   r-   r,   r   r   r   r     s   z$PartialProgramLayer._prepare_outputsc                 C   s   | j ||d}|gS )Nr   )r   )r   r   r   Zinner_scoper   r   r   r     s   z%PartialProgramLayer._create_scope_vecc                 C   s*   t jt jjjg dt jjjd}d|_|S )NZ
cuda_graphT)r   r!  r"  r   r   ZFP32ZRAWr  r   r   r   r   r   r     s   z*PartialProgramLayer._create_cuda_graph_vecc                 C   s.   dd }t | jj|D ]	\}}||| qd S )Nc                 S   s   t | tsJ | j|_d S r   )r1   r   r  )r   Zeager_tensorr   r   r   set_stop_gradient  s   zDPartialProgramLayer._update_stop_gradient.<locals>.set_stop_gradient)r  r   r-   )r   r   r%  r  r   r   r   r   _update_stop_gradient  s   z)PartialProgramLayer._update_stop_gradientc                 C   s,   | j |}|durt|dkr|d }|S )zZ
        Restores same nested outputs by only replacing the Variable with Tensor.
        Nr   r   )r   r<   r2   )r   r   Zoutsr   r   r   r     s   z PartialProgramLayer._restore_outc                 C   s   |j ddS )NT)Zfor_test)r|   r   r   r   r   _clone_for_test  rD   z#PartialProgramLayer._clone_for_testc                 C   s2   t |tjjr|jdgkr| d tkrdS dS )Nr   r   TF)r1   r   r!  r"  r  numpyr   r$  r   r   r   _is_no_value  s   z PartialProgramLayer._is_no_valuec                    s   t |tjjr |rdS |S t |ttfrQt |tr(t fdd|D }n	 fdd|D }t|t|k}t|dkrC|rCdS t|dkrO|rO|d S |S |S )zK
        Removes invalid value for various-length return statement
        Nc                 3   s    | ]
}  |s|V  qd S r   r)  rS   r   r,   r   r   r     s    

z7PartialProgramLayer._remove_no_value.<locals>.<genexpr>c                    s   g | ]	}  |s|qS r   r*  r+  r,   r   r   r]     s    z8PartialProgramLayer._remove_no_value.<locals>.<listcomp>r   r   )r1   r   r!  r"  r)  rq   r:   r2   )r   r   resZhas_removedr   r,   r   r     s"   


z$PartialProgramLayer._remove_no_valuer   c                 C   sp   |j }|j}t||D ]*\}}t|rq| r#|tjjj	j
j q| r2|tjjj	j
j qtdd S )Nz5only support selected_row and dense_tensor grad type.)rl   rB   r  r   Zis_selected_row_typer   r.   rw   r   r   r   r   Zis_dense_tensor_typer   r   )r   r   r   Zforward_params_gradsr  r4   r   r   r   r     s"   z"PartialProgramLayer._set_grad_typec                 C   sn   t | jttfstdt| j t }t| jD ]\}}t |tj	j
s.td|t|||j qdS )a  
        Check all params from main program are already initialized, see details as follows:
            1. all parameters in self._params should be type `framework.EagerParamBase` which are created in dygraph.
            2. all parameters from transformed program can be found in self._params.
               Because they share same data with EagerParamBase of original dygraph.
        zUType of self._params in PartialProgramLayer should be list or tuple, but received %s.zaType of self._params[{}] in PartialProgramLayer should be Parameter or Variable, but received {}.N)r1   r   r:   rq   	TypeErrorr   setr	  r   r!  r"  formataddrF   )r   r   Zparam_and_buffer_names_setr#  r   r   r   r   r     s    z,PartialProgramLayer._check_params_all_initedc                 C   s   |r|S d S r   r   )r   varsr   r   r   r     s   zPartialProgramLayer._valid_varsr   r  F)(r   r"   r#   r$   r   r   r   r   r   r   r   r   r   r   r   r   r?   rB   r   r   r   r   r  r@   r   r   r   r   r   r   r   r&  r   r'  r)  r   r   r   r   __classcell__r   r   r   r   r     sX    +

%


	


Nu#
		
r   Fc                 C   s8   | j }|r|r|dd  }t| j|| j| jfi | jS )Nr   )r   r   r   r   r   r   )Zconcrete_programZfrom_methodr   r   r   r   partial_program_from  s   r4  r2  )(r  r(  r   r.   Zpaddle.pir.corery   r   r  r   Zpaddle.amp.auto_castr   r   Zpaddle.autograd.ir_backwardr   Zpaddle.baser   Zpaddle.base.compilerr   Zpaddle.base.data_feederr	   r
   Zpaddle.base.dygraph.baser   Zpaddle.optimizer.lrr   Z
paddle.pirr   r   r   r/   r   r   __all__r   r%   r@   r   r   r   r4  r   r   r   r   <module>   s8   8 [1     