o
    i eO                     @   sV  d Z ddlZddlZddlm  mZ ddlm	Z	 ddlm
Z
 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 Z			dpddZdd Z 	dqddZ!dd Z"dd Z#	drddZ$dd Z%dd  Z&d!d" Z'd#d$ Z(d%d& Z)d'd( Z*d)d* Z+	+dsd,d-Z,	drd.d/Z-d0d1 Z.d2d3 Z/d4d5 Z0d6d7 Z1d8d9 Z2d:d; Z3d<d= Z4dtd>d?Z5	dtd@dAZ6dtdBdCZ7dtdDdEZ8dFdG Z9dHdI Z:dJdK Z;dLdM Z<dNdO Z=dPdQ Z>dRdS Z?dTdU Z@dVdW ZAdXdY ZBdZd[ ZCd\d] ZDd^d_ ZEd`da ZFdbdc ZGddde ZHejIdfdg ZJdhdi ZKdjdk ZLdldm ZMdndo ZNdS )uz*Utilities related to distributed training.    N)backend)	callbacks)metrics)
optimizers)distribute_coordinator_utils)distributed_training_utils)training_utils_v1)optimizer_v2)tf_contextlib)ModeKeys)
tf_loggingc           	   	   C   s   g }|j D ]5}t|j}|d| }t|j|D ]\}}tjj r(|| q|	| 
|| q||d }qtjj sKt|| dS dS )a  Sets the weights of the replicated models.

    The weights of the replicated models are set to the weights of the original
    model. The weights of the replicated model are Mirrored variables and hence
    we need to use the `update` call within a DistributionStrategy scope.

    Args:
      distribution_strategy: DistributionStrategy used to distribute training
          and validation.
      dist_model: The replicated models on the different devices.
      weights: The weights of the original model.
    N)layerslenweightsziptfcompatv1#executing_eagerly_outside_functionsassignappendunwrapr   get_sessionrun)	distribution_strategy
dist_modelr   
assign_opslayer	num_paramlayer_weightssww r"   a/var/www/myenv/lib/python3.10/site-packages/keras/src/distribute/distributed_training_utils_v1.pyset_weights%   s   

r$   Fc                 C   sv   t | |}t| ||}|rt | |}nd}i }	|r5|d}
|
r't | |
|	d< |d}|r5t | ||	d< ||||	fS )a  Unwrap the list of values contained in the PerReplica parameters.

    This function calls `flatten_per_replica_values` to parse each of the input
    parameters into a list of values on the different devices. If we set
    `with_loss_tensor` to be True, we also call `reduce` on the list of losses
    on the different devices to give us one loss tensor.

    Args:
      distribution_strategy: DistributionStrategy used to distribute training
          and validation.
      grouped_inputs: PerReplica inputs returned from the train or test function
          that we ran on each device.
      grouped_outputs: PerReplica outputs returned from the train or test
          function that we ran on each device.
      grouped_updates: PerReplica updates returned from the train or test
          function that we ran on each device.
      grouped_session_args: PerReplica session args returned from the train or
          test function that we ran on each device.
      with_loss_tensor: Boolean that indicates if we need to add the reduced
          loss tensor as one of the outputs.

    Returns:
      Values of each of the PerReplica parameters.

    N	feed_dictfetches)flatten_per_replica_valuesunwrap_outputsget)r   grouped_inputsgrouped_outputsgrouped_updatesgrouped_session_argswith_loss_tensor
all_inputsall_outputsall_updatesall_session_argsgrouped_feed_dictgrouped_fetchesr"   r"   r#   unwrap_valuesA   s0   #

r5   c                 C   s   |t jkr
t| |S | jtjjj|d d dd}t| |d }t| |d }| jtjjj|d dd}t	| rOtj
j rO|dd| j }|dd| j }|g|||dS )	zBUnwrap the list of outputs contained in the PerReplica parameters.
total_lossr   Naxisoutput_lossesr   
batch_size)r6   r9   r   r:   )r   PREDICTr'   reducer   
distributeReduceOpSUMr   is_tpu_strategyr   r   r   num_replicas_in_sync)strategyr+   moder6   r9   r   r:   r"   r"   r#   unwrap_output_dict   s.   



rD   c                 C   sz   |st | |S t|ts|g}| jtjjj|d dd}t | |dd }t	| r8tj
j r8|dd| j }|g| S )a  Unwrap the list of outputs contained in the PerReplica parameters.

    This function calls `flatten_per_replica_values` to parse each of the input
    parameters into a list of outputs on the different devices. If we set
    `with_loss_tensor` to be True, we also call `reduce` on the list of losses
    on the different devices to give us one loss tensor.

    Args:
      distribution_strategy: DistributionStrategy used to distribute training
          and validation.
      grouped_outputs: PerReplica outputs returned from the train or test
          function that we ran on each device.
      with_loss_tensor: Boolean that indicates if we need to add the reduced
          loss tensor as one of the outputs.

    Returns:
      Values of each of the PerReplica outputs.

    r   Nr7      )r'   
isinstancelistr<   r   r=   r>   r?   r   r@   r   r   r   rA   )r   r+   r.   lossr0   r"   r"   r#   r(      s$   



r(   c                    s    fddt j|D S )a  Unwraps and flattens a nest of PerReplica parameters.

    PerReplica values have one value associated with each device. Each entry in
    the PerReplica dict has a device `key` and the corresponding value on the
    device as the `value`. In this function we take a PerReplica value or a list
    of PerReplica values and return all the values in the PerReplica dict.

    Args:
      distribution_strategy: DistributionStrategy used to distribute training
        and validation.
      per_replica_values: List of PerReplica object or a single PerReplica
        object.

    Returns:
      List of values of all the PerReplica objects.

    c                    s    g | ]}  |D ]}|q	qS r"   )r   ).0	flatteneder   r"   r#   
<listcomp>   s    z.flatten_per_replica_values.<locals>.<listcomp>)r   nestflatten)r   per_replica_valuesr"   rL   r#   r'      s   

r'   c                 C   sl   | r2| D ]/}t |tjtjfrt |tjstd| t |tjr1t|ddr1t	
td d|_qdS dS )a  Validate whether given callbacks are supported by DistributionStrategy.

    Args:
      input_callbacks: List of callbacks passed by the user to fit.
      optimizer: Optimizer instance used to train the model.

    Raises:
      ValueError: If `LearningRateScheduler` or `ReduceLROnPlateau` is one of
          the callbacks passed.
      ValueError: If `write_grads` is one of the parameters passed as part of
          the TensorBoard callback.
    zWYou must specify a Keras Optimizer V2 when using %s callback with DistributionStrategy.write_gradsFz}`write_grads` in the TensorBoard callback is not supported when using DistributionStrategy. Setting `write_grads` to `False`.N)rF   r   LearningRateSchedulerReduceLROnPlateaur	   OptimizerV2
ValueErrorTensorBoardgetattrloggingwarningUserWarningrQ   )input_callbacks	optimizercallbackr"   r"   r#   validate_callbacks   s.   
r^   c                 C   sD   t | |}|durt | |}nd}|durt | |}nd}|||fS )a/  Validate all the components of a DistributedValue Dataset input.

    Args:
      distribution_strategy: The current DistributionStrategy used to call
          `fit`/`evaluate`.
      x: Input Dataset DistributedValue object. For example, when we use
          `MirroredStrategy` this is a PerReplica object with a tensor for each
          device set in the dict. x can also be a tuple or dict. The keys of the
          dict should match the names of the input layers of the model.
      y: Target Dataset DistributedValue object. For example, when we use
          `MirroredStrategy` this is a PerReplica object with a tensor for each
          device set in the dict. y can also be a tuple or dict. The keys of the
          dict should match the names of the output layers of the model.
      sample_weights: Sample weights Dataset DistributedValue object. For
          example, when we use `MirroredStrategy` this is a PerReplica object
          with a tensor for each device set in the dict.

    Returns:
      The unwrapped values list of the x and y DistributedValues inputs.

    Raises:
      ValueError: If x and y do not have support for being evaluated as tensors.
          or if x and y contain elements that are not tensors or if x and y
          contain elements that have a shape or dtype mismatch.
    N)validate_per_replica_inputs)r   xysample_weightsx_values_listy_values_listsample_weights_listr"   r"   r#   #validate_distributed_dataset_inputs!  s   
"
rf   c                 C   sx   t j|}g }|D ]/}| |}|D ]}t |s#tdt|qt  s-t	|| t
|| ||d  q
|S )a  Validates PerReplica dataset input list.

    Args:
      distribution_strategy: The current DistributionStrategy used to call
        `fit`, `evaluate` and `predict`.
      x: A list of PerReplica objects that represent the input or
        target values.

    Returns:
      List containing the first element of each of the PerReplica objects in
      the input list.

    Raises:
      ValueError: If any of the objects in the `per_replica_list` is not a
        tensor.

    zHDataset input to the model should be tensors instead they are of type {}r   )r   rN   rO   r   	is_tensorrU   formattypeexecuting_eagerlyvalidate_all_tensor_shapesvalidate_all_tensor_typesr   )r   r`   per_replica_listrc   x_valuesvaluer"   r"   r#   r_   U  s    




