o
    i ePT                     @   s(  d Z ddlZddlZddl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 g dggZdd	 Zed
G dd dejZedG dd deZdedededeeeeef  fddZdedededeeeeef  fddZdddejfdedeej deej dededefdd ZdS )!z Library of TPU helper functions.    N)ListOptionalTuple)
tf_logging)Topology)	tf_export)r   r   r   r   c                 C   s   i }t | jd D ]8}t | jd D ].}| ||ddf }||}||vr*i ||< ||| vr7t || |< || | | qq	i }| D ]\}}	i }
|	 D ]
\}}t||
|< qR|
||< qH|S )zDComputes a nested dict which maps task and logical core to replicas.r      N)rangeshapetask_ordinal_at_coordinatessetadditemssorted)core_assignmenttopologytask_and_cores_to_replicasreplicalogical_corecoordinatestask_idtask_to_sorted_replica_idtaskcore_to_replicascore_to_sorted_replicascorereplicas r   V/var/www/myenv/lib/python3.10/site-packages/tensorflow/python/tpu/device_assignment.py#_compute_task_and_cores_to_replicas   s$   


r   z tpu.experimental.DeviceOrderModec                   @   s   e Zd ZdZdZdZdZdS )DeviceOrderModezFThe way of determining device orders when computing device assignment.r   r      N)__name__
__module____qualname____doc__AUTORINGMESHr   r   r   r   r    8   s
    r    z!tpu.experimental.DeviceAssignmentc                   @   s@  e Zd ZdZdedejfddZedefddZ	ede
fd	d
Zede
fddZedejfddZde
de
defddZde
de
dee
 fddZd&de
de
de
fddZ			d'de
de
dee defddZ			d'de
de
dee defddZedddejfded eej d!eej d"e
d#edd fd$d%ZdS )(DeviceAssignmentzMapping from logical cores in a computation to the physical TPU topology.

  Prefer to use the `DeviceAssignment.build()` helper to construct a
  `DeviceAssignment`; it is easier if less flexible than constructing a
  `DeviceAssignment` directly.
  r   r   c                 C   s   t |tstdt|tj|tjd}|| _|j	dkr&td|j
 |j
d | _|j
d | _|j
d |jkrFtd|j d	|j
 || _t| j|| _d
S )a  Constructs a `DeviceAssignment` object.

    Args:
      topology: A `Topology` object that describes the physical TPU topology.
      core_assignment: A logical to physical core mapping, represented as a
        rank 3 numpy array. See the description of the `core_assignment`
        property for more details.

    Raises:
      ValueError: If `topology` is not `Topology` object.
      ValueError: If `core_assignment` is not a rank 3 numpy array.
    z*topology must be a Topology object, got {}dtype   z8core_assignment must be a rank 3 numpy array, got shape r   r   zAcore_assignment.shape[-1] must have size equal to topology rank (z), got core_assignment.shape=N)
isinstancer   
ValueErrorformattypenpasarrayint32	_topologyndimr
   _num_replicas_num_cores_per_replica	mesh_rank_core_assignmentr   _task_and_cores_to_replicas)selfr   r   r   r   r   __init__M   s0   


