o
    ?eZ                     @   s|  d Z ddlZddlmZ ddlmZ ddlmZ ddlmZ ddl	m
Z
 ddl	mZ dd	lmZ dd
lmZ ddlmZ ddlmZ ddlmZ ddlmZ ddlmZ ddlmZ ddlmZ ddlmZ ddlmZ dZdZ e!dgZ"e!g dZ#ededdddd0ddZ$G dd dej%Z&d0d d!Z'd"d# Z(d$d% Z)d&d' Z*ej+d(d) Z,G d*d+ d+e-Z.d,d- Z/d.d/ Z0dS )1z>xla is an experimental library that provides XLA support APIs.    N)xla_ops)xla_ops_grad)attr_value_pb2)summary_op_util)context)def_function)ops)	array_ops)control_flow_ops)variable_scope)
tf_logging)compat)nest)
tf_inspect)collections_abc)
deprecated)	tf_exportZ_xla_compile_id   ZPlaceholder)	ZAudioSummaryZAudioSummaryV2ZHistogramSummaryZImageSummaryZMergeSummaryZPrintZScalarSummaryZTensorSummaryZTensorSummaryV2zxla.experimental.compilezXxla.experimental.compile is deprecated. Consider using `@tf.function(jit_compile=True)`.T)Z	warn_oncec                    s,   t  rtj fdd}| S t S )a  Builds an operator that compiles and runs `computation` with XLA.

  NOTE: In eager mode, `computation` will have `@tf.function` semantics.

  Args:
    computation: A Python function that builds a computation to apply to the
      input. If the function takes n inputs, 'inputs' should be a list of n
      `Tensor`s.

      `computation` may return a list of `Tensor`s and `Operation`s.
      `Tensor`s must come before `Operation`s in the returned list.

      All `Operation`s returned from `computation` will be executed when
      evaluating any of the returned output tensors.
    inputs: A list of inputs or `None` (equivalent to an empty list). Each input
      can be a nested structure containing values that can be converted to
      `Tensor`s. Note that passing an N-dimension list of compatible values will
      result in an N-dimension list of scalar `Tensor`s rather than a single
      Rank-N `Tensor`. If you need a different behavior, convert parts of
      `inputs` to `Tensor`s with `tf.convert_to_tensor`.

  Returns:
    List of `Tensor`s corresponding to the `Tensor`s from
      the output of `computation` i.e. the same return value as if
      computation(*inputs) is called directly, with the following exceptions:
      * None output: a NoOp would be returned with a control dependency on
         `computation`.
      * Single value output: a tuple containing the value would be returned.
      * Operation-only outputs: a NoOp would be returned with a control
      dependency on `computation`.
      TODO(b/121383831): Investigate into removing these special cases.

  Raises:
    RuntimeError: When eager execution is enabled.

  Known issues:
    When a tf.random operation is built with XLA, the implementation doesn't
      pass the user provided seed to the XLA compiler. As such, the XLA compiler
      generates a random number and uses it as a seed when compiling the
      operation. This implementation causes a violation of the Tensorflow
      defined semantics in two aspects. First, changing the value of the user
      defined seed doesn't change the numbers generated by the operation.
      Second, when a seed is not specified, running the program multiple times
      will generate the same numbers.
  c                      s
   t  S N)_compile_internal computationinputsr   c/home/www/facesmatcher.com/pyenv/lib/python3.10/site-packages/tensorflow/python/compiler/xla/xla.pyxla_compile_wrappers   s   
z$compile.<locals>.xla_compile_wrapper)r   Zexecuting_eagerlyr   functionr   )r   r   r   r   r   r   compile>   s
   3