r_   c                 C   s>   |d j }tdt|D ]}||| j krtd| qd S )Nr   rE   zAInput tensor dtypes do not match for distributed tensor inputs {})dtyperanger   rU   rh   )r`   rn   x_dtypeir"   r"   r#   rl   ~  s   
rl   c                 C   sF   |d j  }tdt|D ]}||| j  kr td| qd S )Nr   rE   zAInput tensor shapes do not match for distributed tensor inputs {})shapeas_listrq   r   rU   rh   )r`   rn   x_shapers   r"   r"   r#   rk     s   rk   c                 C   s   t t  }g }|D ]}t|dds|| q|sdS 	 | dd |D }g }t||D ]\}}|s:|| d|_q/|sBdS q)z0Utility to wait for variables to be initialized._keras_initializedFNTc                 S   s   g | ]	}t jj|qS r"   )r   r   r   is_variable_initialized)rI   vr"   r"   r#   rM     s    z5_wait_for_variable_initialization.<locals>.<listcomp>)r   _get_variables	get_graphrW   r   r   r   rw   )sessionall_variablescandidate_varsry   is_initializeduninitialized_varsflagr"   r"   r#   !_wait_for_variable_initialization  s(   

r   c                   C   s   t t   dS )zLInitialize or restore variables or wait for variables to be
    initialized.N)r   _initialize_variables_get_sessionr"   r"   r"   r#   "init_restore_or_wait_for_variables  s   r   c                 C   s0   t | tjjjjst |tjjjjrtddS )zValidate inputs when using DistributionStrategy.

    Args:
      x: Model Inputs.
      y: Model Targets.

    Raises:
      ValueError: if input is not a Dataset or a numpy array(when we use
        MirroredStrategy).
    z`DistributionStrategy` does not support inputs of type Iterator. You must pass a `tf.data.Dataset` object or a numpy array as input.N)rF   r   r   r   dataIteratorrU   )r`   ra   r"   r"   r#   validate_inputs  s   r   c                 C   s,   t jt jjj| }dd |D }| S )z9Returns whether a dataset contains a final partial batch.c                 S   s   g | ]}|  s|qS r"   )is_fully_defined)rI   sr"   r"   r#   rM     s    z2is_dataset_shape_fully_defined.<locals>.<listcomp>)r   rN   rO   r   r   r   get_output_shapes)datasetshapesunknown_shapesr"   r"   r#   is_dataset_shape_fully_defined  s   r           c                 C   sp   t j|d }t|tjr4|jd }|r)d|  k rdk r)n nt|d|  }t| ||||d\}}||fS )zFProcess the batch size and step size based on input and dist strategy.r   r   g      ?rE   rC   )	r   rN   rO   rF   npndarrayrt   intget_input_params)rB   inputsr:   steps_per_epochrC   validation_splitfirst_x_valuenum_samplesr"   r"   r#   process_batch_and_step_size  s   


r   c           	      C   sz  t |  }t r|tjkpt|  }n|tjkp)|tjks%|tj	ko)t| }|du r_|du r8t
|d}n	|}|rA|| j9 }|rNt|| t}nP|| rZtd||f || }n?|du rt|| rotd||f || }n*|}|r}|| j9 }|| }|r|dkr||d  d nd}||k rtd|||f |r|| j rtd|| jf || j }||fS |}||fS )	a  Calculate the number of batches and steps/steps_per_epoch.

    Args:
      distribution_strategy: The DistributionStrategy used to compile the model.
      num_samples: The number of samples from which we determine the batch size
        and steps.
      steps:  The specified number of steps.
      batch_size: The specified batch_size.
      mode: ModeKey representing whether input will be used for training,
        evaluation, or prediction. This is used to relax the constraints on
        consuming all the training samples to keep compatibility till we support
        partial batches. If none, then partial batches are not allowed.

    Returns:
      steps: The steps or steps_per_epoch argument depending on if a user is
          calling `fit`, `evaluate` or `predict`. If the is_training flag is set
          we don't require the number of samples to be used completely.
      batch_size: The batch size to be used in model iterations.

    Raises:
      ValueError: If the number of batches or steps evaluates to 0.

    N    z;The number of samples %s is not divisible by batch size %s.zThe number of samples %s is not divisible by steps %s. Please change the number of steps to a value that can consume all the samplesrE   r   z[Number of samples %s is less than samples required for specified batch_size %s and steps %szkThe batch size (%s) could not be sharded evenly across the sync replicas (%s) in the distribution strategy.)
dist_utilsglobal_batch_size_supportedr   rj   r   TRAINr   r@   r;   TESTminrA   r   ceilastyper   rU   )	r   r   stepsr:   rC   use_per_replica_batchallow_partial_batchglobal_batch_sizemin_num_samplesr"   r"   r#   r     sz   	







	r   c                 C   s2   t jt jjj| }|d j}|r|d S d S Nr   )r   rN   rO   r   r   r   r   dims)iteratorr   r   r"   r"   r#   get_batch_dimensionZ  s   
r   c                 C   s@   |   || }W d    n1 sw   Y  t|| |S N)scopemake_dataset_iteratorinitialize_iterator)r   r   r   r"   r"   r#   get_iteratorb  s
   

r   c                 C   sd   |  $ t| j}t s t|f| W d    d S W d    d S 1 s+w   Y  d S r   )r   r   groupinitializerrj   r   r   r   )r   r   init_opr"   r"   r#   r   i  s   
"r   c                 C   s   |   }ttj|t|jkr|}d}d}nttj|t|jt|j kr1|\}}d}n|\}}}t|j||| |||fS )zCGet elements from the iterator and verify the input shape and type.N)	get_nextr   r   rN   rO   r   outputsrf   _distribution_strategy)r   modelnext_elementr`   ra   rb   r"   r"   r#   _get_input_from_iteratorp  s   


