
    BVh%                        d Z ddlZddlZddlmZ ddlmZ ddlmZ ddl	m
Z
 ddl	mZ ddl	mZ dd	l	mZ dd
lmZ ddlmZ ddlmZ ddlmZ ddlmZ da ej0                         a ej4                         Zd Z G d de      Zy)zIUtility for eagerly executing operations in parallel on multiple devices.    N)_pywrap_parallel_device)device_util)context)composite_tensor)constant_op)ops)tensor)	array_ops)	variables)tpu_ops)nest)variable_utilsc                     t         j                  | j                  d      }|$t        dj	                  | j                              |j                  |       S )z<Finds `tensor`'s parallel device and unpacks its components.Nz{} is not a parallel device)_all_parallel_devicesgetdevice
ValueErrorformatunpack)r	   parallel_devices     l/home/dcms/DCMS/lib/python3.12/site-packages/tensorflow/python/distribute/parallel_device/parallel_device.pyr   r   '   sJ    )--fmmTB/
299&--H
II				''    c                   P    e Zd ZdZd Zd Zd Zd Zd Ze	d        Z
d Zd	 Zd
 Zy)ParallelDevicez/A device which executes operations in parallel.c                     t        d |D              | _        | j                  st        d      t        j                         }t        5  dj                  |j                         t              | _        t        dz  addd       t        j                  | j                  | j                        \  }}t        j                  || j                  |       d| _        d| _        | t        | j                  <   y# 1 sw Y   yxY w)a%  Creates a device which executes operations in parallel on `components`.

    Args:
      components: A list of device names. Each operation executed on the
        returned device executes on these component devices.

    Returns:
      A string with the name of the newly created device.
    c              3   F   K   | ]  }t        j                  |        y wN)r   canonicalize).0ds     r   	<genexpr>z*ParallelDevice.__init__.<locals>.<genexpr>C   s     LAK44Q7Ls   !z/ParallelDevice requires at least one component.z{}/device:CUSTOM:{}   N)tuple
componentsr   r   _next_device_number_lockr   host_address_space_next_device_number_namer   GetParallelDeviceCapsulesregister_custom_device_device_ids_device_scoper   )selfr$   ctxr   device_infos        r   __init__zParallelDevice.__init__8   s     LLLDO??HII
//
C	!  )//0F0F0H0CEdjQ 2KK

DOO%FK""64::{CDD(,$**% s   	3C44C=c                 L   |D ]U  }t        |t        j                  t        j                  t
        j                  f      r=t        dj                  |             t        j                  | j                        5  t        j                  |      cddd       S # 1 sw Y   yxY w)z?Helper to pack plain-old-tensors, not structures or composites.zEvery component to pack onto the ParallelDevice must already be a tensor, got {}. Consider running `tf.constant` or `tf.convert_to_tensor` first on literal values.)inputsN)
isinstance
tensor_libTensorr   CompositeTensorr   Variabler   r   r   r   r(   r   tpu_replicated_input)r-   tensorsr	   s      r   _pack_tensorzParallelDevice._pack_tensorT   s     
..   ? VG_	 	 
DJJ	 :))9: : :s   :BB#c                    | j                          t        |      t        | j                        k7  r7t        dj	                  t        |      t        | j                                    t        j                  d      5  t        j                  |      }ddd       t        j                  | j                  g|ddiS # 1 sw Y   ,xY w)a~  Create a tensor on the parallel device from a sequence of tensors.

    Args:
      tensors: A list of tensors, one per device in `self.components`. The list
        can contain composite tensors and nests (lists, dicts, etc. supported by
        `tf.nest`) with the same structure for each device, but every component
        of nests must already be a `tf.Tensor` or composite. Passing
        `tf.Variable` objects reads their value, it does not share a mutable
        reference between the packed and unpacked forms.

    Returns:
      A tensor placed on the ParallelDevice. For nested structures, returns a
      single structure containing tensors placed on the ParallelDevice (same
      structure as each component of `tensors`).

    Raises:
      ValueError: If the length of `tensors` does not match the number of
        component devices, or if there are non-tensor inputs.

    zZCreating a parallel tensor requires one tensor per component. Got {} but was expecting {}.Nexpand_compositesT)_assert_eagerlenr$   r   r   r   r   r   convert_variables_to_tensorsr   map_structurer:   )r-   r9   s     r   packzParallelDevice.packg   s    * 	