r   c                       s`   e Zd ZdZ f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  ZS )XLACompileContexta  A `ControlFlowContext` for nodes inside an XLA computation cluster.

  THIS IS ONLY FOR TENSORFLOW INTERNAL IMPLEMENTATION, DO NO USE DIRECTLY.

  The primary role of `XLACompileContext` is to mark operators inside a
  xla.compile() computation with attribute "_xla_compile_id=XYZ", where XYZ is
  a unique name.

  `ControlFlowContext` is used to perform the annotation since it integrates
  with Tensorflow constructs like ResourceVariables. For example, if a
  `ResourceVariable` is constructed inside a xla.compile() block, the
  `ResourceVariable` implementation can use
  `with ops.control_dependencies(None)` to build the variable's definition
  outside the compiled computation.
  c                    s0   t t|   || _t|| _g | _|| _dS )a  Builds a new XLACompileContext.

    Args:
      name: a unique name for the context, used to populate the
        `_xla_compile_id` attribute.
      pivot: a pivot node. Nodes in the XLACompileContext that do not have any
        inputs will have a control dependency on the pivot node. This ensures
        that nodes are correctly included in any enclosing control flow
        contexts.
    N)	superr   __init___namer   as_bytes_name_as_bytes_unsupported_ops_pivot)selfnamepivot	__class__r   r   r       s
   
zXLACompileContext.__init__c                 C   sh   | j r0ddd | j d t D }tdt| j | t| j tkr2tdt| j t  d S d S d S )N
c                 S   s   g | ]
}d |j |jf qS )z	  %s (%s))typer'   ).0opr   r   r   
<listcomp>   s    zCXLACompileContext.report_unsupported_operations.<locals>.<listcomp>z$%d unsupported operations found: 
%sz... and %d more)r$   join_MAX_WARNING_LINESloggingwarninglen)r&   Zop_strr   r   r   report_unsupported_operations   s   

z/XLACompileContext.report_unsupported_operationsc                 C   sx   g }g }|j D ]'}d}| }|dur!|| krd}q!|j}|dus|r)|| q|| q|  || ||fS )z2Remove any external control dependency on this op.FNT)Zcontrol_inputsZ_get_control_flow_context_outer_contextappendZ_remove_all_control_inputs_add_control_inputs)r&   r.   internal_control_inputsexternal_control_inputsxZis_internal_opZctxtr   r   r   _RemoveExternalControlEdges   s"   

z-XLACompileContext._RemoveExternalControlEdgesc           	      C   s  |j tv rtd|j |j |j tv r| j| tdd |j	D r*t
d|j t|jjv r7td|j |ttj| jd |j| |j| | |\}}|j	sa|s`|| j ntt|j	D ]}|j	| }| |}||ur~||| qh|rtd |   dd	 |D }|    W d   n1 sw   Y  |!| d
d	 |j"D }| }|dur|j#$| |j%}|dus| j%r| j%&| dS dS )zFCreate op in XLACompileContext and notifies outer context recursively.zhOperation of type %s (%s) is not supported in XLA. Execution will fail if this op is used in the graph. c                 s   s    | ]}|j jV  qd S r   )ZdtypeZ_is_ref_dtyper-   r;   r   r   r   	<genexpr>   s    z*XLACompileContext.AddOp.<locals>.<genexpr>zTNon-resource Variables are not supported inside XLA computations (operator name: %s)z?XLA compiled computations cannot be nested, (operator name: %s))sNc                 S   s$   g | ]}|j rt|j d  jqS )r   )outputsr	   identityr.   r=   r   r   r   r/      s    z+XLACompileContext.AddOp.<locals>.<listcomp>c                 S   s   g | ]}|j qS r   r'   r=   r   r   r   r/      s    )'r,   _DENYLISTED_OPSr2   errorr'   _UNSUPPORTED_OPSr$   r7   anyr   NotImplementedError_XLA_COMPILE_ATTRZnode_defattr
ValueErrorZ	_set_attrr   Z	AttrValuer#   graphZprevent_feedingZprevent_fetchingr<   Z_add_control_inputr%   ranger4   AddValueZ_update_inputr   control_dependenciesEnterExitr8   r@   _valuesupdater6   
AddInnerOp)	r&   r.   r9   r:   indexr;   Zreal_xZoutput_namesr   r   r   r   AddOp   sj   





	zXLACompileContext.AddOpc                 C   sl   |j | jv r| j|j }|du r|S |S |}| j|j  | jr.| j|}| j|j  || j|j < |S )zCAdd `val` to the current context and its outer context recursively.N)r'   rQ   Z_external_valuesgetaddr6   rM   )r&   valresultr   r   r   rM     s   zXLACompileContext.AddValuec                 C   s$   |  | | jr| j| d S d S r   )rU   r6   rS   )r&   r.   r   r   r   rS     s   