r   c                    s   | j }t | \ }}t|r|durtdt tr' fdd| jD  t| rBt	|  t	||}t
jtj |f\ }nt   |tjkrSg }g }n|durkt| rkt
 rf| jsftdt	||} ||g}t|S )a  Prepare feed values to the model execution function.

    Args:
      model: Model to prepare feed values for.
      inputs: List or dict of model inputs.
      targets: Optional list of model targets.
      sample_weights: Optional list of sample weight arrays.
      mode: One of ModeKeys.TRAIN/ModeKeys.TEST/ModeKeys.PREDICT.

    Returns:
      Feed values for the model in the given mode.
    Nz,TPUStrategy does not support sample weights.c                    s   g | ]} | qS r"   r"   )rI   keyr   r"   r#   rM         z(_prepare_feed_values.<locals>.<listcomp>zb`sample_weight` is not supported when using tf.distribute.Strategy in eager mode and cloning=True.)r   r   r   r@   rU   rF   dict_feed_input_namesis_distributing_by_cloningr'   r   rN   map_structurer   standardize_single_arrayModelInputsru   r   r;   rj   _compile_distributionNotImplementedErrortuple)r   r   targetsrb   rC   rB   insr"   r   r#   _prepare_feed_values  s2   








r   c                 C   s0   t | jrtjrdS tjj rt| j	S dS )a)  Decide whether this model is going to be distributed via cloning.

    We are going to distribute the model by cloning in graph mode.

    Args:
      model: Keras model to distribute.

    Returns:
      True if the `model` is going to be distributed using cloning and False
      otherwise.
    FT)
