o
    "j                    @  s  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mZ d dl	m
  mZ d dlmZmZ d dlmZmZ d dlmZ d dlmZmZmZ d dlmZ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% ddl&m'Z'm(Z( ddl)m*Z* ddl+m,Z,m-Z-m.Z.m/Z/ ddl0m1Z1m2Z2m3Z3 ddl4m5Z5 ddl6m5Z7 ddl8m9Z9m:Z:m;Z;m<Z<m=Z=m>Z>m?Z?m@Z@mAZAmBZBmCZCmDZD erd dlEmFZF g ZGdZHdZIdd ZJG dd dZKeL ZMeK ZNdd ZOG dd dZPdd  ZQG d!d" d"ZRd#d$ ZSG d%d& d&eRZTG d'd( d(eRZUd)d* ZVG d+d, d,ZWG d-d. d.ZXd/d0 ZYG d1d2 d2ZZG d3d4 d4Z[G d5d6 d6Z\G d7d8 d8e7Z]G d9d: d:Z^G d;d< d<e5Z_G d=d> d>Z`d?d@ Zaeeb eb dAdAfdBdCZcdS )D    )annotationsN)TYPE_CHECKING)decomposition	get_flags)core	framework)
check_type)_to_static_mode_guard_param_guardswitch_to_static_graph)UniqueNameGeneratorguard)in_dynamic_modeuse_pir_api)layers)OpResult)flattengast   )errorlogging_utils)DygraphToStaticAst)FunctionSpec_hash_spec_namesget_buffersget_parameters)attach_origin_info!create_and_update_origin_info_map$update_op_callstack_with_origin_info)PartialProgramLayerHook)ALREADY_D2SNO_SHAPE_VAR_TYPEast_to_funcbackend_guardfunc_to_source_codeinput_specs_compatibleis_paddle_funcmake_hashableprim_is_enabledprim_or_cinn_is_enabled	type_nameunwrap)
AmpOptions
   Z__jst_not_to_staticc                   s   t   _ fdd}|S )Nc                    s8    j   | i |W  d    S 1 sw   Y  d S N)__lock__)argskwargsfunc h/var/www/html/Deteccion_Ine/venv/lib/python3.10/site-packages/paddle/jit/dy2static/program_translator.py	lock_funcY   s   $zsynchronized.<locals>.lock_func)	threadingLockr/   )r3   r6   r4   r2   r5   synchronizedV   s   
r9   c                   @  s0   e Zd ZdZdd Zdd Zdd Zdd	 Zd
S )FunctionCachez_
    Caches the transformed functions to avoid redundant conversions of the same function.
    c                 C  s   t  | _i | _t | _d S r.   )weakrefWeakKeyDictionary_converted_static_func_caches_code_to_ast_cachesr   _dygraph_to_staticselfr4   r4   r5   __init__e   s   
zFunctionCache.__init__c                 C  s.   | j |d}|du r| |}|| j |< |S )zg
        Returns the cached static function or converts it when first encounters the function.
        N)r=   get_convert)rA   r3   static_funcr4   r4   r5   convert_with_cachel   s
   

z FunctionCache.convert_with_cachec                 C  sl   t |}t|}|| jv r| j| }nt|}t||}| j|}|| j|< t||\}}t	|| |S )a!  
        Converts dygraph function into static function. For two functions with same dedent code,
        the second function will reuse the transformed ast node of previous one.

        For example:
            # A.py
            def foo(x, y):
                z = x + y
                return z

            # B.py
            def foo(x, y):
                z = x + y
                return z

        If the conversion of A.foo happens after B.foo, it will reuse the transformed ast node of B.foo
        to speed up the conversion.
        )
r+   r$   r>   r   parser   r?   Zget_static_astr"   r   )rA   r3   source_coderootrE   	file_namer4   r4   r5   rD   y   s   




zFunctionCache._convertc                 C  s
   || j v S r.   )r=   )rA   r3   r4   r4   r5   exist      
zFunctionCache.existN)__name__
__module____qualname____doc__rB   rF   rD   rK   r4   r4   r4   r5   r:   `   s    *r:   c                 C  s   t | tdr| S t | td}|dur|jpt| }|r%t| r#| jS | S t t	
| }t|td |W  d   S 1 s?w   Y  dS )a  
    Transforms function of dygraph into static function using the cache mechanism.

    Note(dev): It will return function.__func__ if encountering class method.

    Args:
        function(callable): The function with dygraph layers that will be converted into static layers.
    NT)getattrr    CONVERSION_OPTIONSZnot_convertr&   inspectismethod__func___CACHE_LOCK_FUNCTION_CACHErF   setattr)functionoptionsZ	need_skiprE   r4   r4   r5   convert_to_static   s   	
$r[   c                   @  sL   e Zd ZdZg dZdd Zedd Zdd Zd	d
 Z	dd Z
dd ZdS )CacheKeyz&
    Cached key for ProgramCache.
    )function_specinput_args_with_specinput_kwargs_with_specclass_instancer1   _spec_names_id
_pir_flagsc                 K  sH   || _ || _|| _|| _|| _t||| _tdd p tdd | _dS )a  
        Initializes a cache key.

        Args:
            functions_spec(FunctionSpec): a FunctionSpec instance of decorated function.
            input_args_with_spec(list[InputSpec]): actual input args with some arguments replaced by InputSpec.
            input_kwargs_with_spec(list[{string:InputSpec}]): actual input kwargs with some arguments replaced by InputSpec.
            class_instance(object): a instance of class `Layer`.
            **kwargs(dict): manage other arguments used for better scalability
        ZFLAGS_enable_pir_in_executorZ!FLAGS_enable_pir_with_pt_in_dy2stN)	r]   r^   r_   r`   r1   r   ra   r   rb   )rA   r]   r^   r_   r`   r1   r4   r4   r5   rB      s   zCacheKey.__init__c           	      C  sN   |rt |d tjr|dd }|||\}}|||\}}t||||S )ag  
        Generated a CacheKey instance by given inputs.

        Args:
            functions_spec(FunctionSpec): a FunctionSpec instance of decorated function.
            args(tuple): tuple of actual inputs arguments.
            kwargs(dict): dict of actual inputs keyword arguments.
            class_instance(object): a instance of class `Layer`.
        r   r   N)
isinstancer   Layerunified_args_and_kwargsargs_to_input_specr\   )	clsr]   r0   r1   r`   _args_kwargsr^   r_   r4   r4   r5   from_func_and_args   s   
zCacheKey.from_func_and_argsc              	   C  sT   d}| j dd}| j dd}tt| jt| j|t| j|| j| j	||| j
fS )NzoArguments to a `@paddle.jit.to_static` must be a hashable Python objects (or nested structures of these types).	with_hookFis_train)r1   rC   hashidr]   r'   r^   r_   ra   r`   rb   )rA   	error_msgrk   rl   r4   r4   r5   __hash__  s   