zDeviceAssignment.__init__returnc                 C      | j S )z-A `Topology` that describes the TPU topology.)r5   r<   r   r   r   r   r      zDeviceAssignment.topologyc                 C   r?   )z The number of cores per replica.)r8   r@   r   r   r   num_cores_per_replicaw   rA   z&DeviceAssignment.num_cores_per_replicac                 C   r?   )z*The number of replicas of the computation.)r7   r@   r   r   r   num_replicas|   rA   zDeviceAssignment.num_replicasc                 C   r?   )zThe logical to physical core mapping.

    Returns:
      An integer numpy array of rank 3, with shape
      `[num_replicas, num_cores_per_replica, topology_rank]`. Maps
      (replica, logical core) pairs to physical topology coordinates.
    )r:   r@   r   r   r   r      s   	z DeviceAssignment.core_assignmentr   r   c                 C   s   t | j||ddf S )z<Returns the physical topology coordinates of a logical core.N)tupler   )r<   r   r   r   r   r   r      s   zDeviceAssignment.coordinatesr   c                 C   s0   z| j | | W S  ty   td||w )at  Lookup replica ids by task number and logical core.

    Args:
      task_id: TensorFlow task number.
      logical_core: An integer, identifying a logical core.
    Returns:
      A sorted list of the replicas that are attached to that task and
      logical_core.
    Raises:
      ValueError: If no replica exists in the task which contains the logical
      core.
    z?Can not find any replica in task: {} contains logical_core: {} )r;   KeyErrorr/   r0   )r<   r   r   r   r   r   lookup_replicas   s   z DeviceAssignment.lookup_replicasr   c                 C   s   |  ||}| j|S )zAReturns the ordinal of the TPU device assigned to a logical core.)r   r5   !tpu_device_ordinal_at_coordinates)r<   r   r   r   r   r   r   tpu_ordinal   s   zDeviceAssignment.tpu_ordinalNjobc                 C      |  ||}| jj||dS )z2Returns the CPU device attached to a logical core.rI   )r   r5   cpu_device_name_at_coordinatesr<   r   r   rI   r   r   r   r   host_device      zDeviceAssignment.host_devicec                 C   rJ   )z>Returns the name of the TPU device assigned to a logical core.rK   )r   r5   tpu_device_name_at_coordinatesrM   r   r   r   
tpu_device   rO   zDeviceAssignment.tpu_devicer   computation_shapecomputation_striderC   device_order_modec                 C   s   t |||||dS )N)r   rR   rS   rC   rT   )device_assignment)clsr   rR   rS   rC   rT   r   r   r   build   s   	zDeviceAssignment.build)r   r   )r   r   N)r"   r#   r$   r%   r   r2   ndarrayr=   propertyr   intrB   rC   r   r   r   r   rF   rH   r   strrN   rQ   classmethodr    r&   rW   r   r   r   r   r)   D   sp    %

	
r)   x_sizey_sizez_coordr>   c                 C   s   g }t |d D ]+}t d| D ]}||d| |f qt | d ddD ]}||d| d |f q$qt |d ddD ]
}|d||f q<|S )a  Ring-order of a X by Y mesh, with a fixed Z coordinate.

  For example, in a 4x4 mesh, this returns the following order.
    0 -- 1 -- 2 -- 3
    |    |    |    |
    15-- 6 -- 5 -- 4
    |    |    |    |
    14-- 7 -- 8 -- 9
    |    |    |    |
    13-- 12-- 11-- 10

  Note that chip 0 is not included in the output.

  Args:
    x_size: An integer represents the mesh size in the x-dimension. Must be
      larger than 1.
    y_size: An integer represents the mesh size in the y-dimension. Must be
      larger than 1.
    z_coord: An integer represents the z-coordinate to use for the chips in the
      ring.

  Returns:
    A list of (x,y,z) triples in ring order.
  r!   r   r   r-   )r	   append)r]   r^   r_   retijr   r   r   _open_ring_2d   s   rd   z_sizec                    s  | dkr|dkrdd t |D S | dkr"|dkr"dd t |D S |dkr3|dkr3dd t | D S | dkr=| d dksQ|dkrG|d dksQ|dkrw|d dkrwtd g }t |D ]t |D ] | fd	d
