
    AVh79                     ^   d 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d Zd Zd,dZ	 	 d,dZ	 	 d,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.d!Z&d" Z'd# Z(d$ Z)d% Z*d& Z+d' Z,d(Z-d)Z.d* Z/d+ Z0y)/z5Utility functions used by values.py and ps_values.py.    )distribute_lib)reduce_util)context)ops)tensor_util)control_flow_ops)math_ops)variable_scope)save_context)save_options)saveable_objectc                    |j                   j                         rj| j                  D ]Z  } |j                  j                  j                         }| j                  j                  d      d   |_        | j                  |_        \ yy)a  Update a SavedObject proto for the caller.

  If a DistributedVariable object supports this method, it will be called when
  saving with a pre-built `SavedObject` proto representing the object, plus an
  instance of `SaveOptions`. This method is then free to modify that proto
  instance.

  `DistributedVariable` with `AUTO` or `ON_WRITE` synchronization optionally
   write out information about their components to the
   `experimental_distributed_variable_components` field of a
   `SavedVariable` (depending on the `SaveOptions` variable policy).

  Args:
    var: The DistributedVariable object.
    proto: A pre-built `SavedObject` proto for this object. It is assumed this
      will be a `SavedVariable` instance.
    options: A `SaveOptions` instance.
  :r   N)	experimental_variable_policy_expand_distributed_variablesvaluesvariable,experimental_distributed_variable_componentsaddnamesplitdevice)varprotooptions	var_protos       X/home/dcms/DCMS/lib/python3.12/site-packages/tensorflow/python/distribute/values_util.pywrite_object_protor      sp    & ))GG zz $
..
E
E
I
I
K xx~~c*1-ini	$    c                 x      fd}t        j                  |d| j                  j                        }||gfS )z5Return saveable spec for AUTO and ON_WRITE variables.c                      t        j                         rj                         sy j                  } | j                  j                        S N)r   executing_eagerlyis_initializeddistribute_strategyextendedread_var)strategyprimary_varr   s    r   tensorz%get_on_write_saveable.<locals>.tensor>   sA      ";+E+E+G &&H%%c**r    r*   
slice_specr   dtyper   r   SaveSpecr.   r   r   r)   r   r*   specs   ``   r   get_on_write_saveabler3   :   sA    + 
	!	!II
!$ 
$r   c                     | j                   2t        j                  t        fdj                  D                    S t        j                  t        fd| j
                  D                    S )z3Return restore ops for AUTO and ON_WRITE variables.c              3   8   K   | ]  }t        |        y wr"   )assign_on_device).0d
packed_varr*   s     r   	<genexpr>z+get_on_write_restore_ops.<locals>.<genexpr>U   s"      ) Q
F3)s   c              3   L   K   | ]  }t        |j                  |        y wr"   r6   r   r7   vr*   s     r   r:   z+get_on_write_restore_ops.<locals>.<genexpr>Y   &       188Q
/   !$)_packed_variabler   grouptupledevicesr   )r   r*   r9   s    `@r   get_on_write_restore_opsrE   P   sp    ##*!! )'') 	)* * 
		 :: 
   r   c                 t      fd}t        j                  |d| j                  |j                        }||gfS )z&Return saveables for ON_READ variable.c                  $     j                         S r"   )_get_cross_replica)r   s   r   r*   z$get_on_read_saveable.<locals>.tensorc   s    !!##r   r+   r,   r/   r1   s   `    r   get_on_read_saveablerI   ^   sA    
$ 
	!	!II
!$ 
$r   c                    |t         j                  j                  k(  r9| j                  }t	        j
                  |j                  z  | j                        t        j                  t        fd| j                  D                    S )z)Return restore ops for ON_READ variables.c              3   L   K   | ]  }t        |j                  |        y wr"   r<   r=   s     r   r:   z*get_on_read_restore_ops.<locals>.<genexpr>z   r?   r@   )vsVariableAggregationSUMr%   r	   castnum_replicas_in_syncr.   r   rB   rC   r   )r   r*   aggregationr(   s    `  r   get_on_read_restore_opsrR   p   sr    
 B**...&&H]]6H$A$AA99&F			 :: 
   r   c                  .    t        j                         d uS r"   )r   get_update_replica_id r   r   in_replica_update_contextrV      s    		-	-	/t	;;r   Nc                 4    d }| j                  |||||      S )Nc                 &     | j                   |i |S r"   )assignr   akws      r   <lambda>z!on_write_assign.<locals>.<lambda>   s    JCJJ$8R$8 r   	update_fnvalueuse_lockingr   
read_value_update)r   r`   ra   r   rb   	assign_fns         r   on_write_assignrf      s,    8)	 
 
 r   c                 4    d }| j                  |||||      S )Nc                 &     | j                   |i |S r"   )
assign_addrZ   s      r   r]   z%on_write_assign_add.<locals>.<lambda>       (@R(@ r   r^   rc   )r   r`   ra   r   rb   assign_add_fns         r   on_write_assign_addrl      ,    @-	 
 
 r   c                 4    d }| j                  |||||      S )Nc                 &     | j                   |i |S r"   )