zCacheKey.__hash__c                 C  s    t | t |u ot| t|kS r.   )typerm   rA   otherr4   r4   r5   __eq__'  s    zCacheKey.__eq__c                 C  s
   | |k S r.   r4   rr   r4   r4   r5   __neq__*  rL   zCacheKey.__neq__c                 C  s   d t| j| j| j| jS )Nz_id(function_spec): {}, input_args_with_spec: {}, input_kwargs_with_spec: {}, class_instance: {})formatrn   r]   r^   r_   r`   r@   r4   r4   r5   __repr__-  s   zCacheKey.__repr__N)rM   rN   rO   rP   	__slots__rB   classmethodrj   rp   rt   ru   rw   r4   r4   r4   r5   r\      s    
$
r\   c                 C  sN   g }| }	 t |tr!|| |j}|dur|j|}n	|j}n	 ||fS q)zW
    Unwraps a decorated function and returns the decorator list and inner target.
    TN)rc   StaticFunctionappend_class_instancedygraph_function__get__)r3   Z
decoratorscurinstancer4   r4   r5   unwrap_decorators6  s   

r   c                   @  s   e Zd Zd5ddZdd Zedd Zdd	 Zd
d Zdd Z	dd Z
dd Zdd Zdd Zdd Zdd Zdd Zdd Zedd Zed d! Zed"d# Z	$d6d%d&Zd'd( Zd)d* Zed+d, Zed-d. Zed/d0 Zed1d2 Zed3d4 ZdS )7rz   Nc                 K  s   t |r |j| _|j| _t| jdstd| j| jj|j	< n|| _d| _|durMt
 rMddlm} t|D ]}t||rLd|jv rLd}td  nq7|| _t||| _t | _t | _t | _|| _d| _d	| _d| _| d
d| _!| "  dS )az  
        Initializes a `StaticFunction`.

        Args:
            function(callable): A function or method that will be converted into static program.
            input_spec(list[InputSpec]): list of InputSpec to specify the `shape/dtype/name` information for each input argument, default None.
            **kwargs(dict): other arguments like `build_strategy` et.al.
        _original_funcscWhen using 'to_static' to convert method of a class, please ensure the class inherits from nn.LayerNr   )	InputSpecz\Now prim and cinn do not support -1 shape, but input_spec has -1 shape so we set it to None.T propertyF)#rS   rT   rU   _dygraph_function__self__r|   hasattr	TypeErrorr   rM   r(   Zpaddle.staticr   r   rc   shapewarningswarn_input_specr   _function_specProgramCache_program_cacher;   r<   _descriptor_cacheProgramTranslator_program_transri   	_training_cuda_graph_capture_mode_cuda_graph_pool_idrC   	_property_get_debug_name)rA   rY   
input_specr1   r   specr4   r4   r5   rB   K  sD   

zStaticFunction.__init__c                 C  sD   z| j r| j jj| _W d S | jj| _W d S  ty!   d| _Y d S w )NZstatic_function)r|   	__class__rM   _debug_namer   	Exceptionr@   r4   r4   r5   r   ~  s   zStaticFunction._get_debug_namec                 C     | j S r.   )r   r@   r4   r4   r5   is_property  s   zStaticFunction.is_propertyc                 C  4   t | jtjr| jjdu rtd| jd| _d S )NFzcFailed to switch train mode. {} is a Layer's method, please use Layer.train() to switch train mode.T	rc   r|   r   rd   trainingRuntimeErrorrv   r}   r   r@   r4   r4   r5   train     
zStaticFunction.trainc                 C  r   )NTz`Failed to switch eval mode. {} is a Layer's method, please use Layer.eval() to switch eval mode.Fr   r@   r4   r4   r5   eval  r   zStaticFunction.evalc                 C  sf   || j vr.|du r| S |  }t|tjr&| jj|j vr&| j|j| jj< ||_	|| j |< | j | S )a  
        Overrides this method to parse the class instance and call bound method correctly.

        For example:

            '''
            class Net(Layer):
                def __init__(self):
                    pass

                @paddle.jit.to_static
                def forward(self, x, y):
                    return x + y

            net = Net()
            out = net(x, y)
            '''

        In above case, `net(x, y)` will call `net.forward(x, y)` firstly that is a bound method
        of `Net` instance. After decorated by `@paddle.jit.to_static`, it will firstly to call `__get__`
        to parse the class instance correctly instead of the `StaticFunction` instance.
        N)
r   _clonerc   r   rd   r   rM   r   keysr|   )rA   r   ownerZnew_static_layerr4   r4   r5   r~     s    



