
    BVhz                     *   d Z ddlmZmZmZmZmZmZ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'dZ(dZ) e*dg      Z+ e*g d      Z,dede-fdZ.deej^                     fdZ0 G d dejb                        Z2deeef   fdZ3 G d  d!ejh                        Z5d"ed#ef   defd$Z6 e%d%g&      d"ed#ef   defd'       Z7d"ed#ef   defd(Z8y))*zBOutsideCompilation, TPUReplicateContext, and supporting functions.    )AnyCallableListOptionalTextTupleUnion)logging)attr_value_pb2)device_util)distribute_lib)device)errors)
func_graph)ops)	array_ops)control_flow_ops)	variables)device_assignment)tpu_ops)core)compat)	tf_export   _tpu_replicate_xla_outside_compilation_xla_map_outside_compilationPlaceholder)	AudioSummaryAudioSummaryV2HistogramSummaryImageSummaryMergeSummaryPrintScalarSummaryTensorSummaryTensorSummaryV2strategyreturnc                 r    d }| j                   } ||      xs t        t        ||j                              S )Nc                 8    | j                   j                  d      S )NTPUStrategy)__name__
startswith)ks    U/home/dcms/DCMS/lib/python3.12/site-packages/tensorflow/python/tpu/tpu_replication.py<lambda>z!is_tpu_strategy.<locals>.<lambda>@   s    1::00?     )	__class__anymap	__bases__)r(   is_tpu_stratclzs      r0   is_tpu_strategyr9   ?   s2    ?,#	c		Cc#lCMM"BCCr2   c                      t        j                         sy t        j                         } t        |       sy | j                  j
                  S N)r   has_strategyget_strategyr9   extended_device_assignment)r(   s    r0    _enclosing_tpu_device_assignmentr@   E   s<    		$	$	&((*(		"				-	--r2   c                   j    e Zd ZdZdededej                  f fdZ	 	 d dedede	e
ej                     e
ej                     f   ded	ed
ej                  fdZd!dZdej                  defdZdej                  defdZ	 d"dee   fdZd Zd! fdZd
e
e   fdZdej                  d
ee
ej                     e
ej                     f   fdZdej                  d
dfdZdej                  d
ej                  fdZdej                  fdZed        Zed        Z d
ej                  fdZ!d Z" xZ#S )#TPUReplicateContextah  A `ControlFlowContext` for nodes inside a TPU computation.

  The primary role of `TPUReplicateContext` is to mark operators inside a
  tpu.replicate() computation with the attribute "_tpu_replicate=XYZ", where XYZ
  is a unique name.

  We use a `ControlFlowContext` to perform the annotation since it integrates
  with Tensorflow constructs like ResourceVariables. For example, if a
  `ResourceVariable` is constructed inside a tpu.replicate() block, the
  `ResourceVariable` implementation can use
  `with ops.control_dependencies(None)` to build the variable's definition
  outside the replicated computation.
  namenum_replicaspivotc                 ^   t         t        |           || _        d| _        d| _        d| _        d| _        d| _        d| _	        d| _
        g | _        g | _        || _        t        j                  t!        j"                  | j                              | _        g | _        || _        i | _        y)a  Builds a new TPUReplicateContext.

    Args:
      name: a unique name for the context, used to populate the `_tpu_replicate`
        attribute.
      num_replicas: an integer that gives the number of replicas for the
        computation.
      pivot: a pivot node. Nodes in the TPUReplicateContext 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.
    NFr   s)superrB   __init___num_replicas_outer_device_function_stack_oc_dev_fn_stack_outside_compilation_cluster_is_map_outside_compilation_outside_compilation_v2_context_outside_compilation_counter_in_gradient_colocation_gradient_colocation_stack_host_compute_core_namer   	AttrValuer   as_bytes_tpu_replicate_attr_unsupported_ops_pivot_replicated_vars)selfrC   rD   rE   r3   s       r0   rJ   zTPUReplicateContext.__init__^   s     

t-/%D(,D% D(,D%',D$+/D(()D%#'D &(D# DDJ-77
//$**
% D DDKDr2   	handle_idvars_is_mirrored	is_packedr)   c           	         t               }| j                  j                  |      }||S ||st        j                  j                  |d   j                        j                  }|D 	ci c]"  }	t        j                  |	j                        |	$ }
}	g }t        |j                        D ]v  }t        |j                        D ]C  }t        j                  |j                  |||            }||
v s/|j                  |
|           ] t        dj!                  |             n|}t#               \  }}|j%                         5  t'        |d   t(        j*                        r|D 	cg c]  }	|	j,                   }}	|j/                         }|j1                  | j2                         t5        j6                  ||dz   ||      }|j1                  |       ddd       || j                  |<   |S c c}	w c c}	w # 1 sw Y   $xY w)a  Returns a variable handle for replicated TPU variable 'var'.

    This is a method used by an experimental replicated variable implementation
    and is not intended as a public API.

    Args:
      name: The common name of the variable.
      handle_id: Unique ID of the variable handle, used as the cache key.
      vars_: The replicated TPU variables or handles.
      is_mirrored: Whether the variables are mirrored, which guarantees the
        values in each replica are always the same.
      is_packed: Whether the replicated variables are packed into one variable.

    Returns:
      The handle of the TPU replicated input node.
    Nr   )replicalogical_corejobzSFailed to find a variable on any device in replica {} for current device assignmentz/handle)rC   is_mirrored_variabler`   )r@   r[   getpydev
DeviceSpecfrom_stringr   rd   r   canonicalizerangerD   num_cores_per_replica
tpu_deviceappend
ValueErrorformat _enclosing_tpu_context_and_graph
as_default
isinstancer   Variablehandle_get_control_flow_context_set_control_flow_contextouter_contextr   tpu_replicated_input)r\   rC   r]   r^   r_   r`   r   ru   job_namevdevices_to_varsreplicated_vars
replica_idrc   r   _graphsaved_contexts                     r0   get_replicated_var_handlez-TPUReplicateContext.get_replicated_var_handle~   s   . 9: ""&&y1Fm$Y !!--eAhoo>BBhHMN111!((;Q>NoNo/<<= *!"3"I"IJ 	L++**$<X + OP& &""?6#:;	 **0&*<  o 01HAu				 5 
OA&	(:(:	;-<=188==557m%%d&8&89++
i*	f
 %%m45  (.D)$MW O> >5 5s%   ('G)"G3#G.6AG3.G33G<Nc                 ^   | j                   rdj                  d | j                   d t         D              }t        j                  dt        | j                         |       t        | j                         t        kD  r1t        j                  dt        | j                         t        z
         y y y )N
c              3   V   K   | ]!  }d |j                   d|j                  d # yw)z  z ()N)typerC   ).0ops     r0   	<genexpr>zDTPUReplicateContext.report_unsupported_operations.<locals>.<genexpr>   s"      6/1"''
*6s   ')z$%d unsupported operations found: 
%sz... and %d more)rY   join_MAX_WARNING_LINESr
   warninglen)r\   op_strs     r0   report_unsupported_operationsz1TPUReplicateContext.report_unsupported_operations   s    yy 6


 3!3