assign_subrZ   s      r   r]   z%on_write_assign_sub.<locals>.<lambda>   rj   r   r^   rc   )r   r`   ra   r   rb   assign_sub_fns         r   on_write_assign_subrr      rm   r   c                 t     j                   4t        j                  t         fd j                  D                    }n2t        j                  t        fd j
                  D                    }|s|S t        j                  |r|gng       5   j                         cddd       S # 1 sw Y   yxY w)zIUpdate the variable on each replica with the given assign_func and value.Nc              3   F   K   | ]  } |j                           y wr"   )rA   )r7   r8   assign_funcr`   r   s     r   r:   z(assign_on_each_device.<locals>.<genexpr>   s'      O<=K3//7O   !c              3   F   K   | ]  } |j                   |        y wr"   )r   )r7   r>   ru   r`   s     r   r:   z(assign_on_each_device.<locals>.<genexpr>   s     C!k!((Au-Crv   )	rA   r   rB   rC   _devices_valuesr   control_dependenciesrb   )r   ru   r`   rb   updates   ```  r   assign_on_each_devicer|      s    %## OADO 	OPF ##Cs{{CCEF	M
F; >>  s   B..B7c                 0   t        j                  | j                        5  t        j                         rM| j                  t
        j                  j                  k(  rt        d      t        | t        ||      cd d d        S 	 d d d        y # 1 sw Y   y xY w)NzSyncOnReadVariable does not support `assign_sub` in cross-replica context when aggregation is set to `tf.VariableAggregation.SUM`.)r   enter_or_assert_strategyr%   in_cross_replica_contextrQ   rL   rM   rN   
ValueErrorr|   assign_sub_on_devicer   r`   rb   s      r    on_read_assign_sub_cross_replicar          ..s/F/FG 6..0	B2266	6,- 	- #3(<#(*66 606 6 6   ABBc                 0   t        j                  | j                        5  t        j                         rM| j                  t
        j                  j                  k(  rt        d      t        | t        ||      cd d d        S 	 d d d        y # 1 sw Y   y xY w)NzSyncOnReadVariable does not support `assign_add` in cross-replica context when aggregation is set to `tf.VariableAggregation.SUM`.)r   r~   r%   r   rQ   rL   rM   rN   r   r|   assign_add_on_devicer   s      r    on_read_assign_add_cross_replicar      r   r   c                    t        j                  | j                        5  t        j                         r}|}| j                  t
        j                  j                  k(  r9| j                  }t        j                  ||j                  z  | j                        }t        | t        ||      cddd       S 	 ddd       y# 1 sw Y   yxY w)z:Return the value of the variable in cross replica context.N)r   r~   r%   r   rQ   rL   rM   rN   _distribute_strategyr	   rO   rP   r.   r|   r6   )r   r`   rb   r*   r(   s        r   on_read_assign_cross_replicar      s    ..s/F/FG /..0 f	B2266	6++v(E(EE"yy*"3(8&#-// /0/ / /s   BB<<Cc                 2    d }| j                  ||||      S )Nc                 &     | j                   |i |S r"   )scatter_subrZ   s      r   r]   zscatter_sub.<locals>.<lambda>       !)Br)B r   r_   r`   ra   r   rc   )r   sparse_deltara   r   scatter_sub_fns        r   r   r      )    B.		 
 
 r   c                 2    d }| j                  ||||      S )Nc                 &     | j                   |i |S r"   )scatter_addrZ   s      r   r]   zscatter_add.<locals>.<lambda>   r   r   r   rc   )r   r   ra   r   scatter_add_fns        r   r   r      r   r   c                 2    d }| j                  ||||      S )Nc                 &     | j                   |i |S r"   )scatter_mulrZ   s      r   r]   zscatter_mul.<locals>.<lambda>   r   r   r   rc   )r   r   ra   r   scatter_mul_fns        r   r   r      r   r   c                 2    d }| j                  ||||      S )Nc                 &     | j                   |i |S r"   )scatter_divrZ   s      r   r]   zscatter_div.<locals>.<lambda>   r   r   r   rc   )r   r   ra   r   scatter_div_fns        r   r   r      r   r   c                 2    d }| j                  ||||      S )Nc                 &     | j                   |i |S r"   )scatter_minrZ   s      r   r]   zscatter_min.<locals>.<lambda>  r   r   r   rc   )r   r   ra   r   scatter_min_fns        r   r   r      r   r   c                 2    d }| j                  ||||      S )Nc                 &     | j                   |i |S r"   )scatter_maxrZ   s      r   r]   zscatter_max.<locals>.<lambda>
  r   r   r   rc   )r   r   ra   r   scatter_max_fns        r   r   r   	  r   r   c                 2    d }| j                  ||||      S )Nc                 &     | j                   |i |S r"   )scatter_updaterZ   s      r   r]   z scatter_update.<locals>.<lambda>  s    ,>C,>,>,HR,H r   r   rc   )r   r   ra   r   scatter_update_fns        r   r   r     s*    H	!	 
 
 r   c                      t        j                         } | r3| j                  }t        |t              st        j                  |      }|S t        j                         }|S )z8Returns the current replica ID as an integer, or `None`.)r   get_replica_context_replica_id