zStaticFunction.__get__c                 C  s   | j | j| jfi | jS r.   )r   r}   r   ri   r@   r4   r4   r5   r     s
   zStaticFunction._clonec                 O  s`   | j r| j|i |S | jjstd | j|i |S t s(td| j d| j	|i |S )ag  
        Supports to call the returned instance with input `args` and `kwargs` directly.

        Args:
            *args(tuple): tuple of all input arguments from original decorated function.
            **kwargs(dict): dict of all input keyward arguments from original decorated function.

        Return:
            Outputs of decorated function.
        zThe decorator '@paddle.jit.to_static' does NOT work when setting 'paddle.jit.enable_to_static' to False. We will just return dygraph output. If you would like to get static graph output, please call API paddle.jit.enable_to_static(True)z"Failed to run the callable object z decorated by '@paddle.jit.to_static', because it is NOT in dynamic mode. Please disable the static graph mode to enter dynamic mode with the following API: paddle.disable_static().)
r   _call_dygraph_functionr   enable_to_staticr   r   r   r   r}   _perform_callrA   r0   r1   r4   r4   r5   __call__  s   zStaticFunction.__call__c                 C  s,   | j d urt| j dstd| j jS | jS )Nr   r   )r|   r   r   r   r   r@   r4   r4   r5   _is_train_mode  s   
zStaticFunction._is_train_modec                 O  s   | j |i |S )aN  
        Calls dygraph function directly and returns the outputs.

        Args:
            *args(tuple): tuple of all input arguments from original decorated function.
            **kwargs(dict): dict of all input keyward arguments from original decorated function.

        Return:
            Outputs of dygraph function.
        )r}   r   r4   r4   r5   r     s   z%StaticFunction._call_dygraph_functionc                 C  s   | j rtddS )zraise RuntimeError when property=True

        Raises:
            RuntimeError: can not call this func when property=True
        z)Can not call the func when property=True.N)r   r   r@   r4   r4   r5   _raise_when_property  s   z#StaticFunction._raise_when_propertyc                 O     t dNzNot implemented yet.NotImplementedErrorr   r4   r4   r5   get_concrete_program     z#StaticFunction.get_concrete_programc                 C  r   r   r   )rA   
cached_keyr4   r4   r5   #get_concrete_program_with_cache_key  r   z2StaticFunction.get_concrete_program_with_cache_keyc                 C  r   r   r   r@   r4   r4   r5   get_traced_count   r   zStaticFunction.get_traced_countc                 C  r   r   r   r@   r4   r4   r5   code#     zStaticFunction.codec                 C  s   | j dur| j| j S | jS )z:
        Returns the original decorated function.
        N)r|   r   r~   r@   r4   r4   r5   r}   '  s   
zStaticFunction.dygraph_functionc                 C  r   r   r   r@   r4   r4   r5   concrete_program1  r   zStaticFunction.concrete_programFc                 C  r   r   r   )rA   r   rk   is_prim_inferr4   r4   r5   #concrete_program_specify_input_spec5  s   z2StaticFunction.concrete_program_specify_input_specc                   s    fdd | j du r| jS | jj}|| j jv s"J d|| j j| j j| }t| j ||| j  | j jddD ]} | q:t	| j |S )a  
        Rollback into original dygraph functions for current class instance.

        Returns:
            Function or Method

        Example::
            .. code-block:: python

                >>> # doctest: +SKIP('`paddle.jit.to_static` can not run in xdoctest')
                >>> import paddle

                >>> class Net(paddle.nn.Layer):
                ...     def __init__(self):
                ...         super().__init__()
                ...
                ...     def forward(self, x, flag=True):
                ...         if flag:
                ...             out = x + 1
                ...         else:
                ...             out = x - 1
                ...         return out
                ...
                >>> x = paddle.randn([10, 1], 'float32')
                >>> net = paddle.jit.to_static(Net())  # convert into static graph mode
                >>> out = net(x)

                >>> net.forward.rollback()  # rollback into dygraph mode
                >>> out = net(x)
        c                   sD   | j  D ]\}}t| |||  q| jddD ]} | qd S )NFZinclude_self)r   itemsrX   r~   	sublayers)r`   namer3   sublayerrollback_implr4   r5   r   Z  s
   
z.StaticFunction.rollback.<locals>.rollback_implNz&Not Found function '{}' in class '{}'.Fr   )
r|   r   rM   r   rv   r   rX   r~   r   rQ   )rA   	func_namer3   r   r4   r   r5   rollback:  s     

zStaticFunction.rollbackc                 C  sP   | j dur%t| j j}tjdd||d |   | j|t	| j  S | jS )a  
        Customized behavior for copy.deepcopy, return original decorated function instead
        of a new StaticFunction Object. StaticFunction itself is not copyable becuase it's
        associated with class_instance.

        We add __deepcopy__ here only for the following usage:

        Example::
            .. code-block:: python

                >>> import copy
                >>> import paddle

                >>> class Net(paddle.nn.Layer):
                ...     def __init__(self):
                ...         super().__init__()
                ...
                ...     def forward(self, x, flag=True):
                ...         if flag:
                ...             out = x + 1
                ...         else:
                ...             out = x - 1
                ...         return out
                ...
                >>> x = paddle.randn([10, 1], 'float32')
                >>> net = paddle.jit.to_static(Net())  # convert into static graph mode

                >>> copy_net = copy.deepcopy(net)      # deepcopy a new net without @to_static

        Please attention that original 'net' will unwrap @to_static and rollback into simple Layer.
        Nr   zNot recommend to deepcopy '{}' decorated with @to_static, it has side effect that will rollback into original state before @to_static. Please deepcopy '{}' before applying @to_static.)levelmsg)
r|   rq   rM   r   logrv   r   r   r~   rn   )rA   memoZnet_namer4   r4   r5   __deepcopy__u  s   
 zStaticFunction.__deepcopy__c                 C  r   r   r   r@   r4   r4   r5   inputs  r   zStaticFunction.inputsc                 C  r   r   r   r@   r4   r4   r5   outputs  r   zStaticFunction.outputsc                 C  r   r   r   r@   r4   r4   r5   main_program  r   zStaticFunction.main_programc                 C  r   r   r   r@   r4   r4   r5   program_cache  r   zStaticFunction.program_cachec                 C  r   r   r   r@   r4   r4   r5   r]     r   zStaticFunction.function_specr.   NFF)rM   rN   rO   rB   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]   r4   r4   r4   r5   rz   J  sH    