zXLACompileContext.AddInnerOpc                 C   s   d S r   r   r&   r   r   r   
grad_state!  s   zXLACompileContext.grad_statec                 C   s   |   r	|   jS dS )z0Forwards to the enclosing while context, if any.F)ZGetWhileContext	back_proprZ   r   r   r   r\   )  s   
zXLACompileContext.back_prop)__name__
__module____qualname____doc__r    r5   r<   rU   rM   rS   propertyr[   r\   __classcell__r   r   r)   r   r   |   s    I
r   c                 C   s  |du rg }t |tjstdt|}dd |D }t d}t	j
|d d}t||d}z^|  d	d t|D }tj||d
}t }|j}|d t  | | }	W d   n1 sdw   Y  || t|	}
|
r{t|	\}}nt|	\}}|| W |  |  n	|  |  w |st	j|ddS dd t|D }t| dd t|D }W d   n1 sw   Y  |
stj|	|d
}|S )aE  Builds graph operators that compiles and symbolically executes computation.

  Args:
    computation: A Python function that builds the computation to compile and
      execute.
    inputs: A list of inputs or `None` (equivalent to an empty list). Each input
      can be a nested structure containing values that are convertible to
      tensors. Note that passing an N-dimension list of compatible values will
      result in a N-dimension list of scalar tensors rather than a single Rank-N
      tensors. If you need different behavior, convert part of inputs to tensors
      with `tf.convert_to_tensor`.

  Returns:
    Same data structure as if computation(*inputs) is called directly with some
    exceptions for correctness. Exceptions include: 1) None output 2) Single
    value output 3) Operation-only outputs
  Raises:
    ValueError: If any element in computation outputs is neither an operations
      or a value that can be converted to tensor.
    ValueError: If computation outputs is non-flat and contains any Operations.
    TypeError: If `inputs` is not a list or tuple.
  Nzinputs must be a listc                 S   s   g | ]}t |qS r   )r   convert_to_tensorr=   r   r   r   r/   Q  s    z%_compile_internal.<locals>.<listcomp>Zclusterz/pivotrB   )r'   r(   c                 S   $   g | ]\}}t j|d |dqS )zinput_{}rB   )r	   rA   format)r-   ir;   r   r   r   r/   [      )Z	structureZflat_sequenceTZoutput_0c                 S   rd   )zoutput{}rB   )r   Zxla_cluster_outputre   r-   rf   or   r   r   r/     rg   c                 S   s"   g | ]\}}t j|d | dqS )z	output_%drB   )r	   rA   rh   r   r   r   r/     s    )
isinstancer   Sequence	TypeErrorr   flattenr   Zget_default_graphZunique_namer
   no_opr   rO   	enumerateZpack_sequence_asr   Zget_variable_scopeZuse_resourceZset_use_resource_disable_summary_contextis_flat_postprocess_flat_outputs_postprocess_non_flat_outputsZ