46 6f oo=$//0&:	T"" 
"
#)T2236HH	K
# r2   r   gradient_uidc                    |4t        j                         j                  l	 |j                  t              j                  d      }|j                  d      }|d   dz   |z   }t        |      | _	        | j                  j                          y | j                  j                  |       | j                  s	 |j                  t              j                  d      }| j                  rt        d      |dk(  rt        d      || _        |j                  d      }|d   dz   |z   }| j!                  |       y y y # t        $ r Y y w xY w# t        $ r Y y w xY w)Nascii.r   z>Cannot nest gradient colocation operations outside compilation__unsupported__z;No gradient_uid calling gradient within outside_compilation)cluster)r   get_default_graph_control_flow_contextget_attr_OUTSIDE_COMPILATION_ATTRdecodero   splitOutsideCompilationV2ContextrP   EnterrS   rn   rN   rR   NotImplementedError_EnterOutsideCompilationScope)r\   r   r   outside_attrpartsr   s         r0   EnterGradientColocationz+TPUReplicateContext.EnterGradientColocation   se   	~				 	6	6	>	%>?FFwO, ""3'(S.<//J0,,,224
%%,,R0..!	%>?FFwO,))%P  ..%MO O( *,$
&$$S)%!HsN\1'

,
,W
,
=? /#   	
	T  	
	s$   $D9 6B E 9	EE	EEc           	      ,   |t        j                         j                  | j                  J y | j                  "| j                  j	                          d | _        y | j
                  s1t        j                  |j                  |dd|j                   z         | j
                  j                         }||u r'|| j                  u rd | _        | j                          y y t        j                  |j                  |dd| d|j                   z         y )Nz"Badly nested gradient colocation: zempty stack when popping Op z"Badly nested gradient colocation, z	expected z, got )r   r   r   rP   ExitrS   r   InternalErrornode_defrC   poprR   _ExitOutsideCompilationScope)r\   r   r   last_ops       r0   ExitGradientColocationz*TPUReplicateContext.ExitGradientColocation  s   	~				 	6	6	> 33;;;		-	-	9 	,,113/3,,,""KK1-bggY78
 	

 //335g	w---)-$