3	
*$	

	

;0



rz   c                   s    fdd}|S )Nc                    s   d}t |j d)Nz[Can't call {func} when full_graph=False. Use paddle.jit.to_static(full_graph=True) instead.r2   )r   rv   )r0   r1   Zerror_templatefunc_strr4   r5   _raise_error  s   z*raise_error_template.<locals>._raise_errorr4   )r   r   r4   r   r5   raise_error_template  s   r   c                      s   e Zd Zd fdd	Zdd Zedd Zedd	 Zed
Z	edZ
edZedZedd Zedd Zedd Zedd Zedd Z  ZS )SymbolicStaticFunctionNc                   s2   |d ur	t d t j||fi | d | _d S )Nzfull_graph=False don't support input_spec arguments. It will not produce any effect.
You can set full_graph=True, then you can assign input spec.
)r   r   superrB   last_call_input_specrA   rY   r   r1   r   r4   r5   rB     s   
zSymbolicStaticFunction.__init__c           	      O  s   ddl m} | j||\}}| j||\}}|| _| jdd }| jdd }|| j|| 	 |d}| j
d ur?| j
f| }||i |S )N   )symbolic_translatebuild_strategybackend)r   r   r   )Zsotr   r   re   rf   r   ri   rC   r   r   r|   )	rA   r0   r1   r   r^   r_   r   r   Z
traced_funr4   r4   r5   r     s$   
z$SymbolicStaticFunction._perform_callc                 C     t d  d S )Nr   r   r@   r4   r4   r5   r        zSymbolicStaticFunction.codec                 C  r   )Nr   r   r@   r4   r4   r5   r     r   z'SymbolicStaticFunction.concrete_programr   r   r   r   c                 C  r   )Nr   r   r@   r4   r4   r5   r     r   zSymbolicStaticFunction.inputsc                 C  r   )Nr   r   r@   r4   r4   r5   r     r   zSymbolicStaticFunction.outputsc                 C  r   )Nr   r   r@   r4   r4   r5   r     r   z#SymbolicStaticFunction.main_programc                 C  r   )Nr   r   r@   r4   r4   r5   r     r   z$SymbolicStaticFunction.program_cachec                 C  r   )Nzfunction_spec r   r@   r4   r4   r5   r]     r   z$SymbolicStaticFunction.function_specr.   )rM   rN   rO   rB   r   r   r   r   r   r   r   r   r   r   r   r   r   r]   __classcell__r4   r4   r   r5   r     s2    	





r   c                      s   e Zd ZdZd fdd	Zdd Zdd Zd	d
 Zdd Ze	dd Z
e	dd Z	dddZe	dd Ze	dd Ze	dd Ze	dd Ze	dd Z  ZS ) ASTStaticFunctionzL
    Wrapper class to Manage program conversion of decorated function.

    Nc                   s   t  j||fi | d S r.   )r   rB   r   r   r4   r5   rB     s   zASTStaticFunction.__init__c              
   O  s  | j ||\}}zR| j|i |d|  i\}}t| jtjr'| jj|_n| j	|_| j
|_
| j|_z||W W S  ty[ } zt|tjsOtj|dd  W Y d }~W d S d }~ww  ty } z"t|tjd }|rq|  ntdt| d |W Y d }~d S d }~ww )Nrl   T)Z
in_runtimezaPlease file an issue at 'https://github.com/PaddlePaddle/Paddle/issues' if you can't handle this z
 yourself.)r   re   r   r   rc   r|   r   rd   r   r   r   r   r   r   r   
ERROR_DATAattach_error_datarQ   raise_new_exceptionr   r   rq   )rA   r0   r1   _partial_program_layere
error_datar4   r4   r5   r     sJ   
zASTStaticFunction._perform_callc                 O  s   |    |dd}|dd}|dd}d|v r|d d|v r(|d d|v r1|d t|t| jjkrD| j||\}}| j||\}}t| j||| j	fi | j
||d}|rk| j|\}	}
n| j| \}	}
| j|
_|	|
fS )a*  
        Returns traced concrete program and inner executable partial layer.

        Args:
            *args(tuple): input arguments values or InputSpec
            **kwargs(dict) : input kwargs values.

        Returns:
            Traced ConcreteProgram and executable translated Layer.
        rk   Frl   Tr   )rk   rl   )r   rC   poplenr   Z	args_namere   rf   r\   r|   ri   r   get_program_without_cacher   )rA   r0   r1   rk   rl   r   r^   r_   	cache_keyr   r   r4   r4   r5   r   :  sN   



	
z&ASTStaticFunction.get_concrete_programc                 C  s    |    | j|\}}||fS )a  
        Returns traced concrete program and inner executable partial layer by cached key.

        Args:
            cached_key(CacheKey): The cached key use to get concrete program.

        Returns:
            Traced ConcreteProgram and executable translated Layer.
        )r   r   r   )rA   r   r   r   r4   r4   r5   r   q  s   

z5ASTStaticFunction.get_concrete_program_with_cache_keyc                 C  
   t | jS )zS
        Returns the number of traced programs for the decorated function.
        )r   r   r@   r4   r4   r5   r     s   
z"ASTStaticFunction.get_traced_countc                 C  s   t | j}t|}|S )zW
        Returns the source code of transformed static function for debugging.
        )r[   r}   r$   )rA   rE   rH   r4   r4   r5   r     s   
