
    AVhH                        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dlmZ ddlmZ ddlmZ  edg        G d dej*                               Z edg       G d dej.                               Z G d dej2                        Z G d dej6                        Zy)z8A tf.distribute.Strategy for running on a single device.    )device_util)distribute_lib)distribute_utils)	input_lib)
input_util)numpy_dataset)constant_op)ops)	array_ops)control_flow_ops)
while_loop)nest)	tf_exportzdistribute.OneDeviceStrategy)v1c                   f     e Zd ZdZ fdZd	 fd	Z	 d	 fd	Z fdZd
 fd	Z fdZ	 fdZ
 xZS )OneDeviceStrategya{  A distribution strategy for running on a single device.

  Using this strategy will place any variables created in its scope on the
  specified device. Input distributed through this strategy will be
  prefetched to the specified device. Moreover, any functions called via
  `strategy.run` will also be placed on the specified device
  as well.

  Typical usage of this strategy could be testing your code with the
  tf.distribute.Strategy API before switching to other strategies which
  actually distribute to multiple devices/machines.

  For example:
  ```
  strategy = tf.distribute.OneDeviceStrategy(device="/gpu:0")

  with strategy.scope():
    v = tf.Variable(1.0)
    print(v.device)  # /job:localhost/replica:0/task:0/device:GPU:0

  def step_fn(x):
    return x * 2

  result = 0
  for i in range(10):
    result += strategy.run(step_fn, args=(i,))
  print(result)  # 90
  ```
  c                     t         t        |   t        | |             t        j
                  j                  d      j                  d       y)a  Creates a `OneDeviceStrategy`.

    Args:
      device: Device string identifier for the device on which the variables
        should be placed. See class docs for more details on how the device is
        used. Examples: "/cpu:0", "/gpu:0", "/device:CPU:0", "/device:GPU:0"
    V2r   N)superr   __init__OneDeviceExtendedr   distribution_strategy_gaugeget_cellsetselfdevice	__class__s     `/home/dcms/DCMS/lib/python3.12/site-packages/tensorflow/python/distribute/one_device_strategy.pyr   zOneDeviceStrategy.__init__F   s?     

T+,=dF,KL..77=AA    c                 ,    t         t        |   ||      S )a  Distributes a tf.data.Dataset instance provided via dataset.

    In this case, there is only one device, so this is only a thin wrapper
    around the input dataset. It will, however, prefetch the input data to the
    specified device. The returned distributed dataset can be iterated over
    similar to how regular datasets can.

    NOTE: Currently, the user cannot add any more transformations to a
    distributed dataset.

    Example:
    ```
    strategy = tf.distribute.OneDeviceStrategy()
    dataset = tf.data.Dataset.range(10).batch(2)
    dist_dataset = strategy.experimental_distribute_dataset(dataset)
    for x in dist_dataset:
      print(x)  # [0, 1], [2, 3],...
    ```
    Args:
      dataset: `tf.data.Dataset` to be prefetched to device.
      options: `tf.distribute.InputOptions` used to control options on how this
        dataset is distributed.
    Returns:
      A "distributed `Dataset`" that the caller can iterate over.
    )r   r   experimental_distribute_dataset)r   datasetoptionsr   s      r   r"   z1OneDeviceStrategy.experimental_distribute_datasetR   s    4 "DI r    c                 ,    t         t        |   ||      S )a  Distributes `tf.data.Dataset` instances created by calls to `dataset_fn`.

    `dataset_fn` will be called once for each worker in the strategy. In this
    case, we only have one worker and one device so `dataset_fn` is called
    once.

    The `dataset_fn` should take an `tf.distribute.InputContext` instance where
    information about batching and input replication can be accessed:

    ```
    def dataset_fn(input_context):
      batch_size = input_context.get_per_replica_batch_size(global_batch_size)
      d = tf.data.Dataset.from_tensors([[1.]]).repeat().batch(batch_size)
      return d.shard(
          input_context.num_input_pipelines, input_context.input_pipeline_id)

    inputs = strategy.distribute_datasets_from_function(dataset_fn)

    for batch in inputs:
      replica_results = strategy.run(replica_fn, args=(batch,))
    ```

    IMPORTANT: The `tf.data.Dataset` returned by `dataset_fn` should have a
    per-replica batch size, unlike `experimental_distribute_dataset`, which uses
    the global batch size.  This may be computed using
    `input_context.get_per_replica_batch_size`.

    Args:
      dataset_fn: A function taking a `tf.distribute.InputContext` instance and
        returning a `tf.data.Dataset`.
      options: `tf.distribute.InputOptions` used to control options on how this
        dataset is distributed.

    Returns:
      A "distributed `Dataset`", which the caller can iterate over like regular
      datasets.
    )r   r   !distribute_datasets_from_function)r   
dataset_fnr$   r   s      r   r&   z3OneDeviceStrategy.distribute_datasets_from_functiono   s"    R "99CWMNr    c                 *    t         t        |   |      S )a  Returns the list of all local per-replica values contained in `value`.

    In `OneDeviceStrategy`, the `value` is always expected to be a single
    value, so the result is just the value in a tuple.

    Args:
      value: A value returned by `experimental_run()`, `run()`,
        `extended.call_for_each_replica()`, or a variable created in `scope`.

    Returns:
      A tuple of values contained in `value`. If `value` represents a single
      value, this returns `(value,).`
    )r   r   experimental_local_results)r   valuer   s     r   r)   z,OneDeviceStrategy.experimental_local_results   s     "DDUKKr    c                 0    t         t        |   ||||      S )a  Run `fn` on each replica, with the given arguments.

    In `OneDeviceStrategy`, `fn` is simply called within a device scope for the
    given device, with the provided arguments.

    Args:
      fn: The function to run. The output must be a `tf.nest` of `Tensor`s.
      args: (Optional) Positional arguments to `fn`.
      kwargs: (Optional) Keyword arguments to `fn`.
      options: (Optional) An instance of `tf.distribute.RunOptions` specifying
        the options to run `fn`.

    Returns:
      Return value from running `fn`.
    )r   r   run)r   fnargskwargsr$   r   s        r   r,   zOneDeviceStrategy.run   s      "D-b$HHr    c                 .    t         t        |   |||      S )a  Reduce `value` across replicas.

    In `OneDeviceStrategy`, there is only one replica, so if axis=None, value
    is simply returned. If axis is specified as something other than None,
    such as axis=0, value is reduced along that axis and returned.

    Example:
    ```
    t = tf.range(10)

    result = strategy.reduce(tf.distribute.ReduceOp.SUM, t, axis=None).numpy()
    # result: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

    result = strategy.reduce(tf.distribute.ReduceOp.SUM, t, axis=0).numpy()
    # result: 45
    ```

    Args:
      reduce_op: A `tf.distribute.ReduceOp` value specifying how values should
        be combined.
      value: A "per replica" value, e.g. returned by `run` to
        be combined into a single tensor.
      axis: Specifies the dimension to reduce along within each
        replica's tensor. Should typically be set to the batch dimension, or
        `None` to only reduce across replicas (e.g. if the tensor has no batch
        dimension).

    Returns:
      A `Tensor`.
    )r   r   reduce)r   	reduce_opr*   axisr   s       r   r1   zOneDeviceStrategy.reduce   s    > "D0E4HHr    c                 (    t         t        |          S )a  Returns a context manager selecting this Strategy as current.

    Inside a `with strategy.scope():` code block, this thread
    will use a variable creator set by `strategy`, and will
    enter its "cross-replica context".

    In `OneDeviceStrategy`, all variables created inside `strategy.scope()`
    will be on `device` specified at strategy construction time.
    See example in the docs for this class.

    Returns:
      A context manager to use for creating variables with this strategy.
    )r   r   scope)r   r   s    r   r5   zOneDeviceStrategy.scope   s     "D/11r    N) NN)__name__
__module____qualname____doc__r   r"   r&   r)   r,   r1   r5   __classcell__r   s   @r   r   r   &   s<    <
@ *NXL I$IB2 2r    r   c                        e Zd Zej                  j                  dd      Z fdZej                  j                  e_         xZS )OneDeviceStrategyV1zFor example:
  ```z0For example:
  ```
  tf.enable_eager_execution()c                     t         t        |   t        | |             t        j
                  j                  d      j                  d       y )NV1r   )r   r?   r   r   r   r   r   r   r   s     r   r   zOneDeviceStrategyV1.__init__   s=    	
t-.?f.MN..77=AAr    )r8   r9   r:   r   r;   replacer   r<   r=   s   @r   r?   r?      s?     %%--:<' '//77(r    r?   c                   x    e Zd ZdZ fdZd#dZed        Zd Zd Z	d Z
ej                  j                  fdZd	 Zd
 Zd Zd Zd Z	 d#dZd Zd Zd Zd Zd Zd Zd Zd Zd Zed        Zed        Zed        Z d Z!ed        Z"ed        Z#ed        Z$ed        Z%ed         Z&ed!        Z'd" Z( xZ)S )$r   z$Implementation of OneDeviceStrategy.c                     t         t        |   |       t        j                  |      | _        t        j                  | j
                        | _        y r6   )r   r   r   r   resolve_deviceget_host_for_device_input_device)r   container_strategyr   r   s      r   r   zOneDeviceExtended.__init__  s=    	
T+,>?&&v.DL$88FDr    c                     |r|j                   r-t        j                  | j                  | j                  ffg      S t        j                  | j                  | j                  ffg      S r6   )experimental_fetch_to_devicer   InputWorkersrH   rF   )r   r$   s     r   _input_workers_with_optionsz-OneDeviceExtended._input_workers_with_options  sc    g::##d&8&84<</%J$KLL##d&8&8'+'9'9&;&= %> ? ?r    c                 "    | j                         S r6   )rM   r   s    r   _input_workersz OneDeviceExtended._input_workers  s    ++--r    c                    |j                  dd       }|1t        j                  | j                        5   |di |cd d d        S t	        |t
        j                        r1t        j                  |j                        5   |di |cd d d        S t        j                  |      5   |di |cd d d        S # 1 sw Y   y xY w# 1 sw Y   y xY w# 1 sw Y   y xY w)Ncolocate_withr7   )popr
   r   rF   
isinstancer   SingleDevicerR   )r   next_creatorr/   rR   s       r   _create_variablez"OneDeviceExtended._create_variable  s    JJ5M::dll# &%f%& &	M=#=#=	>::m**+ &%f%& & ]+ &%f%& && && && &s#   B8?C&C8CCCc                 0    t        j                  ||        y r6   )r   validate_colocate)r   colocate_with_variables     r    _validate_colocate_with_variablez2OneDeviceExtended._validate_colocate_with_variable  s    &&'=tDr    c                 `    t        j                  || j                  | j                               S )z7Make iterator from dataset without splitting the batch.)input_lib_v1DatasetIteratorrP   _container_strategy)r   r#   s     r   _make_dataset_iteratorz(OneDeviceExtended._make_dataset_iterator   s/     ''1D1D(,(@(@(BD Dr    c                     t        j                  || j                  t        j                         g| j                               S r6   )r]   InputFunctionIteratorrP   r   InputContextr_   )r   input_fnreplication_modes      r   _make_input_fn_iteratorz)OneDeviceExtended._make_input_fn_iterator'  s>     --h8K8K/=/J/J/L.M.2.F.F.HJ Jr    c                 j    t        j                  |t        j                  | j                        |      S r6   )r   one_host_numpy_datasetrU   rH   )r   numpy_inputsessions      r    _experimental_make_numpy_datasetz2OneDeviceExtended._experimental_make_numpy_dataset/  s/    //]//0B0BCWN Nr    c                     ~|S r6   r7   )r   tensordestinationss      r   _broadcast_tozOneDeviceExtended._broadcast_to3  s
    Mr    c                     |r2|j                   t        j                  j                  k(  rt	        d      t        j                  || j                  |      | j                         |      S )NzhInputReplicationMode.PER_REPLICA is only supported in  `experimental_distribute_datasets_from_function`.r$   )	experimental_replication_moder   InputReplicationModePER_REPLICANotImplementedErrorr   get_distributed_datasetrM   r_   )r   r#   r$   s      r    _experimental_distribute_datasetz2OneDeviceExtended._experimental_distribute_dataset7  sj     	G99++778> 
 --((1  "	 r    c                     |r2|j                   t        j                  j                  k(  rt	        d      t        j                  || j                  |      t        j                         g| j                         |      S )NzInputReplicationMode.PER_REPLICA is only supported in `experimental_distribute_datasets_from_function` of tf.distribute.MirroredStrategyrq   )
rr   r   rs   rt   ru   r   &get_distributed_datasets_from_functionrM   rc   r_   )r   r'   r$   s      r   "_distribute_datasets_from_functionz4OneDeviceExtended._distribute_datasets_from_functionG  sw    G99++778./ /
 <<((1		$	$	&'  " r    c                 6     |t        j                               S r6   )r   ValueContext)r   value_fns     r   -_experimental_distribute_values_from_functionz?OneDeviceExtended._experimental_distribute_values_from_functionV  s     N//122r    c           
         |i }t        j                  |      }t        j                         fd}t	        j
                         j                         | _        fd}t        j                  d      }t        j                  |||g|z   ddddd      }| `t        j                  |      _        |dd  }	t        j                  j                  |	      }
j!                  |
       S )	Nc                     ~ j                               }t        j                  j                        }t	        j
                  |g      5  | dz   g|z   cddd       S # 1 sw Y   yxY w)z4A wrapper around `fn` to create the while loop body.   N)get_nextr   flattenlast_step_outputsr
   control_dependencies)ir.   	fn_resultflat_last_step_outputsctxr-   iterators       r   bodyzCOneDeviceExtended._experimental_run_steps_on_iterator.<locals>.bodyd  sd    
S(++-.i#||C,A,AB##YK0 0Aw//0 0 0s   	A""A+c                     | k  S r6   r7   )r   r.   
iterationss     r   <lambda>zGOneDeviceExtended._experimental_run_steps_on_iterator.<locals>.<lambda>u  s    A
N r    r    r   FT)nameparallel_iterations	back_propswap_memoryreturn_same_structure)r   r   r   MultiStepContextr
   get_default_graph_get_control_flow_context_outer_control_flow_contextr	   constantr   r   grouprun_oppack_sequence_asr   _set_last_step_outputs)r   r-   r   r   initial_loop_valuesr   condr   loop_resultlast_step_tensor_outputslast_step_tensor_outputs_dictr   s    ```       @r   #_experimental_run_steps_on_iteratorz5OneDeviceExtended._experimental_run_steps_on_iterator]  s    ",,':;