7|s4??++*6#g,DOO 457 7 
D	 E ;;GDgE d// 6' 6046 6	E Es   >B??Cc                 f   t        |t        j                  t        j                  t
        j                  f      st        dj                  |            t        j                  | j                        5  t        j                  |t        | j                              cddd       S # 1 sw Y   yxY w)z!Helper to unpack a single tensor.zExpected a tensor, got {}.)num_replicasN)r3   r4   r5   r   r6   r   r7   r   r   r   r   r(   r   tpu_replicated_outputr>   r$   )r-   parallel_tensors     r   _unpack_tensorzParallelDevice._unpack_tensor   s    ,,	
 3::?KLL	DJJ	 >**
DOO(<>> > >s   3*B''B0c                 
   | j                          t        t        | j                              D cg c]  }g  }}t	        j
                  | j                        5  t        j                  |      }ddd       t        j                  |d      D ]6  }t        || j                  |            D ]  \  }}|j                  |        8 |D cg c]  }t        j                  ||d       c}S c c}w # 1 sw Y   xY wc c}w )a  Unpack a parallel tensor into its components.

    Args:
      parallel_tensor: A tensor, composite tensor, or `tf.nest` of such placed
        on the ParallelDevice. Passing `tf.Variable` objects reads their value,
        it does not share a mutable reference between the packed and unpacked
        forms.

    Returns:
      A list with the same length as `self.components` each with the same
      structure as `parallel_tensor`, containing component tensors.

    NT)r<   )r=   ranger>   r$   r   r   r(   r   r?   r   flattenziprF   appendpack_sequence_as)r-   rE   _unpacked_componentsr	   accumulatorunpacked_tensorunpackeds           r   r   zParallelDevice.unpack   s     	',S-A'BC!2CC	DJJ	 &CC
o ,,$G ,*-
t226:+< ,
&+?+,, 01 !!/848: 1 1 D 1s   	C/C4D 4C=c           
         | j                   t        j                         5  g }t        | j                        D ]Z  \  }}t        j
                  |      5  |j                  t        j                  t        j                  |                   ddd       \ | j                  |      | _         ddd       | j                   S | j                   S # 1 sw Y   xY w# 1 sw Y   | j                   S xY w)a!  A parallel tensor with scalar integers numbering component devices.

    Each device ID is placed on its corresponding device, in the same order as
    the `components` constructor argument.

    Returns:
      A parallel tensor containing 0 on the first device, 1 on the second, etc.
    N)r+   r   
init_scope	enumerater$   r   rK   r
   identityr   constantrA   )r-   device_ids_listindexr   s       r   
device_idszParallelDevice.device_ids   s      >> 6 &t7 	AME6zz&! A """";#7#7#>?AA A	A  99_56 4A A6 s#   3C8C CCCC,c                 B    t        j                         st        d      y)z$Verifies that tracing is not active.zParallelDevice is currently not supported inside `tf.function`. It can however run calls to a `tf.function` in parallel:

with ParallelDevice() as p:
  f()N)r   executing_eagerlyNotImplementedErrorr-   s    r   r=   zParallelDevice._assert_eager   s%    $$&/0 0 'r   c                     | j                   t        d      | j                          t        j                  | j
                        | _         | j                   j                          | S )zERuns ops in parallel, makes variables which save independent buffers.z;Re-entered a ParallelDevice scope without first exiting it.)r,   AssertionErrorr=   r   r   r(   	__enter__r]   s    r   r`   zParallelDevice.__enter__   sX    %
GI IDJJ/D  "Kr   c                 L    | j                   j                  |||       d | _         y r   )r,   __exit__)r-   typexctbs       r   rb   zParallelDevice.__exit__   s"    S"-Dr   N)__name__
__module____qualname____doc__r0   r:   rA   rF   r   propertyrY   r=   r`   rb    r   r   r   r   5   sC    7-8:& 6D>16  @0r   r   )ri   	threadingweakreftensorflow.pythonr   tensorflow.python.distributer   tensorflow.python.eagerr   tensorflow.python.frameworkr   r   r   r	   r4   tensorflow.python.opsr
   r   tensorflow.python.tpu.opsr   tensorflow.python.utilr   r   r'   Lockr%   WeakValueDictionaryr   r   objectr   rk   r   r   <module>rx      sn    P   5 4 + 8 3 + < + + - ' 1 )9>>+ 3335 (sV sr   