zASTStaticFunction.codec                 C  s   | j ddS )a  
        Returns recent ConcreteProgram instance of decorated function.

        Examples:
            .. code-block:: python

                >>> # doctest: +SKIP('`paddle.jit.to_static` can not run in xdoctest')
                >>> import paddle
                >>> from paddle.jit import to_static
                >>> from paddle.static import InputSpec

                >>> paddle.disable_static()

                >>> def foo(x, y):
                ...     z = x + y
                ...     return z
                ...
                >>> # usage 1:
                >>> decorated_foo = to_static(foo, input_spec=[InputSpec([10], name='x'), InputSpec([10], name='y')])
                >>> print(decorated_foo.concrete_program)

                >>> # usage 2:
                >>> decorated_foo = to_static(foo)
                >>> out_foo = decorated_foo(paddle.rand([10]), paddle.rand([10]))
                >>> print(decorated_foo.concrete_program)
        N)r   )r   r@   r4   r4   r5   r     s   z"ASTStaticFunction.concrete_programFc           
      C  s  |    t| j}|}| jjdur;|dur*tt|t| jjs*td|| jj| jj}|dur;t	
d|| |du}|rQ| j|||  |d\}}|S |dkrt	
d |dkrht	
d| j| | jj}	|rsd	|	jd
< |r~| |	\}}|S | j|	 \}}|S td| j)a  
        Returns recent ConcreteProgram instance of decorated function while
        specifying input_spec. If the self._function_spec already has
        input_spec, it will check the compatibility of input input_spec and
        the self._function_spec.input_spec. If input input_spec=None, then
        this method uses self._function_spec.input_spec

        args:
            input_spec (list[InputSpec], optional): Describes the input of
                the translate function.
        NzxThe `input_spec`: {} used to construct concrete_program is conflict with the `input_spec`: {} in `@paddle.jit.to_static`z

You have specified `input_spec` both in function definition (higher priority) and `paddle.jit.save` (will be ignored.)

	 Using: {}

	 Ignore: {}
)rk   rl   r   r   z3No input_spec is found, save cached program insteadr   zcCurrent {} has more than one cached programs: {}, the last traced progam will be return by default.Trk   zNo valid transformed program for {}.
	    Please specific `input_spec` in `@paddle.jit.to_static` or feed input tensor to call the decorated function at once.
)r   r   r   r   r   r%   r   
ValueErrorrv   r   r   r   r   _recent_cache_keyr1   r   )
rA   r   rk   r   Zcached_program_lenZdesired_input_specZhas_input_specr   r   r   r4   r4   r5   r     sl   


z5ASTStaticFunction.concrete_program_specify_input_specc                 C  &   |    | j}dd t|jD }|S )zK
        Returns input tensors of recent converted static program.
        c                 S      g | ]}t |tjtfr|qS r4   rc   r   Variabler   .0varr4   r4   r5   
<listcomp>
      z,ASTStaticFunction.inputs.<locals>.<listcomp>)r   r   r   r   )rA   r   r   r4   r4   r5   r     s   zASTStaticFunction.inputsc                 C  r   )zL
        Returns output tensors of recent converted static program.
        c                 S  r   r4   r   r   r4   r4   r5   r     r   z-ASTStaticFunction.outputs.<locals>.<listcomp>)r   r   r   r   )rA   r   r   r4   r4   r5   r     s   zASTStaticFunction.outputsc                 C  s   |    | j}|j}|S )z?
        Returns recent converted static main program.
        )r   r   r   )rA   r   r   r4   r4   r5   r      s   zASTStaticFunction.main_programc                 C  r   r.   )r   r@   r4   r4   r5   r   *     zASTStaticFunction.program_cachec                 C  r   r.   )r   r@   r4   r4   r5   r]   .  r   zASTStaticFunction.function_specr.   r   )rM   rN   rO   rP   rB   r   r   r   r   r   r   r   r   r   r   r   r   r]   r   r4   r4   r   r5   r     s.    &7


T


	
r   c                 C  s(   t | tjr| jstd| dS dS )z?
    Verifies the instance is initialized in dynamic mode.
    z `paddle.jit.to_static` is only available in dynamic mode. Please call `paddle.disable_static()` before initializing your Layer class `{}` . Because parameters of Layer class should be initialized firstly in dynamic mode while applying transformation.N)rc   r   rd   Z_init_in_dynamic_moder   rv   )r`   r4   r4   r5   _verify_init_in_dynamic_mode3  s   r   c                   @  s*   e Zd ZdZd
ddZdd Zdd Zd	S )
HookHelperz
    Only For converting pre/post hooks operation in outermost layer while jit.save.
    Because hooks in sublayer have been processed automatically.
    Fc                 C  s4   || _ || _|| _|ot| jtjo|jdk| _d S )Nforward)r3   r`   rk   rc   r   rd   rM   need_apply_hook)rA   r3   r`   rk   r4   r4   r5   rB   H  s   zHookHelper.__init__c                 C  s`   | j s|S |dd }| jj D ]}|| j|}|dur't|ts%|f}|}q| jgt| S )z?
        Apply _forward_pre_hooks from outermost layer
        r   N)r  r`   Z_forward_pre_hooksvaluesrc   tuplelist)rA   r   Zforward_pre_hookhook_resultr4   r4   r5   apply_pre_hooksR  s   
zHookHelper.apply_pre_hooksc                 C  sT   | j s|S |dd }| jj D ]}|| j||}|dur |}q|d| j |S )z@
        Apply _forward_post_hooks from outermost layer
        r   Nr   )r  r`   Z_forward_post_hooksr  insert)rA   r   r   Zforward_post_hookr  r4   r4   r5   apply_post_hooksc  s   
zHookHelper.apply_post_hooksN)F)rM   rN   rO   rP   rB   r  r  r4   r4   r4   r5   r   B  s
    

r   c                   @  s@   e Zd Zg dZ	d	ddZeedd Zeedd ZdS )
ConcreteProgramr   r   r   startup_program
parametersrY   name_generatorr1   Nc           	      K  s4   || _ || _|| _|| _|| _|| _|| _|| _d S r.   r
  )	rA   r   r   r  rY   r  r   r  r1   r4   r4   r5   rB     s   