t | D  qbq\|S dg}|dkr|t| |d |S |dkrdg}|dd
 t| |dD  |S | dkrdg}|dd
 t||dD  |S dg}t d|D ]}t| ||}|d dkr|| q|t| qt |d ddD ]
}|dd|f q|S )a  Ring-order of a X by Y by Z mesh.

  Constructs the 3d ring from 2d rings that are stacked in the Z dimension and
  joined in one corner.

  z == 0:
    0 -- 1 -- 2 -- 3
    |    |    |    |
    15 - 6 -- 5 -- 4
    |    |    |    |
    14 - 7 -- 8 -- 9
    |    |    |    |
    13 - 12 - 11 - 10
  z == 1:
    63 - 30 - 29 - 28
    |    |    |    |
    16 - 25 - 26 - 27
    |    |    |    |
    17 - 24 - 23 - 22
    |    |    |    |
    18 - 19 - 20 - 21
  z == 2:
    62 - 31 - 32 - 33
    |    |    |    |
    45 - 36 - 35 - 34
    |    |    |    |
    44 - 37 - 38 - 39
    |    |    |    |
    43 - 42 - 41 - 40
  z == 3:
    61 - 60 - 59 - 58
    |    |    |    |
    46 - 55 - 56 - 57
    |    |    |    |
    47 - 54 - 53 - 52
    |    |    |    |
    48 - 49 - 50 - 51

  Args:
    x_size: An integer represents the mesh size in the x-dimension. Must be
      larger than 1.
    y_size: An integer represents the mesh size in the y-dimension. Must be
      larger than 1.
    z_size: An integer represents the mesh size in the z-dimension. Must be
      larger than 1.  For example, in a 4x4x4 mesh, this returns the following
      order.

  Returns:
    A list of (x,y,z) triples in ring order.
  r   c                 S   s   g | ]}d d |fqS r   r   .0rb   r   r   r   
<listcomp>'      z_ring_3d.<locals>.<listcomp>c                 S   s   g | ]}d |d fqS rf   r   rg   r   r   r   ri   )  rj   c                 S   s   g | ]}|d d fqS rf   r   rg   r   r   r   ri   +  rj   r!   r   zOdd dimensionc                 3   s    | ]}| fV  qd S Nr   )rh   xyzr   r   	<genexpr>6  s    z_ring_3d.<locals>.<genexpr>)r   r   r   c                 s   s     | ]\}}}|||fV  qd S rk   r   )rh   rl   ro   rn   r   r   r   rp   B      c                 s   s     | ]\}}}|||fV  qd S rk   r   )rh   rn   ro   rl   r   r   r   rp   F  rq   r-   )r	   loggingwarningextendrd   reversedr`   )r]   r^   re   ra   rb   rr   rm   r   _ring_3d   sJ   6
 rw   r   r   rR   rS   rC   rT   c           2   	      s@  t | tr
t| d} t | tstdt|  t| j| j} du r0tjdg tj	d ntj
 tj	d du rHtjdg tj	dntj
tj	d jfkratd d j jfkrrtd dj t dk rtd	 tdk rtd
  }t||krtd|||| }| }t|}	||	krtd||	 |dd }