r   r@   r   r   rj   r   r   r   boolr   r   r"   r"   r#   r     s   

r   c                 C   s,   | j sdS d| _d| _d| _d| _d| _dS )z$Custom compile for TPU predict mode.NT)built_is_compiledr6   train_functiontest_functionpredict_functionr   r"   r"   r#   _custom_compile_for_predict  s   
r   c              	      s   ddl m} ddlm} t| |jr|j| ||jd}n|j| ||jd}| j	|_	dd   fdd|j
D |_
t|trCtj|}|tjkrR|d	urRt| |S |j| j| jt| j| j| jt| j|d
 |S )a6  Build an updated model on replicas.

    We create a new Keras model while sharing the variables from the old graph.
    Building a new sub-graph is required since the original keras model creates
    placeholders for the input and the output that are not accessible till we
    call iterator.get_next() inside the step_fn for `fit`/`evaluate`/`predict`.

    The sharing of weights and layers between the old and the new model
    guarantee that we're using Strategy variables and any updates on either
    model are reflected correctly in callbacks and loop iterations.

    We need to make sure we share the optimizers between the old and the new
    model as well so that optimizer state is not lost if the user is running fit
    multiple times.

    Args:
      model: Model to be replicated across Replicas
      mode: Which of fit/eval/predict is building the distributed network
      inputs: Input variables to be passed to the model
      targets: Target tensor to be passed to model.compile

    Returns:
      A new model with shared layers with the old model.
    r   models)