zConcreteProgram.__init__c                 K  s  t | | j}t|}t|||dd}t t }}	t||	 tdd | 	||}
| 	||}|rBt
|gt|
 }
tt|dZ tt|dC z||
}|rb||i |}n|| }|||}W n ty } zt| t|tjd}|r|   d}~ww W d   n1 sw   Y  W d   n1 sw   Y  ddlm} ||}|durt|t
tf pt|dk}|r|g}W d   n1 sw   Y  W d   n1 sw   Y  t }td
|
||||||	d	|S )  
        Builds the main_program with specialized inputs and returns outputs
        of program as fetch_list.

        Args:
            func_spec(FunctionSpec): A FunctionSpec instance for decorated function.
            input_spec(list[InputSpec]):
        rk   FTZis_to_staticNr   )_global_parameter_recorderr   )r   r   r  r  rY   r   r  r4   )r   r}   r[   r   rC   	ir_staticProgramprogram_guardr	   Zpir_to_static_inputs_with_specr  r  r
   r   r   r  r  BaseExceptionr   r   rQ   r   r   Z pir_dy2static.parameter_recorderr  r   rc   r   r   r	  )	func_specr   input_kwargs_specr`   r1   r}   rE   hook_helperr   r  static_inputsri   r   r   r   r   r  all_parameters_and_buffersneed_wrap_into_listnew_name_generatorr4   r4   r5   pir_from_func_spec  s   

 
5z"ConcreteProgram.pir_from_func_specc                 K  sL  t | | j}t|}t|||dd}t t }}	t j|_t	 j|	_t
 }
t j  t||	 tdd t|
 | ||}| ||}|r]t|gt| }tt|dZ tt|dC z||}|r}||i |}n|| }|||}W n ty } zt| t|tjd}|r|   d}~ww W d   n1 sw   Y  W d   n1 sw   Y  t j !|}|durt"|ttf pt#|dk}|r|g}W d   n1 sw   Y  W d   n1 sw   Y  W d   n	1 sw   Y  t$|}t%d|||||
||	d|S )	r  rk   FTr  Nr   )r   r   r  rY   r  r   r  r4   )&r   r}   r[   r   rC   r   r  Zdefault_main_programZrandom_seedZdefault_startup_programr   r   get_instance_amp_recordsclearr  r	   UniqueNameGuardZto_static_inputs_with_specr  r  r
   r   r   r  r  r  r   r   rQ   r   r   _params_recorderr   rc   r   r   r	  )r  r   r  r`   r1   r}   rE   r  r   r  r  r  ri   r   r   r   r   r  r  r4   r4   r5   from_func_spec  s   

 

 3zConcreteProgram.from_func_specr.   )	rM   rN   rO   rx   rB   staticmethodr   r  r"  r4   r4   r4   r5   r	  x  s    
cr	  c                 C  s   t | S )zh
    because program is not deleted while calling from_func_spec.
    so it's ok to use id(program)
    )rn   )programr4   r4   r5   _program_hashb  s   r%  c                   @  s(   e Zd Zdd Zedd Zdd ZdS )ParametersRecorderc                 C  
   i | _ d S r.   params_dictr@   r4   r4   r5   rB   k  rL   zParametersRecorder.__init__c                 C  s6   t |}|| jvrt | j|< | j| }|| dS z@use the default_program as key, append param the parameter list.N)r%  r)  setadd)rA   r$  paramkeyparamsr4   r4   r5   r,  n  s
   

zParametersRecorder.addc                 C  s0   | j t|}|d u rg S | j t|= t|S r.   )r)  rC   r%  r  )rA   r$  r/  r4   r4   r5   r   w  s
   zParametersRecorder.popN)rM   rN   rO   rB   r9   r,  r   r4   r4   r4   r5   r&  j  s
    
r&  c                   @  s8   e Zd Zdd Zedd Zdd Zdd Zd	d
 ZdS )
InplaceMapc                 C  r'  r.   r(  r@   r4   r4   r5   rB     rL   zInplaceMap.__init__c                 C  s2   t |}|| jvri | j|< | j| }|||< dS r*  )r%  r)  )rA   r$  rn   r-  r.  r/  r4   r4   r5   r,    s
   


zInplaceMap.addc                 C  s   | j t|}|d u rd S ||vrd S || }g }|j | v r8|| ||j  }|j | v s#|D ]	}|||j < q:|S r.   )r)  rC   r%  descrn   r   r{   )rA   r$  rn   r/  Zroot_varsavedr   r4   r4   r5   rC     s   
zInplaceMap.getc                 C  s
   || _ d S r.   r(  )rA   
checkpointr4   r4   r5   restore_checkpoint  s   
	zInplaceMap.restore_checkpointc                 C  s   t | j S r.   )dictr)  r   r@   r4   r4   r5   save_checkpoint     zInplaceMap.save_checkpointN)	rM   rN   rO   rB   r9   r,  rC   r4  r6  r4   r4   r4   r5   r0    s    
	r0  c                      s@   e Zd Zg dZdd Zdd Z fddZ fdd	Z  ZS )
FallbackProgramLayer)	_instance_dy_funcr   r   r   r   c                 C  s   || _ || _d S r.   )r9  r:  )rA   r   Zdy_funcr4   r4   r5   rB     s   
zFallbackProgramLayer.__init__c                 C  s
   | j | S r.   )r:  )rA   r   r4   r4   r5   r     rL   zFallbackProgramLayer.__call__c                   s@   || j vr	td|dv r| jd urt| j|S d S t |S NzThere raises a exception after applying `@paddle.jit.to_static()` and already switch into fallback mode. 
You can't get attribute for a fallback program layer. Please check `to_static.error` file for detail.)r   )rx   r   r9  rQ   r   __getattr__)rA   r.  r   r4   r5   r<    s   

z FallbackProgramLayer.__getattr__c                   sD   || j vr	td|dv r| jd urt| j||S d S t ||S r;  )rx   r   r9  rX   r   __setattr__)rA   r.  valuer   r4   r5   r=    s   

