
    AVh>                        d Z ddlZddlZddlZddlmZmZmZm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j@                         Z! G d de"      Z#y)z>Propagates information about tensor layouts across operations.    N)AnyListSequenceSet)attr_value_pb2)config)layout)_pywrap_dtensor_device)context)core)device)dtypes)ops)sparse_tensor)tensor_util)_pywrap_utilsc                      e Zd ZdZ	 	 ddeej                     fdZd Zdej                  fdZ	e
deej                     fd       Zd	ee   d
ej                  defdZdedee   fdZdedej                  fdZdedefdZd Zd Zd Zd Zd Zdeej                     fdZej8                  dej                  fd       Zej8                  d
ej                  fd       Zy)DTensorDevicezAWraps a custom device which attempts to propagate tensor layouts.meshesc                 R   t        d |D              rt        dj                  |            t        j                         }t        5  dj                  |j                         t              | _        t        dz  addd       t        j                  | j                  ||      \  }}t        j                  || j                  |       || _        d| _        d| _        t               | _        t!        j"                         | _        |D ]  }| j'                  |        y# 1 sw Y   xY w)a  Create a new DTensorDevice which executes ops on `underlying_device`.

    Args:
      meshes: A list of `Mesh` objects indicating groups of devices to execute
        on. These may also be registered lazily.
      is_async: Indicates whether DTensor operations on this client will return
        immediately (with "non-ready" handles) or block until executed. This is
        on by default and is exposed as an option for ease of debugging.
      in_flight_nodes_limit: Indicates the limit of in-flight nodes before
        enqueueing of async operations to DTensorDevice is blocked. This limit
        is per mesh. 0 for no limits from DTensor. Default is 8.
    c              3   R   K   | ]  }t        |t        j                          ! y wN)
isinstance
layout_libMesh).0meshs     X/home/dcms/DCMS/lib/python3.12/site-packages/tensorflow/dtensor/python/dtensor_device.py	<genexpr>z)DTensorDevice.__init__.<locals>.<genexpr>@   s     
DTz$
00
Ds   %'z,Expected a flat list of Mesh objects, got {}z{}/device:CUSTOM:{}   N)any	TypeErrorformatr   _next_device_number_lockhost_address_space_next_device_numbernamer
   Allocateregister_custom_device_device_info_current_output_layout_current_default_meshset_meshes	threadingLock
_mesh_lock_register_mesh)selfr   is_asyncin_flight_nodes_limitctxr   device_infor   s           r   __init__zDTensorDevice.__init__0   s     
DV
DD
8
?
?
GI I //
C	! '..s/E/E/G/BDdiQ 199		82FK ""6499kB#D"&D!%D5DLnn&DO  
$  s   3DD&c                 0   t        j                  |      }t        j                  |      j                  |      }t	        j
                  t        j                         dd      g}t        |      }t        |      D cg c]
  }|||z  z    }}|||fS c c}w )zCReturns ID and device lists that can be used to create a host mesh.CPUr   )jobdevice_typedevice_index)
npprodarangereshape	tf_device
DeviceSpecr   full_job_namelenrange)	r3   shapehost_idnum_global_devicesglobal_device_idslocal_device_listnum_local_devicesxlocal_device_idss	            r   _create_host_arrayz DTensorDevice._create_host_arrayV   s    		"45==eD$$&E	K -.167H1I,-G'''  .0AAAs   =Br   c                    | j                   5  || j                  vrt        j                  | j                  |j                         d       | j                  j                  |       |j                         j                         dk(  rt        j                  d|j                         j                         |j                                t        j                  | j                  |j                         j                         d       | j                  j                  |j                                ddd       y# 1 sw Y   yxY w)z5Idempotently register `mesh` with the dtensor device.FTPUz7Registering virtual 1:1 mapped host mesh %s for mesh %sTN)r1   r.   r
   AddMeshr*   	to_stringaddr<   upperlogginginfo	host_mesh)r3   r   s     r   r2   zDTensorDevice._register_meshd   s    	 -	T\\	!&&t~~/	
 	##%.