sequential)input_tensorslayer_fnc                 S      | j tjkrt| tjS | S r   rp   r   bfloat16castfloat32outputr"   r"   r#   _upcast_low_precision_outputs     z@_build_network_on_replica.<locals>._upcast_low_precision_outputsc                       g | ]} |qS r"   r"   rI   or   r"   r#   rM         z-_build_network_on_replica.<locals>.<listcomp>Nr   loss_weightssample_weight_modeweighted_metricstarget_tensors)	keras.srcr   keras.src.enginer   rF   
Sequential_clone_sequential_modelshare_weights_clone_functional_model_callable_lossesr   r   r   rN   rO   r   r;   r   compiler\   rH   metrics_moduleclone_metrics_compile_metricsr   r   _compile_weighted_metrics)r   rC   r   r   r   r   updated_modelr"   r   r#   _build_network_on_replica  s>   


r   c              	   C   s   t   7 |  |jjt| |||fd}t| || W d   n1 s(w   Y  W d   dS W d   dS 1 s@w   Y  dS z&Create a cloned model on each replica.argsN)r   r{   
as_defaultr   extendedcall_for_each_replicar   set_distributed_modelr   rB   rC   r   r   distributed_modelr"   r"   r#   _build_distributed_network/  s   Pr  c              	      s   ddl m} |j| |d}t| jtjr| j}n| j }| jj	|}dd   fdd|j
D |_
t|tr>tj|}|tjkrM|durMt| |S |j|| jt| j| j| jt| j|d	 |S )
z&Clone and build the given keras_model.r   r   )r   c                 S   r   r   r   r   r"   r"   r#   r   L  r   z=_clone_and_build_model.<locals>._upcast_low_precision_outputsc                    r   r"   r"   r   r   r"   r#   rM   R  r   z*_clone_and_build_model.<locals>.<listcomp>Nr   )r   r   clone_modelrF   r\   r   TFOptimizer
get_config	__class__from_configr   r   r   rN   rO   r   r;   r   r   rH   r   r   r   r   r   r   )r   rC   r   r   r   cloned_modelr\   optimizer_configr"   r   r#   _clone_and_build_model:  s6   



r	  c              	   C   s   t   . |  |jjt| |||fd}t| || W d   n1 s(w   Y  W d   n1 s7w   Y  |tj	krH| 
| dS dS r   )r   r{   r   r   r   r   r	  r   r   r   _make_callback_modelr   r"   r"   r#   clone_model_on_replicasi  s    
r  c                 C   s>   t | r	t| |S t| |}|r|S t| |}t| || |S )zLMakes or reuses function to run one step of distributed model
    execution.)r   %_make_execution_function_with_cloningget_distributed_function(_make_execution_function_without_cloningset_distributed_function)r   rC   distributed_functiondistribution_functionr"   r"   r#   _make_execution_functiont  s   