z FallbackProgramLayer.__setattr__)	rM   rN   rO   rx   rB   r   r<  r=  r   r4   r4   r   r5   r8    s    	r8  c                   @  ,   e Zd Zdd Zdd Zdd Zdd Zd	S )
PirPrimHookerc                 C  sl   || _ t | _t| j   t r$dd | jD | _W d    d S W d    d S 1 s/w   Y  d S )Nc                 S  s   h | ]}t |r| qS r4   )r   Zhas_custom_vjpr   r   opr4   r4   r5   	<setcomp>  s    z)PirPrimHooker.__init__.<locals>.<setcomp>)r   r+  custom_vjpsr#   r   _is_all_prim_enabledglobal_blockopsrA   Zoriginal_programr   r4   r4   r5   rB     s   
"zPirPrimHooker.__init__c                 C  sf   t | j$ t rtj||| jd}||fW  d    S ||fW  d    S 1 s,w   Y  d S N)	blacklist)r#   r   r   _is_fwd_prim_enabledr   	decomposerD  )rA   forward_programsrc_varsdst_varsr4   r4   r5   before_append_backward  s   $z$PirPrimHooker.before_append_backwardc                 C  s   t | j? t r8t| jdkr8t| j| }tj	||| jd}t| j| }|||fW  d    S |||fW  d    S 1 sGw   Y  d S )Nr   )	whitelist)
r#   r   r   rK  r   rD  rF  rG  r   rL  )rA   whole_programrN  Zforward_end_idxbackward_lengthrO  new_start_indexr4   r4   r5   after_append_backward  s   $z#PirPrimHooker.after_append_backwardc                 C  sf   t | j$ t r t|j|j}||_dt|j	 j
f|_	 W d    d S 1 s,w   Y  d S Nr   )r#   r   r   rK  r   rL  r$  Z
out_valuesr   rF  rG  Zforward_range)rA   infer_programtargetsr4   r4   r5   after_infer  s   $zPirPrimHooker.after_inferNrM   rN   rO   rB   rP  rU  rY  r4   r4   r4   r5   r@    s
    	r@  c                   @  s\   e Zd ZdZdZdd Zdd Zdd Zd	d
 Zdd Z	dd Z
dd Zdd Zdd ZdS )r   zN
    Wrapper class for the program functions defined by dygraph function.
    zto_static.errorc                 C  s   t  | _d | _d | _d S r.   )collectionsOrderedDict_caches_recent_keyr   r@   r4   r4   r5   rB     s   

zProgramCache.__init__c                 C  s  |j d j}|}z*t rtjd
|j|j|j|jd|j }ntj	d
|j|j|j|jd|j }W nC t
yu } z7|rptd t| jd}|t| W d    n1 sYw   Y  t|j|jj}||fW  Y d }~S  d }~ww |j d }t|j d |rt s|j D ]}	|	jtvrd|	jv rtd|	j|	j qt rdd	lm}
 |
||jd u}ndd	lm}
 |