&

+
+
- . ""KK1	y12
 	
1 r2   r   c                 t    G d dt               }| j                  rt        d      |r|| _        n/t        | j                        | _        | xj                  dz  c_        |rd| _        t        j                         } |       }|j                  |       t        j                  j                  |j                        }|j                  dk(  rJ|j                  >| j                  j!                  | j                  dz   t        |j                        z          |j"                  | _        | j&                  |_        y )Nc                   B    e Zd ZdZd Zed        Zed        Zd Zd Z	y)ATPUReplicateContext._EnterOutsideCompilationScope.<locals>.FakeOpzA helper class to determine the current device.

      Supports only the type and device set/get methods needed to run the
      graph's _apply_device_function method.
      c                     d| _         y )N _devicer\   s    r0   rJ   zJTPUReplicateContext._EnterOutsideCompilationScope.<locals>.FakeOp.__init__9  s	    r2   c                      y)NFakeOp r   s    r0   r   zFTPUReplicateContext._EnterOutsideCompilationScope.<locals>.FakeOp.type<  s    r2   c                     | j                   S r;   r   r   s    r0   r   zHTPUReplicateContext._EnterOutsideCompilationScope.<locals>.FakeOp.device@  s    ||r2   c                 r    t        |t        j                        r|j                         | _        y || _        y r;   )rs   rg   rh   	to_stringr   )r\   r   s     r0   _set_devicezMTPUReplicateContext._EnterOutsideCompilationScope.<locals>.FakeOp._set_deviceD  s)    fe../))+$,$,r2   c                     || _         y r;   r   )r\   
device_strs     r0   _set_device_from_stringzYTPUReplicateContext._EnterOutsideCompilationScope.<locals>.FakeOp._set_device_from_stringJ  s	    !r2   N)
r-   
__module____qualname____doc__rJ   propertyr   r   r   r   r   r2   r0   r   r   2  s>    
     "r2   r   z(Cannot nest outside_compilation clusters   TTPU_REPLICATED_CORE:)objectrN   r   strrQ   rO   r   r   _apply_device_functionsrg   rh   ri   r   device_typedevice_indexrT   rn   _device_function_stackrM   rL   )r\   r   is_map_outside_compilationr   r   fake_opr   s          r0   r   z1TPUReplicateContext._EnterOutsideCompilationScope/  s   " "6 (( JKK*1d'*-d.O.O*Pd'