ExitResultr5   rP   grouprN   )r   r   Zflat_inputsZcluster_namer(   r   Zcomputation_inputsZvscopeZsaved_use_resourcer@   Zoutputs_is_flatoutput_tensorsZcontrol_depsr   r   r   r   1  s`   






r   c                 C   sd   t | tjr | D ]}t |tjst |tjst|jdr dS qt | tjr(dS t| jdr0dS dS )au  Checks if outputs is a flat structure.

    Following structures and values are considered flat:
    1) None
    2) A single object
    3) A list or tuple of Tensors/Operations

    The only structures that this function understands are sequences,
    dictionaries and types defined using the attrs library.  E.g. this means
    that if outputs contains a single user-defined Object, it is considered to
    be flat. Errors are raised later on if that Object cannot be converted to a
    Tensor.

  Args:
    outputs: Output from `computation` inside `xla.compile`.

  Returns:
    A boolean indicates whether outputs is flat.
  Z__attrs_attrs__FT)rj   r   rk   Mappinghasattrr*   )r@   ri   r   r   r   rq     s   

rq   c              
   C   s   | du rt  } t| tjs| f} | t f7 } z	dd | D } W n ty4 } ztdt| d}~ww dd | D }dd | D }| || krMtdg }|D ]%}t	
|j
r[|j
nd |t| W d   n1 sqw   Y  qQ||fS )	zValidates flat outputs and adds back device assignments.

  Args:
    outputs: Output from `computation` inside `xla.compile`.

  Returns:
    Tensors and Operations extracted from outputs.
  Nc                 S   s&   g | ]}t |tjr|nt|qS r   )rj   r   	Operationrc   r-   ri   r   r   r   r/     s    z-_postprocess_flat_outputs.<locals>.<listcomp>oXLA computation function return values must all either be Operations or convertible to Tensors. Got error: "%s"c                 S   s   g | ]
}t |tjr|qS r   rj   r   rx   ry   r   r   r   r/         c                 S   s   g | ]
}t |tjs|qS r   r{   ry   r   r   r   r/     r|   zdXLA computation function must return zero or more Tensor values followed by zero or more Operations. )tuplerj   r   rk   r
   rn   	ExceptionrJ   strr   devicer7   r	   rA   )r@   eZoutput_operationsru   new_output_tensorstr   r   r   rr     s<   
rr   c                 C   s   g }t | D ]N}t|tjrtd|j zt|}W n ty1 } ztdt	| d}~ww t
|j
r:|j
nd |t| W d   n1 sPw   Y  q|g fS )a  Validates non-flat outputs and adds back device assignments.

  Args:
    outputs: Output from `computation` inside `xla.compile`.

  Returns:
    Tensors extracted from outputs and an empty list because Operations are not
    allowed in non-flat outputs..
  zxla.compile does not support Operation as return value in non-flat output structure. You can set returned Operations as control dependencies of returned Tensors so Operations are triggered when Tensors are evaluated. Operation found: "%s"rz   Nr}   )r   rm   rj   r   rx   rJ   r'   rc   r   r   r   r7   r	   rA   )r@   r   ri   r   r   r   r   rs     s.   rs   c                  c   s.    t j} dd t _z	dV  W | t _dS | t _w )a  Enters a context where all summary ops are skipped.

  Summaries are not yet supported in xla.compile(). So we provide this context
  manager that can skip creating summary ops. This is a temporary workaround due
  to XLA not supporting summary ops.

  Yields:
    None.
  c                   S   s   dS )NTr   r   r   r   r   <lambda>%  s    z*_disable_summary_context.<locals>.<lambda>N)r   Zskip_summary)Zoriginal_skip_summary_funcr   r   r   rp     s   
rp   c                   @   s(   e Zd ZdZdd Zdd Zdd ZdS )	_CapturedObjectz#A placeholder to capture an object.c                 C   s
   d | _ d S r   _objectrZ   r   r   r   r    0  s   
z_CapturedObject.__init__c                 C   s   | j rtd|| _ d S )NzFInternalError: _CapturedObject can capture only once. Please file bug.)r   RuntimeError)r&   ri   r   r   r   capture3  s
   
z_CapturedObject.capturec                 C   s   | j S r   r   rZ   r   r   r   rV   ;  s   z_CapturedObject.getN)r]   r^   r_   r`   r    r   rV   r   r   r   r   r   -  s
    r   c                 C   s*   |   }|sdS | }|du rtd|S )z3Retrieves the Scaffold from `captured_scaffold_fn`.Nz?TPUEstimatorSpec.scaffold_fn returns None, which is not allowed)rV   rJ   )Zcaptured_scaffold_fnZscaffold_fnZscaffoldr   r   r   _get_scaffold?  s   r   c           	      C   s   dd }|}|dur||j 7 }t| }t|j}|jdu r!d}nt|j}|| }||k rA|dkr<|jdu r<|d|S |d|S |jdu rX||krX|dkrS|d|S |d|S dS )a  Validate the number of input arguments to an XLA function.

  Args:
    func: the Python function that will be called to generate the body of an XLA
      computation graph.
    input_arity: the number of explicit arguments supplied by the caller.
    infeed_queue: if not None, the infeed queue that will supply
      additional arguments to the function.

  Returns:
    None if function can be called with the supplied number of
      arguments, or an error string if it cannot.
  c                 S   s   d| ||dkrdf S df S )Nz%s %d argument%s   r}   r?   r   )Z	complaintZquantityr   r   r   format_error\  s
   
z3check_function_argument_count.<locals>.format_errorNr   Zexactlyzat leastzat most)Znumber_of_tuple_elementsr   
getargspecr4   argsdefaultsvarargs)	funcZinput_arityZinfeed_queuer   Znum_args_suppliedZarg_specZnum_func_argsZnum_func_defaultsZmin_func_argsr   r   r   check_function_argument_countN  s&   








r   r   )1r`   
contextlibZtensorflow.compiler.jit.opsr   r   Ztensorflow.core.frameworkr   Ztensorflow.python.distributer   Ztensorflow.python.eagerr   r   Ztensorflow.python.frameworkr   Ztensorflow.python.opsr	   r
   r   Ztensorflow.python.platformr   r2   Ztensorflow.python.utilr   r   r   Ztensorflow.python.util.compatr   Z"tensorflow.python.util.deprecationr   Z tensorflow.python.util.tf_exportr   rH   r1   setrC   rE   r   ZXLAControlFlowContextr   r   rq   rr   rs   contextmanagerrp   objectr   r   r   r   r   r   r   <module>   sT   9 
6g*4#