isinstanceintr   constant_valuerT   )replica_context
replica_ids     r   get_current_replica_id_as_intr     sV    "668/ ,,Jj#&--j9j 
  557J	r   c                 z    t        j                  |       5  |j                  |      cd d d        S # 1 sw Y   y xY wr"   )r   r   rY   r   r   r*   s      r   r6   r6   '  s/    
zz& #??6"# # #   1:c                 z    t        j                  |       5  |j                  |      cd d d        S # 1 sw Y   y xY wr"   )r   r   ri   r   s      r   r   r   ,  1    
zz& 'v&' ' 'r   c                 z    t        j                  |       5  |j                  |      cd d d        S # 1 sw Y   y xY wr"   )r   r   rp   r   s      r   r   r   1  r   r   c                 x    t        j                         }|st        d      |j                  | urt        d      y )NzBReplica-local variables may only be assigned in a replica context.)r   r   RuntimeErrorr(   )r(   r   s     r   assert_replica_contextr   6  sJ    "668/	
LN NX-
LN N .r   c                    |t         j                  j                  k(  r/| j                  j	                  | j                  |      d   |      S t        j                  j                  |      }| j                  j                  |||      S )Nr   )destinations)
rL   rM   ONLY_FIRST_REPLICAr&   broadcast_toexperimental_local_resultsr   ReduceOpfrom_variable_aggregation	reduce_to)r(   r`   rQ   r   	reduce_ops        r   apply_aggregationr   @  s}    B**===))++E215! * # # ""<<[I)				$	$Y|	DDr   a  You must specify an aggregation method to update a {variable_type} in Replica Context. You can do so by passing an explicit value for argument `aggregation` to tf.Variable(..).e.g. `tf.Variable(..., aggregation=tf.VariableAggregation.SUM)``tf.VariableAggregation` lists the possible aggregation methods.This is required because {variable_type} should always be kept in sync. When updating them or assigning to them in a replica context, we automatically try to aggregate the values before updating the variable. For this aggregation, we need to know the aggregation method. Another alternative is to not try to update such {variable_type} in replica context, but in cross replica context. You can enter cross replica context by calling `tf.distribute.get_replica_context().merge_call(merge_fn, ..)`.Inside `merge_fn`, you can then update the {variable_type} using `tf.distribute.StrategyExtended.update()`.z{op_name} is only supported for mirrored variable (variable created within certain `tf.distribute.Strategy` scope) with NONE or `ONLY_FIRST_REPLICA` aggregation, got: {aggregation}.c                      t        j                         syt        j                         } | j                  t        j
                  j                  k7  S )a  Returns whether we're saving a non-distributed version of the model.

  It returns True iff we are in saving context and are saving a non-distributed
  version of the model. That is, SaveOptions.experimental_variable_policy is
  NONE.

  Returns:
    A boolean.
  F)r   in_save_contextget_save_optionsr   r   VariablePolicyEXPAND_DISTRIBUTED_VARIABLES)r   s    r   is_saving_non_distributedr   b  sE     
	%	%	'))+'

.
.

%
%
B
BC Dr   c                      t        j                         r9t        j                         s$t        j                         j                  d       yyy)z<Marks the function as unsaveable if not inside save context.a:  
ConcreteFunction that uses distributed variables in certain way cannot be saved.
If you're saving with

tf.saved_model.save(..., signatures=f.get_concrete_function())

do

@tf.function(input_signature=...)
def f_with_input_signature():
  ...

tf.saved_model.save(..., signatures=f_with_input_signature)`

instead.N)r   inside_functionr   r   get_default_graphmark_as_unsaveablerU   r   r   r   r   s  s>    <#?#?#A.. 0  $Br   )FNT)T)FN)1__doc__tensorflow.python.distributer   r   tensorflow.python.eagerr   tensorflow.python.frameworkr   r   tensorflow.python.opsr   r	   r
   rL   tensorflow.python.saved_modelr   r   !tensorflow.python.training.savingr   r   r3   rE   rI   rR   rV   rf   rl   rr   r|   r   r   r   r   r   r   r   r   r   r   r   r6   r   r   r   r   aggregation_error_msgscatter_error_msgr   r   rU   r   r   <module>r      s    < 7 4 + + 3 2 * 6 6 6 =$8, $ "< =A#' =A#'	6	6/ 	#
'
'
NE7 &M D"r   