r  c                    sr   | j  ( t| fdd | js$t   fdd}n }|W  d   S 1 s2w   Y  dS )zBCreates a function to run one step of distributed model execution.c                    s8   |  \}}}j |||fd}t| tjkd}|S )z;A single step of the distributed execution across replicas.r   r.   )r   r(   r   r;   )input_fnr`   ra   rb   r   r0   )rC   per_replica_functionrB   r"   r#   r    s   
zF_make_execution_function_without_cloning.<locals>.distributed_functionc                    s   dd  | D S )Nc                 S      g | ]}|  qS r"   )numpy)rI   outr"   r"   r#   rM     r   zX_make_execution_function_without_cloning.<locals>.execution_function.<locals>.<listcomp>r"   )r  )r  r"   r#   execution_function  s   zD_make_execution_function_without_cloning.<locals>.execution_functionN)r   r    _make_replica_execution_functionrun_eagerlyr   function)r   rC   r  r"   )r  rC   r  rB   r#   r    s   


$r  c                    sR   |t jkr	 j}n|t jkr j}n	d fdd	}|}|t jkr'tj|dd}|S )z8A single step of the distributed execution on a replica.Nc                    s   ~~  | S r   )predict_on_batch)r`   ra   rb   r   r"   r#   r    s   
z:_make_replica_execution_function.<locals>.predict_on_batchF)reset_metricsNN)r   r   train_on_batchr   test_on_batchr;   	functoolspartial)r   rC   funcr  r"   r   r#   r    s   


r  c                 C   s,   | j }| jrt| || dS t| || dS )zBuild models on each replica.N)r   r   r  r  )r   rC   rB   r"   r"   r#   $_make_replicated_models_with_cloning  s   r%  c                 C   s|   t | |}|rt|drt|dr|js|jS |s#t| | t | |}|s'J t r1t| |}nt| |}||_d|_|S )zLClones or re-uses models to run one step of distributed model
    execution._distribution_function_recompile_exec_functionF)	get_distributed_modelhasattrr'  _distributed_functionr%  r   rj   _make_eager_execution_function_make_graph_execution_function)r   rC   r   r  r"   r"   r#   r    s(   




r  c              	      s    fdd}| j }| = |jj|t|  fd\}}}}t  t||||| tjkd\}}	}
}t	j
||	f|
d  dd|W  d   S 1 sMw   Y  dS )	zBMakes function to run one step of distributed model in graph mode.c                    s   |   }|j|j|j|jfS r   )r  r   r   
updates_opsession_kwargsr   fr   r"   r#   _per_replica_function  s   
z=_make_graph_execution_function.<locals>._per_replica_functionr   r  distributed_	_function)updatesnameN)r   r   r   r   r(  r   r5   r   r;   r   r  )r   rC   r1  rB   r*   r+   r,   r-   r/   r0   r1   r2   r"   r   r#   r,    sF   



$r,  c              
      s    fdd}| j }t }| d | O t|' |jj|t|  fd}|\}}t	||| t
jkd\}}	}
}
W d   n1 sFw   Y  tj||	d  ddW  d   W  d   S 1 shw   Y  W d   dS 1 sxw   Y  dS )	zDMakes function to run one step of distributed model eager execution.c                    s   |   }|j|jfS r   )r  r   r   r/  r   r"   r#   r1  ,  s   
z=_make_eager_execution_function.<locals>._per_replica_functionr   r  Neager_distributed_r3  )r5  )r   r   r{   r   r   _scratch_graphr   r   r(  r5   r   r;   r  )r   rC   r1  rB   global_graphgroupedr*   r+   r/   r0   _r"   r   r#   r+  )  s.   

Rr+  c                 C   s>   | j }t| |}|r|  }||d }t||| dS dS )z9Copies weights from original model to distributed models.r   N)r   r(  get_weightsr   r$   )original_modelrC   rB   r   orig_model_weightsfirst_modelr"   r"   r#   "_copy_weights_to_distributed_modelX  s   
r?  c                 C   sD   | j r|tjkr t| |}| j |d  }| | dS dS dS )zCCopies weights from first distributed model back to original model.r   N)r   r   r   r(  r   r;  r$   )r   rC   r   updated_weightsr"   r"   r#   _copy_weights_to_original_modeld  s   
rA  c                 C   sf   | dur1|t jkr1g }tt|jD ]}| j}||| || |  }|ttj	
| q|S |S )zKAggregates the per-replica batch-level outputs from a distributed
    step.N)r   r;   rq   r   r   rA   r   concat_along_batch_dimensionr   rN   rO   )rB   