''1,'!)-d&!!#EhG	!!'*))'..9F33'
$$T%F%F%L%()<)<%=&> ?!88D#'#D#DE r2   c                     | j                   st        d      d | _         d| _        t        j                         }| j
                  |_        y )Nz=Attempted to exit outside_compilation scope when not in scopeF)rN   ro   rO   r   r   rM   r   )r\   r   s     r0   r   z0TPUReplicateContext._ExitOutsideCompilationScopea  sI    ,,
IK K(,D%',D$!!#E#'#8#8E r2   c                     | j                   s3t        j                         }|j                  j	                         | _         t
        t        |           y r;   )rL   r   r   r   copyrI   rB   r   )r\   r   r3   s     r0   r   zTPUReplicateContext.Enterj  sA    ,, ##%e*/*F*F*K*K*Md'	
t*,r2   c                     | j                   S r;   )rT   r   s    r0   HostComputeCorez#TPUReplicateContext.HostComputeCoret  s    """r2   c                    g }g }|j                   D ]R  }d}|j                         }||| k(  rd}n|j                  }||r|j                  |       B|j                  |       T |j	                          |j                  |       ||fS )z2Remove any external control dependency on this op.FT)control_inputsrv   _outer_contextrn   _remove_all_control_inputs_add_control_inputs)r\   r   internal_control_inputsexternal_control_inputsxis_internal_opctxts          r0   _RemoveExternalControlEdgesz/TPUReplicateContext._RemoveExternalControlEdgesw  s     !  *n((*d4<.
""	 
 
&&q)&&q)* !!#23"$;;;r2   c                 >   |j                   t        v r+t        j                  d|j                   |j                         |j                   t
        v r| j                  j                  |       t        d |j                  D              rt        d|j                   d      t        |j                  j                  v r'd|j                  j                  vrt        d| d      |j                  t        | j                          | j"                  rG|j                  t$        t'        j(                  t+        j,                  | j"                                     | j.                  r*|j                  t0        t'        j(                  d	             | j2                  d
kD  s| j"                  s6|j4                  j7                  |       |j4                  j9                  |       | j;                  |      \  }}|j                  s"|sz|j=                  | j?                                nZtA        tC        |j                              D ]9  }|j                  |   }| jE                  |      }||us(|jG                  ||       ; |rtI        jJ                  d       5  | jM                          |D cg c]:  }|jN                  r,tQ        jR                  |jN                  d         jT                  < }}| jW                          d d d        |jY                  |       |jN                  D cg c]  }|j                   }}| }|*|jZ                  j]                  |       |j^                  }|*| j^                  r| j^                  ja                  |       y y c c}w # 1 sw Y   xY wc c}w )NzlOperation of type %s (%s) is not supported on the TPU. Execution will fail if this op is used in the graph. c              3   H   K   | ]  }|j                   j                    y wr;   )dtype_is_ref_dtype)r   r   s     r0   r   z,TPUReplicateContext.AddOp.<locals>.<genexpr>  s     
4Q177  
4s    "zQNon-resource Variables are not supported inside TPU computations (operator name: r   _clonedz)TPU computations cannot be nested on op (rG   Tbr   r   )1r   _DENYLISTED_OPSr
   errorrC   _UNSUPPORTED_OPSrY   rn   r4   inputsr   _TPU_REPLICATE_ATTRr   attrro   	_set_attrrX   rN   r   r   rV   r   rW   rO   _MAP_OUTSIDE_COMPILATION_ATTRrK   r   prevent_feedingprevent_fetchingr   _add_control_inputGetControlPivotrk   r   AddValue_update_inputr   control_dependenciesr   outputsr   identityr   r   r   _valuesupdater   
AddInnerOp)	r\   r   r   r   indexr   real_xoutput_namescontexts	            r0   AddOpzTPUReplicateContext.AddOp  s   	ww/!mmBCE77
''
 