||jd u}t|9 t  rt r|!t"|j| n|!t#|j| W d    ||fS W d    ||fS W d    ||fS 1 sw   Y  ||fS )Nr   )r  r   r  r`   aG  Exception is thrown while applying @paddle.jit.to_static. It will fallback into dygraph mode for training.
1. You can check `to_static.error` file in current workspace directory for detail.
2. In fallback mode, you can only do training, can't call paddle.jit.save(). Please modify model code according `to_static.error` firstlywr   r   zHNow prim and cinn do not support -1 shape, but the shape of var {} is {}r   )partial_program_fromr4   )$r1   Zbuild_cinn_passr   r	  r  r]   r^   r_   r`   r"  r   r   r   opendy2static_error_filewritestrr8  r}   r)   r   Z	list_varsrq   r!   r   rv   r   pir_partial_programr`  partial_programr#   r   rK  Z
set_hookerr@  
PrimHooker)rA   r   Zenable_primZenable_fallbackr   r   fpZfallback_layerr   r   r`  rf  r4   r4   r5   _build_once  s   












zProgramCache._build_oncec                 C  sv   t |tstdt| t|}|| _|| _|| jvr6| || j|< t	| j}|t
kr6td|t
 | j| S )Nz.type(item) should be CacheKey, but received %szCurrent traced program number: {} > `max_tracing_count`:{}. Too much cached programs will bring expensive overhead. The reason may be: (1) passing tensors with different shapes, (2) passing python objects instead of tensors.)rc   r\   r   r*   rm   r   r^  r]  ri  r   MAX_TRACED_PROGRAM_COUNTr   r   rv   )rA   itemitem_idZcurrent_tracing_countr4   r4   r5   __getitem__f  s(   



zProgramCache.__getitem__c                 C  s   | j |dS )N)r   )ri  )rA   r   r4   r4   r5   r   }  s   z&ProgramCache.get_program_without_cachec                 C  s>   t |tstdt| t|}|| jvrtd| j| S )Nz9Input item's type should be FunctionSpec, but received %szaFailed to find program for input item, please decorate input function by `@paddle.jit.to_static`.)rc   r\   r   r*   rm   r]  r   )rA   rk  rl  r4   r4   r5   get_program  s   


zProgramCache.get_programc                 C  s6   t | jdksJ d| jd usJ | j| j| j fS )Nr   z(No valid cached program in ProgramCache.)r   r]  r^  r@   r4   r4   r5   last  s
   zProgramCache.lastc                 C  r   r.   )r   r]  r@   r4   r4   r5   __len__  rL   zProgramCache.__len__c                 C  s   dd | j  D S )Nc                 S  s   g | ]\}\}}|qS r4   r4   )r   r.  cpr   r4   r4   r5   r     s    z2ProgramCache.concrete_programs.<locals>.<listcomp>)r]  r   r@   r4   r4   r5   concrete_programs  s   zProgramCache.concrete_programsc                 C  s   t  | _d S r.   )r[  r\  r]  r@   r4   r4   r5   r    r7  zProgramCache.clearN)rM   rN   rO   rP   rb  rB   ri  rm  r   rn  ro  rp  rr  r  r4   r4   r4   r5   r   	  s    Or   c                   @  r?  )
rg  c                 C  s   t |jdkrtd|| _t | _t| j! t r0dd |	dj
D | _W d    d S W d    d S 1 s;w   Y  d S )Nr   z4The primitive mode only support one block currently.c                 S  s   h | ]}t |jr|jqS r4   )r   Zhas_comp_grad_op_makerrq   rA  r4   r4   r5   rC    s    
z&PrimHooker.__init__.<locals>.<setcomp>r   )r   blocksr   r   r+  rD  r#   r   rE  blockrG  rH  r4   r4   r5   rB     s   

"zPrimHooker.__init__c                 C  sJ   t | j t rt|j| jd |W  d    S 1 sw   Y  d S rI  )r#   r   r   rK  _to_primrs  rD  )rA   rM  r4   r4   r5   rP    s
   $z!PrimHooker.before_append_backwardc                 C  s   t | j= t|dj| }t r"t| jdkr"t|j	|d t|dj| }|dkr7t|j	|d ||fW  d    S 1 sEw   Y  d S )Nr   )rS  )	start_idx)
r#   r   r   rt  rG  r   rK  rD  ru  rs  )rA   rR  Zbackward_start_idxrS  rT  r4   r4   r5   rU    s   $z PrimHooker.after_append_backwardc                 C  sH   t | j t rt|d |W  d    S 1 sw   Y  d S rV  )r#   r   r   rK  ru  rt  )rA   rW  r4   r4   r5   rY    s
   $zPrimHooker.after_inferNrZ  r4   r4   r4   r5   rg    s
    rg  c                   @  sP   e Zd ZdZe ZdZedd Z	e
dd Ze
dd Zd	d
 Zdd ZdS )r   a  
    Class to translate dygraph function into static graph function. The object
    of this class is a singleton.

    Args:
        None.

    Returns:
        ProgramTranslator: the singleton object.

    Examples:
        .. code-block:: python

            >>> import paddle

            >>> # Two methods get same object because ProgramTranslator is a singleton
            >>> paddle.jit.dy2static.program_translator.ProgramTranslator()
            >>> paddle.jit.dy2static.program_translator.ProgramTranslator.get_instance()

    Nc                 O  s2   | j d u rtj| g|R i || _ d| j _| j S NF)r9  object__new___initialized)rg   r0   r1   r4   r4   r5   ry    s   
zProgramTranslator.__new__c                 C  sB   | j d u r| j |  | _ W d    | j S 1 sw   Y  | j S r.   )r9  _singleton_lockrg   r4   r4   r5   r    s   


zProgramTranslator.get_instancec                 C  s$   | j d urd| j _| j   d S d S rw  )r9  rz  rB   r|  r4   r4   r5   reset  s   
zProgramTranslator.resetc                 C  s8   | j rd S d| _ t | _t | _t | _i | _d| _d S )NT)	rz  r   r   r&  r!  r0  Z_inplace_mapr  r   r@   r4   r4   r5   rB     s   
zProgramTranslator.__init__c                 C  s   t |dtd || _d S )Nr   ProgramTranslator.enable)r   boolr   )rA   r   r4   r4   r5   enable  s   
r~  )rM   rN   rO   rP   r7   r8   r{  r9  r9   ry  ry   r  r}  rB   r  r4   r4   r4   r5   r     s    


r   c                 C  s"   t | dtd t }||  dS )aw  
    Enable or disable the converting from imperative to static graph by
    ProgramTranslator globally.

    Args:
        enable_to_static_bool (bool): True or False to enable or disable converting to static.

    Returns:
        None.

    Examples:
        .. code-block:: python

            >>> import paddle
            >>> @paddle.jit.to_static
            >>> def func(x):
            ...     if paddle.mean(x) > 0:
            ...         x_v = x - 1
            ...     else:
            ...         x_v = x + 1
            ...     return x_v
            ...
            >>> paddle.jit.enable_to_static(False)

            >>> x = paddle.ones([1, 2])
            >>> # ProgramTranslator is disabled so the func is run in dygraph
            >>> print(func(x))
            Tensor(shape=[1, 2], dtype=float32, place=Place(cpu), stop_gradient=True,
            [[0., 0.]])

    enable_to_static_boolzpaddle.jit.enable_to_staticN)r   r  r   r  )r  r   r4   r4   r5   r     s    r   r   c                 C  s$   ddl m} |j| ||||d dS )z'Swith to static graph and call to_prim.r   )primapi)rJ  rQ  rv  rS  N)Zpaddle.incubate.autogradr  Zto_prim)rs  rJ  rQ  rv  rS  r  r4   r4   r5   ru  5  s   

ru  )d
__future__r   r[  rS   r7   r   r;   typingr   Zpaddle.pir.coreZpirr   r  Zpaddler   r   Zpaddle.baser   Zpaddle.base.data_feederr   Zpaddle.base.dygraph.baser	   r
   r   Zpaddle.base.unique_namer   r   r   Zpaddle.frameworkr   r   Zpaddle.nn.layerr   Z
paddle.pirr   Zpaddle.utilsr   r   r   r   r   Zast_transformerr   r]   r   r   r   r   Zorigin_infor   r   r   rf  r   re  ZPirPartialProgramLayerHookutilsr    r!   r"   r#   r$   r%   r&   r'   r(   r)   r*   r+   Zpaddle.static.amp.fp16_utilsr,   __all__rj  rR   r9   r:   r8   rV   rW   r[   r\   r   rz   r   r   r   r   r   r	  r%  r&  r0  r8  r@  r   rg  r   r   	frozensetru  r4   r4   r4   r5   <module>   s   8
Gp  rF  *6 k,,2 +B*