,,Gnn((*DNN,<> !
(
(!1!;!;!=t ,,

4>>+
,- - -s   D"D88Ereturnc                     | j                   S r   )r.   r3   s    r   r   zDTensorDevice.meshesu   s    <<    tensorsr	   c           	         t        j                         st        d      | j                  |j                         t        j                  | j                        5  t        d D              rt        fdD              st        d      d}D cg c]  }|j                   c}D cg c]  }|j                   c}z   D cg c]1  }t        j                  |j                  t        j                        3 c}z   nt!        d D              rt        d      d	}	 t#        j$                  t        j                          j&                  |j)                         | j*                  |      cd
d
d
       S c c}w c c}w c c}w # t,        j.                  $ r}t-        j0                  |      d
d
}~ww xY w# 1 sw Y   y
xY w)a	  Packs tensors into a DTensor handle on this DTensor device.

    Packing and unpacking are inverse operations:

    ```
    * unpack(pack(tensors)) == tensors
    * pack(unpack(dtensor)) == dtensor
    ```

    Refer to `dtensor.pack` for more information.

    Args:
      tensors: The list of tensors to pack into a DTensor.
      layout: The layout of the DTensor to be created.

    Returns:
      A DTensor created from the individual component tensors.

    Raises:
      RuntimeError: When not called eagerly.
    z`pack` must be called eagerly.c              3   P   K   | ]  }t        |t        j                           y wr   r   r   SparseTensorr   ts     r   r   z%DTensorDevice.pack.<locals>.<genexpr>   s     H1Z=556H   $&c              3   V   K   | ]   }|j                   d    j                   k(   " yw)r   N)rG   )r   rc   r]   s     r   r   z%DTensorDevice.pack.<locals>.<genexpr>   s$     @1177gaj...@s   &)z3All input SparseTensors to Pack must be same shape.T)dtypec              3   P   K   | ]  }t        |t        j                           y wr   r`   rb   s     r   r   z%DTensorDevice.pack.<locals>.<genexpr>   s     JQz!]778Jrd   z'Cannot Pack SparseTensors with Tensors.FN)r   executing_eagerlyRuntimeErrorr2   r   r   r   r'   allr"   indicesvaluesconvert_to_tensorrG   r   int64r!   r
   Pack_handlerS   r*   r   _NotOkStatusException_status_to_exception)r3   r]   r	   	is_sparserc   es    `    r   packzDTensorDevice.packy   su   , $$&9::$	DII	 5	HH	H@@@OP
P	&-.199.G1Lq!((1LLHOP
CDC!!!''>P
 
 J'JJABB	5%**OO%%5 5
 /1L P
 '' 5''*45'5 5sU   8F9E9&F9,E>?F96F=%F9#AF9F9F6F11F66F99Gdtensorc                    t        j                         st        d      	 t        j                  t        j                          j
                  || j                        }t        j                  t        j                          j
                  || j                        }|rpg }t        t        |      dz        D ]R  }|j                  t        j                  ||   ||t        |      dz  z      ||dt        |      z  dz  z                   T |S |S # t        j                  $ r}t        j                  |      dd}~ww xY w)a  Unpacks a DTensor handle on this DTensor device.

    Packing and unpacking are inverse operations:

    ```
    * unpack(pack(tensors)) == tensors
    * pack(unpack(dtensor)) == dtensor
    ```

    Refer to `dtensor.unpack` for more information.

    Args:
      dtensor: The DTensor to unpack.

    Returns:
      The raw underlying tensor components of the DTensor.

    Raises:
      RuntimeError: When not called eagerly.
    z `unpack` must be called eagerly.N      )r   rh   ri   r
   Unpackrp   r*   r   rq   rr   IsSparseDTensorrF   rE   appendr   ra   )r3   rv   r]   rt   rs   resultis          r   unpackzDTensorDevice.unpack   s.   * $$&;<<3&--
//

#
#



g '66!!I fS\Q&' L!&&wqz'.q3w<13D/D'E'.q1s7|3Cq3H/H'IK	LL
 mn! %% 3%%a(d23s   =D D="D88D=c                    t        j                         st        d      t        j                  |      r|j                         }	 t        j                  t        j                          j                  || j                        }|yt        j                  j                  |      S # t        j                  $ r}t        j                  |      dd}~ww xY w)zFetches the layout of the DTensor.

    Args:
      dtensor: The DTensor whose layout is to be fetched.

    Returns:
      The `Layout` of this DTensor.

    Raises:
      RuntimeError: When not called eagerly.
    z&`fetch_layout` must be called eagerly.N)r   rh   ri   r   
IsVariable
read_valuer
   FetchLayoutrp   r*   r   rq   rr   r   Layoutfrom_string)r3   rv   layout_stringrt   s       r   fetch_layoutzDTensorDevice.fetch_layout   s     $$&ABB(""$g3,88
//

#
#



m ((77 %% 3%%a(d23s   =B% %C8CCtensorc                 (   t        j                         st        d      t        j                  |      syt        j                  |      r|j                  }t        j                  t        j                          j                  || j                        S )a~  Check whether the input tensor is a DTensor.

    In Python, a DTensor has the same type as a `tf.Tensor`. This method will
    let you check and handle the tensor differently if a tf.Tensor is a DTensor.

    Args:
      tensor: an object to be checked.

    Returns:
      bool, True if the given tensor is a DTensor.

    Raises:
      RuntimeError: When not called eagerly.
    z$`is_dtensor` must be called eagerly.F)r   rh   ri   r   	is_tensorr   r   rp   r
   	IsDTensorr*   )r3   r   s     r   
is_dtensorzDTensorDevice.is_dtensor   ss     $$&?@@  ('~~f!++!! r\   c                 F    t        j                  | j                  ||       y)zSets the singleton global device ID-to-physical core ID map.

    Args:
      mesh_name: The name of a mesh. If empty, set the default mapping.
      tpu_core_ids: TPU core IDs sorted by TF task/device ordinal.
    N)r
   SetTPUCoreIDsr*   )r3   	mesh_nametpu_core_idss      r   set_tpu_core_idszDTensorDevice.set_tpu_core_ids  s     (():):I)57r\   c                 B    t        j                  | j                         y r   )r
   ClearTPUCoreIDsr*   r[   s    r   clear_tpu_core_idsz DTensorDevice.clear_tpu_core_ids  s    **4+<+<=r\   c                 |    t        j                  t        j                         j                  | j                  |      S )zTranslates TPU core IDs to TPU core locations.

    Args:
      tpu_core_ids: A list of TPU core IDs. Each one is an unsigned integer.

    Returns:
      A list of corresponding TPU core locations.
    )r
   TPUCoreIDsToLocationsr   rp   r*   )r3   r   s     r   tpu_core_ids_to_locationsz'DTensorDevice.tpu_core_ids_to_locations  s3     "77!! r\   c                 |    t        j                  t        j                         j                  | j                  |      S )zTranslates TPU core locations to TPU core IDs.

    Args:
      tpu_core_locations: A list of TPU core locations. Each one is a list of
        four unsigned integers, [x, y, z, core].

    Returns:
      A list of corresponding TPU core IDs.
    )r
   TPUCoreLocationsToIDsr   rp   r*   )r3   tpu_core_locationss     r   tpu_core_locations_to_idsz'DTensorDevice.tpu_core_locations_to_ids(  s3     "77!! r\   c                 z    t        j                  t        j                         j                  | j                        S )zReturns the number of cache hit and miss for function compilation.

    Returns:
      A dictionary.
        'miss': number of cache misses;
        'hit': number of cache hits; and
        'size': size of cache;
      miss count.
    )r
   GetStatsr   rp   r*   r[   s    r   
_get_statszDTensorDevice._get_stats7  s0     "**!! r\   layoutsc           	          t        j                  t        j                         j                  ||D cg c]  }|j	                          c}| j
                         yc c}w )a6  Sets the element layouts on an iterator resource tensor.

    Args:
      iterator_resource_dtensor: a DTensor created by packing the individiual
        iterator resource tensors.
      layouts: the flattened list of layouts to be applied to the elements
        emitted by the iterator resource DTensor.
    N)r
   SetIteratorElementLayoutsr   rp   rS   r*   )r3   iterator_resource_dtensorr   r	   s       r   set_iterator_element_layoutsz*DTensorDevice.set_iterator_element_layoutsF  sJ     44!!!*12			2	 	3s   Ac              #     K   | j                   }| j                  |       t        j                  | j                  |j                         j                  d             || _         d t        j                  | j                         |r=t        j                  | j                  |j                         j                  d             || _         yw)aD  Sets a default mesh for all ops in the scope.

    Note: This is an internal helper method, which is not user facing api.

    Useful for requesting a specific mesh for ops which would have no inferred
    layout, e.g. tf.zeros.

    Args:
      mesh: A Mesh to be used for ops without Mesh.

    Yields:
      Nothing.
    utf-8N)r,   r2   r
   ExperimentalSetDefaultMeshr*   rS   encodeExperimentalClearDefaultMesh)r3   r   previous_defaults      r   _experimental_default_meshz(DTensorDevice._experimental_default_meshV  s      1155(* "&D	778I8IJ77




$
$
&
-
-g
68 "2Ds   CCc              #     K   d}d}d}| j                  |j                         	 | j                  }|j                         j	                  d      | _        t        j                  | j                  | j                         t        j                         r-t        j                  | j                        5  d ddd       n1t        j                         }t        |j                               }d ||j                         |d D ]  }|j!                  dt#        j$                  t"        j$                  j'                  | j                  g                   |j!                  dt#        j$                  |j                  j                         j	                  d                    || _        | j                   t        j(                  | j                         yt        j                  | j                  | j                  j+                  d             y# 1 sw Y   -xY w# ||j                         |d D ]  }|j!                  dt#        j$                  t"        j$                  j'                  | j                  g                   |j!                  dt#        j$                  |j                  j                         j	                  d                    || _        | j                   t        j(                  | j                         w t        j                  | j                  | j                  j+                  d             w xY ww)a  Sets a default output layout for all ops in the scope.

    Note: This is an internal helper method, which is not user facing api.

    Useful for requesting a specific layout for ops which would have no inferred
    layout, e.g. tf.zeros.

    Caveats:

    - Currently only affects the first output of an op. For Op with multiple
      outputs, this does not support yet.

    - All Ops in the scope will be attached with the same layout. This might not
      be valid as the rank is different. The current suggestion is: Try to wrap
      the raw op wheneven possible.

    Args:
      layout: A Layout for the outputs of all operations in this scope.

    Yields:
      Nothing.
    Nr   _layout)s)list_mesh)r2   r   r+   rS   r   r
   ExperimentalSetDefaultLayoutr*   r   rh   r   r   r'   get_default_graphrE   get_operations	_set_attrr   	AttrValue	ListValueExperimentalClearDefaultLayoutdecode)r3   r	   r   previous_graph_sizegraph	operations         r   _default_layoutzDTensorDevice._default_layouts  s    0 E$%L44$*$4$4$6$=$=g$Fd!99


T88:		"	"	$ZZ		" 	
	 	 %%'!%"6"6"89		--/0C0DE 
	>I


&&%//99445 : 789
 

&&KK))+227;=>
	> %5d!		$	$	,==d>O>OP;;t::AA'J	L=	 	 
	--/0C0DE 
	>I


&&%//99445 : 789
 

&&KK))+227;=>
	> %5d!		$	$	,==d>O>OP;;t::AA'J	Ls7   "MBH! 2H7:H! 1D#MHH! !D$MMN)T   )__name__
__module____qualname____doc__r   r   r   r8   rO   r2   propertyr   r   r   r   r   ru   r   r   boolr   r   r   r   r   r   r   
contextlibcontextmanagerr   r    r\   r   r   r   -   sJ   I %&$ JOO,$ LB- -" c*//*  -5(3- -51B1B -5s -5^,C ,HSM ,\8# 8**;*; 88s t 67>,01B1B,C  2Z__ 2 28 ALJ$5$5 AL ALr\   r   )$r   r   rV   r/   typingr   r   r   r   numpyr>   tensorflow.core.frameworkr   tensorflow.dtensor.pythonr   r	   r   tensorflow.pythonr
   tensorflow.python.eagerr   r   tensorflow.python.frameworkr   rB   r   r   r   r   tensorflow.python.utilr   r&   r0   r$   objectr   r   r\   r   <module>r      sh    E    + +  4 , : 4 + ( ; . + 5 3 0  )9>>+ HLF HLr\   