ww""
""2&

4"))
44WWIQ() ) 	r{{///)))B2$aHIILL$d&>&>?((ll
#

"
" A ABDE ''ll
'

"
"T
* AT%F%F 	hhr"hh#
 !% @ @ D99$
d2245 RYY( *%IIeq!?


5&
)	*  ##D) 

 -#
yy qyy|,//#
 #

 			 	45 %'JJ/qAFF/L/G

oo\*&&g 
 
$$R( '#
  0s$   N%?N	$NN	NNvalc                    | j                   s|S |j                  | j                  v r+| j                  j	                  |j                        }||S |S |}| j                  j                  |j                         | j                   r@| j                   j                  |      }| j                  j                  |j                         || j                  |j                  <   |S )zCAdd `val` to the current context and its outer context recursively.)r   rC   r   _external_valuesrf   addr   )r\   r   results      r0   r   zTPUReplicateContext.AddValue  s    j
xx4<<$$((2fNS..FLLSXX""++C0f
llv{{#&,D#((#Mr2   c                 v    | j                  |       | j                  r| j                  j                  |       y y r;   )r   r   r   r\   r   s     r0   r   zTPUReplicateContext.AddInnerOp  s/    JJrN
$$R( r2   c                      y r;   r   r   s    r0   
grad_statezTPUReplicateContext.grad_state  s     r2   c                 X    | j                         r| j                         j                  S y)z0Forwards to the enclosing while context, if any.F)GetWhileContext	back_propr   s    r0   r  zTPUReplicateContext.back_prop  s(     !!#---r2   c                     | j                   S r;   )rZ   r   s    r0   r   z#TPUReplicateContext.GetControlPivot  s    ;;r2   c                      y)NTr   r   s    r0   RequiresUniqueFunctionRetracingz3TPUReplicateContext.RequiresUniqueFunctionRetracing  s     r2   )FF)r)   N)NF)$r-   r   r   r   r   intr   	OperationrJ   r	   r   
core_typesTensorr   rt   boolr   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r  r  r   r  __classcell__)r3   s   @r0   rB   rB   O   s   4 s 3== J 5:27N&*N+/N (-T*2C2C-D-1)2D2D-E.F (GN
 .2N ,0N =G<M<MN`
K4 4T 4l
s}} 
D 
@ HM0Ed^0Ed9-#tDz #<
--<!$s}}"5tCMM7J"JK<4Q)cmm Q) Q)f*++ 
0A0A ()3== )
    s}} r2   rB   c                      t        j                         } | E| j                         }|#t        |t              r|| fS |j
                  }|#t        | dd      } | Et        d      )z9Returns the TPUReplicateContext and its associated graph.Nouter_graphziget_replicated_var_handle() called without TPUReplicateContext. This shouldn't happen. Please file a bug.)r   r   rv   rs   rB   rx   getattrro   )r   context_s     r0   rq   rq     s~    



!%..0H

	H1	2''h 
 E=$/E 	 	  	 r2   c                       e Zd ZdZddefdZdej                  ddfdZdej                  ddfdZ	dd	Z
dej                  ddfd
Zy)r   zThe context for outside compilation in Tensorflow 2.0.

  Every op added in this context will be assigned an _xla_outside_compilation
  attribute.
  rC   c                 ^    t         j                  j                  |        || _        || _        y r;   )r   ControlFlowContextrJ   rU   rO   )r\   rC   r   s      r0   rJ   z$OutsideCompilationV2Context.__init__.  s%    ''006DJ'AD$r2   r   r)   Nc                 t    | j                   r| j                   j                  |       | j                  |       y r;   )r   r   #_set_outside_compilation_attributesr  s     r0   r   z!OutsideCompilationV2Context.AddOp3  s-    
#,,R0r2   c                 t    | j                   r| j                   j                  |       | j                  |       y r;   )r   r   r  r  s     r0   r   z&OutsideCompilationV2Context.AddInnerOp8  s-    
$$R(,,R0r2   c                     t         r;   )r   )r\   context_defexport_scopes      r0   to_control_flow_context_defz7OutsideCompilationV2Context.to_control_flow_context_def=  s    
r2   c                     |j                  t        t        j                  t	        j
                  | j                                     | j                  r+|j                  t        t        j                  d             y y )NrG   Tr   )	r   r   r   rV   r   rW   rU   rO   r   r  s     r0   r  z?OutsideCompilationV2Context._set_outside_compilation_attributes@  sX    LL!  6??4::#>? ''ll
')A)AD)I (r2   )Fr;   )r-   r   r   r   r   rJ   r   r  r   r   r  r  r   r2   r0   r   r   '  s_    B4 B
1cmm 1 1
13== 1T 1
	CMM 	d 	r2   r   computation.c                    |g n|}t        j                         }t        |t        j                        rt	 t               \  }}t        |j                        }|j                  dz   |_
        t        ||       }|j                          |g n|} ||i |}	|j                          |	S |j                         }
|
}|r1t        |t              r|j!                  |        |j"                  }|r1 ||i |}	|j                         }|
|urt%        d      |
}|r/t        |t              r|j'                          |j"                  }|r/|	S # t        $ r  t        j                  d        ||i |cY S w xY w)z~Tags ops in `computation` with outside compilation attributes for ordinary `outside_compilation` or `map_outside_compilation`.zOutside compilation attempted outside TPUReplicateContext scope. As no enclosing TPUReplicateContext can be found, returning the result of `computation` as is.r   )r   zYControl-flow context cannot be different at start and end of an outside_compilation scope)r   r   rs   r   	FuncGraphrq   ro   r
   r   r   rQ   r   r   r   rv   rB   r   rx   r   r   )is_mapr!  argskwargsr   tpu_contextr   outside_compilation_nameoutside_compilation_contextretvalinitial_contextr   final_contexts                r0   outside_compilation_implr-  M  s    |$



!%
 z++,*79nk1  #;#K#KL0014 ,
 #> V#  %%'24D$)&)F$$&M 335/''./++v+N##G 	
 ''& 113-M)
	$  ''./**,##G 	
 
-c  *oo9
 $)&))*s   E
 
&E32E3ztpu.outside_compilation)v1c                 "    t        d| g|i |S )ah  Builds part of a computation outside any current TPU replicate scope.

  `tf.tpu.outside_compilation()` is used to run ops in `computation` on CPU
  instead of running on TPU. For example, users can run ops that are not
  supported on TPU's (e.g. tf.summary.write()) by explicitly placing those
  ops on CPU's. Below usage of outside compilation will place ops in
  `computation_with_string_ops` on CPU.

  Example usage:

  ```python
  def computation_with_string_ops(x):
    # strings types are not supported on TPU's and below ops must
    # run on CPU instead.
    output = tf.strings.format('1{}', x)
    return tf.strings.to_number(output)

  def tpu_computation():
    # Expected output is 11.
    output = tf.tpu.outside_compilation(computation_with_string_ops, 1)
  ```

  Outside compilation should be called inside TPUReplicateContext. That is,
  `tf.tpu.outside_compilation()` should be called inside a function that is
  passed to `tpu.split_compile_and_replicate()` -- this is implied when
  outside compilation is invoked inside a function passed to TPUStrategy
  `run()`. If invoked outside of TPUReplicateContext,
  then this simply returns the result of `computation`, and therefore,
  would be a no-op. Note that outside compilation is different from
  `tf.distribute.experimental.TPUStrategy.merge_call()` as logic in
  outside compilation is replicated and executed separately for each
  replica. On the other hand, `merge_call()` requires a `merge_fn`
  to aggregate the inputs from different replicas and is executed only
  once.

  For variables placed in TPU device, which includes variables created inside
  TPUStrategy scope, outside compilation logic must not include variable
  read/write. For variables placed on host, variable read/write is only allowed
  if the variable is not accessed by any other ops in the TPU computation.
  Variable read/write from outside compilation cluster is not visible from TPU
  computation and vice versa. Therefore, if outside compilation logic contains
  such host variables read/write ops and if the variables are accessed by TPU
  computation as well, then this may lead to deadlock.

  Internally, `tf.tpu.outside_compilation()` adds outside compilation
  attributes to all ops in `computation`. During a later passes ops with outside
  compilation attributes are moved to a host-side graph. Inputs to this extract
  host-side graph are sent from TPU computation graph to host graph via a pair
  of XlaSendToHost and XlaRecvFromHost ops. Note that using
  `tf.tpu.outside_compilation()` may result in tensor transfer between TPU and
  CPU, leading to non-trivial performance impact.

  Args:
    computation: A Python function that builds the computation to place on the
      host.
    *args: the positional arguments for the computation.
    **kwargs: the keyword arguments for the computation.

  Returns:
    The Tensors returned by computation.
  Fr-  r!  r%  r&  s      r0   outside_compilationr2    s    B 
"%	Ft	Fv	FFr2   c                 "    t        d| g|i |S )a#  Maps `computation` onto shards and puts it outside any current TPU replicate scope.

  `experimental_map_outside_compilation(f, x)` maps `f` onto the shards
  of `x`, where `x` is split-sharded. Each invocation of `f` on a split occurs
  on the CPU that's associated with the TPU that owns the split.

  Example usage:

  ```python
  def normalize_each_split(split):
    return split - tf.math.reduce_mean(split)

  def tpu_computation(x):
    x_split = strategy.experimental_split_to_logical_devices(
                x, [num_cores_per_replica, 1])
    y = experimental_map_outside_compilation(
          normalize_each_split, x_split)
    y_split = strategy.experimental_split_to_logical_devices(
                x, [num_cores_per_replica, 1])
    return y_split
  ```

  `experimental_map_outside_compilation` should be called inside
  TPUReplicateContext. That is, `outside_compilation()` should be called
  inside a function that is passed to `tpu.split_compile_and_replicate()` --
  this is implied when outside compilation is invoked inside a function passed
  to TPUStrategy `run()`. It is invalid to invoke outside of
  TPUReplicateContext.

  `experimental_map_outside_compilation` should input and output tensors that
  are located on the TPU.

  Internally, `experimental_map_outside_compilation()` adds outside
  compilation attributes to all ops in `computation` and moves outside-compiled
  ops to a host-side graph. This is similar to `tf.tpu.outside_compilation()`.
  Send/recv ops from/to the TPU send each split directly to the TPU's host.

  Args:
    computation: A Python function that builds the computation to place on the
      host.
    *args: the positional arguments for the computation.
    **kwargs: the keyword arguments for the computation.

  Returns:
    The Tensors returned by computation.
  Tr0  r1  s      r0   $experimental_map_outside_compilationr4    s    b 
"$	Ed	Ef	EEr2   N)9r   typingr   r   r   r   r   r   r	   abslr
   tensorflow.core.frameworkr   tensorflow.python.distributer   r   tensorflow.python.frameworkr   rg   r   r   r   tensorflow.python.opsr   r   r   tensorflow.python.tpur   device_assignment_libtensorflow.python.tpu.opsr   tensorflow.python.typesr   r  tensorflow.python.utilr    tensorflow.python.util.tf_exportr   r   r   r   r   	frozensetr   r   r  r9   DeviceAssignmentr@   XLAControlFlowContextrB   rq   r  r   r-  r2  r4  r   r2   r0   <module>rD     sn    I D D D  4 4 7 7 . 2 + + 2 + L - 6 ) 6 & 6  >     
 
 Dc Dd D.#445.D*@@ DN%S/ """2"E"E "L>!#s(+>>B ()*@G#s(#@G@G +@GF1F#s(#1F1Fr2   