batch_outsr   rC   total_batch_outsrs   num_replicasnested_outsr"   r"   r#   _per_replica_aggregate_batchn  s   rG  c                 C   sJ   | j r!tjtjtjfD ]}t| |}|r | j |d }|  qd S d S r   )r   r   r   r   r;   r(  r   r  )r   rC   r   r>  r"   r"   r#   _reset_metrics  s   
rH  c                 C      t |}| j|d S r   )_generate_cache_key_distributed_model_cacher)   r   rC   r   r"   r"   r#   r(       r(  c                 C      t |}|| j|< d S r   )rJ  rK  )r   rC   r   r   r"   r"   r#   r     rM  r   c                 C   rI  r   )rJ  _distributed_function_cacher)   rL  r"   r"   r#   r    rM  r  c                 C   rN  r   )rJ  rO  )r   rC   r  r   r"   r"   r#   r    rM  r  c                 C   s   t | }|S r   )hash)rC   r   r"   r"   r#   rJ    s   rJ  c              	   c   sp    |   ) t| d V  W d    n1 sw   Y  W d    d S W d    d S 1 s1w   Y  d S r   )r   r   learning_phase_scope)rB   learning_phaser"   r"   r#   distributed_scope  s   PrS  c                   C   s
   t  jS r   )dcget_current_worker_contextis_chiefr"   r"   r"   r#   is_current_worker_chief  s   
rW  c                 C   sP   |  std| pg } dd | D std | du st r!| S dd | D S )a  Filter Callbacks based on the worker context when running multi-worker.

    Args:
      callbacks_list: A list of `Callback` instances.
      model: Keras model instance.

    Returns:
      The list of `Callback` instances that should be run on this worker.
    zXfilter_distributed_callbacks() should only be called when Keras is in multi worker mode.c                 S   s   g | ]
}t |tjr|qS r"   )rF   r   ModelCheckpoint)rI   cr"   r"   r#   rM     s
    z0filter_distributed_callbacks.<locals>.<listcomp>z]ModelCheckpoint callback is not provided. Workers will need to restart training if any fails.Nc                 S   s   g | ]}|j s|qS r"   )_chief_worker_only)rI   r]   r"   r"   r#   rM     s    )_in_multi_worker_moderU   rX   rY   rW  )callbacks_listr   r"   r"   r#   filter_distributed_callbacks  s    r]  c                 C   s   t | rCt| |}|st| | t| |}tdd | jD |_|rEt| j|}|d }|rGd|vrIt||D ]\}}|j	|gd q7dS dS dS dS dS )z3Update sample_weight_mode of the distributed model.c                 S   r  r"   )sample_weights_mismatch)rI   rK   r"   r"   r#   rM     r   z/_update_sample_weight_modes.<locals>.<listcomp>r   N)rb   )
r   r(  r%  any_training_endpointsr'  r'   r   r   _update_sample_weight_modes)r   rC   rb   r   distributed_modelsmr    r"   r"   r#   ra    s(   


	ra  c                 C   sH   t | d tjrtjjd| dS t | d tjrtj| ddS t| S )z5Concats prediction outputs along the batch dimension.r   )r8   	sp_inputsr7   )rF   r   SparseTensorsparseconcatRaggedTensorr   concatenate)r   r"   r"   r#   rB    s
   
rB  )NNF)Fr   )r   r  )O__doc__r"  r  r   tensorflow.compat.v2r   v2r   r   r   r   r   r   r   keras.src.distributer   rT  r   r   r   r   keras.src.optimizers.legacyr	   keras.src.utilsr
   keras.src.utils.mode_keysr   tensorflow.python.platformr   rX   r$   r5   rD   r(   r'   r^   rf   r_   rl   rk   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?  rA  rG  rH  r(  r   r  r  rJ  contextmanagerrS  rW  r]  ra  rB  r"   r"   r"   r#   <module>   s    
C'
2*
4)


{4
M


/$(7/

'