| jjdkrCdg }|dkr|}}tfddt|D D ])\}}| d  }tt|d|  }t||||< |
||| }|d8 }q|dkr|dksJ tj|gdtj	d}dko: d |d ko:tdko:||	k}|tjkrS|tjkrN|sNtd|tjk}|rg }t d  d  d }t|d |d |d }t|D ]N}|| \}}}g }tt D ]5}|||d   \}}}| d  | } | d  | }!| d  | }"||d  }#|| |!|"|#g q|| qtnt|D ]F}|}$g }%t|d g|dd gD ]}&|%|$|&  |$|& }$qt|%dd |%d gg}'|' }(|' })|(| |) ||ddf< qȇ fddtD }*tjdd tj|*ddiD dd}*|* df}*|*|ddtj!ddf  }nWtdksMJ |t  | j"| j# ks]J | j$}+g }t },t|D ].}-g }.t|,D ]}|-|, | }/|/| j# }0|/| j# }1|.|+|0|1ddf  qs||. qkt%| |dS )a  Computes a device_assignment of a computation across a TPU topology.

  Attempts to choose a compact grid of cores for locality.

  Returns a `DeviceAssignment` that describes the cores in the topology assigned
  to each core of each replica.

  `computation_shape` and `computation_stride` values should be powers of 2 for
  optimal packing.

  Args:
    topology: A `Topology` object that describes the TPU cluster topology. To
      obtain a TPU topology, evaluate the `Tensor` returned by
      `initialize_system` using `Session.run`. Either a serialized
      `TopologyProto` or a `Topology` object may be passed. Note: you must
        evaluate the `Tensor` first; you cannot pass an unevaluated `Tensor`
        here.
    computation_shape: A rank 1 int32 numpy array with size equal to the
      topology rank, describing the shape of the computation's block of cores.
      If None, the `computation_shape` is `[1] * topology_rank`.
    computation_stride: A rank 1 int32 numpy array of size `topology_rank`,
      describing the inter-core spacing of the `computation_shape` cores in the
      TPU topology. If None, the `computation_stride` is `[1] * topology_rank`.
    num_replicas: The number of computation replicas to run. The replicas will
      be packed into the free spaces of the topology.
    device_order_mode: An enum of `DeviceOrderMode` class which indicates
      whether to assign devices to form rings or meshes, or let the library to
      choose.

  Returns:
    A DeviceAssignment object, which describes the mapping between the logical
    cores in each computation replica and the physical cores in the TPU
    topology.

  Raises:
    ValueError: If `topology` is not a valid `Topology` object.
    ValueError: If `computation_shape` or `computation_stride` are not 1D int32
      numpy arrays with shape [3] where all values are positive.
    ValueError: If computation's replicas cannot fit into the TPU topology.
  )
serializedz)`topology` is not a Topology object; got Nr   r*   z#computation_shape must have shape [z]; got z$computation_stride must have shape [z<computation_shape must be positive; got computation_shape={}z>computation_stride must be positive; got computation_stride={}z>computation footprint {} does not fit in TPU topology shape {}zprequested {} replicas but only {} replicas with shape {} and computation_stride {} fit in a TPU mesh of shape {}c                 S   s   | | d | S )Nr   r   )nmr   r   r   ceil_of_ratio  s   z(device_assignment.<locals>.ceil_of_ratior   c                 3   s$    | ]\}}||d    fV  qdS )r   Nr   )rh   rb   rl   )topology_rankr   r   rp     s    z$device_assignment.<locals>.<genexpr>g      ?r-      zdevice_order_mode=DeviceOrderMode.RING is not compatible with the 3D tiling current topology.  Try setting device_order_mode=DeviceOrderMode.AUTOr!   c                    s*   g | ]}t d  | |  | qS rf   )r2   arangerg   )rR   rS   r   r   ri     s    z%device_assignment.<locals>.<listcomp>c                 S   s   g | ]	}|d t jf qS ).)r2   newaxisrg   r   r   r   ri     s    indexingij)axis)r   )&r.   bytesr   r/   r1   len
mesh_shaper2   arrayr4   r3   r
   anyr0   prodmissing_devicessizer   	enumeraterZ   mathceilminfullr    r&   r'   rw   r	   r`   concatenatemeshgridreshaper   	num_tasksnum_tpus_per_taskdevice_coordinatesr)   )2r   rR   rS   rC   rT   r   computation_footprintblock_countsreplica_countsmax_replicasr{   replica_shaperemaining_replicasremaining_dimsrl   nirb   target_sizereplica_offsetsenable_3d_tiling
assignment
inner_ring
outer_ringr   outer_xouter_youter_zper_replica_assignmentindexinner_xinner_yinner_zpxpypzpitposdimreplica_posouterinnerindicesr   devices_per_replicarindexreplica_assignment
logical_idr   devicer   )rR   rS   r|   r   rU   V  s  
0








 




rU   )r%   enumr   typingr   r   r   numpyr2   tensorflow.python.platformr   rr   tensorflow.python.tpu.topologyr    tensorflow.python.util.tf_exportr   SINGLE_CORE_ASSIGNMENTr   IntEnumr    objectr)   rZ   rd   rw   r&   rX   rU   r   r   r   r   <module>   sT    


%
h