$
$
&C0 	99; 	$ +DQA''qc''"$K 	(!''4CJ  +12$($9$97%9! <=Jr    c                     | j                         }t        j                  | j                        5  t	        |      5   ||i |cd d d        cd d d        S # 1 sw Y   nxY wd d d        y # 1 sw Y   y xY wr6   )r_   r
   r   rF   _OneDeviceReplicaContext)r   r-   r.   r/   strategys        r   _call_for_each_replicaz(OneDeviceExtended._call_for_each_replica  sd    '')H	DLL	! !#;H#E !  ! ! ! ! ! ! !s"   A,A	A,A 	A,,A5c                     ~~~|S r6   r7   )r   r2   r*   rn   r$   s        r   
_reduce_tozOneDeviceExtended._reduce_to  s    <Lr    c                     ~~~|S r6   r7   )r   r*   rn   r3   r$   s        r   _gather_to_implementationz+OneDeviceExtended._gather_to_implementation  s    dGLr    c                 F    | j                  |||ft        |      z   ||      S r6   )_update_non_slottuple)r   varr-   r.   r/   r   s         r   _updatezOneDeviceExtended._update  s(       b3&5;*>NNr    c                 f   ~t        j                  | j                        5  t        j                  | j                        5   ||i |}|r|cd d d        cd d d        S t        j                  | j                  |      cd d d        cd d d        S # 1 sw Y   nxY wd d d        y # 1 sw Y   y xY wr6   )r
   r   rF   r   UpdateContextr   map_structure_local_results)r   rR   r-   r.   r/   r   results          r   r   z"OneDeviceExtended._update_non_slot  s    	DLL	! ?>#?#?#M ?4"6"f	? ? ?
 !!$"5"5v>? ? ? ? ? ? ?s/    B'B	B' B?	B'B	B''B0c                 ,    t        j                  |      S )z5Read the aggregate value of a replica-local variable.)r   identity)r   replica_local_vars     r   read_varzOneDeviceExtended.read_var  s    /00r    c                     |fS r6   r7   r   r*   s     r   r   z OneDeviceExtended._local_results  s	    8Or    c                     |S r6   r7   r   s     r   value_containerz!OneDeviceExtended.value_container  s    Lr    c                      y)zAWhether this strategy indicates working in multi-worker settings.Fr7   rO   s    r   _in_multi_worker_modez'OneDeviceExtended._in_multi_worker_mode      r    c                      y)Nr   r7   rO   s    r   _num_replicas_in_syncz'OneDeviceExtended._num_replicas_in_sync  s    r    c                     | j                   fS r6   rF   rO   s    r   worker_devicesz OneDeviceExtended.worker_devices      LL?r    c                     | j                   fS r6   r   rO   s    r   parameter_devicesz#OneDeviceExtended.parameter_devices  r   r    c                     ~| j                   fS r6   r   )r   var_lists     r   non_slot_devicesz"OneDeviceExtended.non_slot_devices  s    LL?r    c                      yNTr7   rO   s    r   experimental_should_initz*OneDeviceExtended.experimental_should_init      r    c                      yNFr7   rO   s    r   experimental_between_graphz,OneDeviceExtended.experimental_between_graph  r   r    c                      yr   r7   rO   s    r   should_checkpointz#OneDeviceExtended.should_checkpoint  r   r    c                      yr   r7   rO   s    r   should_save_summaryz%OneDeviceExtended.should_save_summary  r   r    c                      y)zEGlobal and per-replica batching are equivalent for OneDeviceStrategy.Tr7   rO   s    r   _global_batch_sizez$OneDeviceExtended._global_batch_size  s     r    c                      yr   r7   rO   s    r   _support_per_replica_valuesz-OneDeviceExtended._support_per_replica_values  r   r    c                     |S r6   r7   )r   replica_id_in_sync_groups     r   _get_local_replica_idz'OneDeviceExtended._get_local_replica_id  s    ##r    r6   )*r8   r9   r:   r;   r   rM   propertyrP   rW   r[   r`   r   rs   
PER_WORKERrf   rk   ro   rw   rz   r~   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r<   r=   s   @r   r   r      s_   ,G
? . .
&ED &::EEJN 3 ?C-^!
O
?1                  $r    r   c                   &    e Zd ZdZd Zed        Zy)r   z%ReplicaContext for OneDeviceStrategy.c                 H    t         j                  j                  | |d       y )Nr   )r   )r   ReplicaContextr   )r   r   s     r   r   z!_OneDeviceReplicaContext.__init__  s"    !!**h + 4r    c                 B    | j                   j                  j                  S r6   )	_strategyextendedr   rO   s    r   devicesz _OneDeviceReplicaContext.devices  s    >>""111r    N)r8   r9   r:   r;   r   r   r   r7   r    r   r   r     s    -4 2 2r    r   N)r;   tensorflow.python.distributer   r   r   r   r   r   tensorflow.python.distribute.v1r]   tensorflow.python.frameworkr	   r
   tensorflow.python.opsr   r   r   tensorflow.python.utilr    tensorflow.python.util.tf_exportr   Strategyr   
StrategyV1r?   StrategyExtendedV1r   r   r   r7   r    r   <module>r      s    ? 4 7 9 2 3 6 E 3 + + 2 , ' 6 )b1E2// E2 2E2P -./
8.33 
8 0
8b$99 b$J	2~<< 	2r    