o
    ?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shapeZtask_ordinal_at_coordinatessetadditemssorted)core_assignmenttopologyZtask_and_cores_to_replicasreplicalogical_corecoordinatestask_idZtask_to_sorted_replica_idtaskZcore_to_replicasZcore_to_sorted_replicascoreZreplicas r   h/home/www/facesmatcher.com/pyenv/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RINGZ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 {}Z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_replicaZ	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.)r-   r3   r   r   r   r   r      zDeviceAssignment.topologyc                 C   r6   )z The number of cores per replica.)r0   r7   r   r   r   num_cores_per_replicaw   r8   z&DeviceAssignment.num_cores_per_replicac                 C   r6   )z*The number of replicas of the computation.)r/   r7   r   r   r   num_replicas|   r8   zDeviceAssignment.num_replicasc                 C   r6   )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.
    )r1   r7   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   )r3   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: {} )r2   KeyErrorr'   r(   )r3   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   r-   Z!tpu_device_ordinal_at_coordinates)r3   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.r?   )r   r-   Zcpu_device_name_at_coordinatesr3   r   r   r?   r   r   r   r   host_device      zDeviceAssignment.host_devicec                 C   r@   )z>Returns the name of the TPU device assigned to a logical core.rA   )r   r-   Ztpu_device_name_at_coordinatesrB   r   r   r   
tpu_device   rD   zDeviceAssignment.tpu_devicer   computation_shapecomputation_strider:   device_order_modec                 C   s   t |||||dS )N)r   rF   rG   r:   rH   )device_assignment)clsr   rF   rG   r:   rH   r   r   r   build   s   	zDeviceAssignment.build)r   r   )r   r   N)r   r   r   r   r   r*   ndarrayr4   propertyr   intr9   r:   r   r   r   r   r=   r>   r   strrC   rE   classmethodr   r    rK   r   r   r   r   r"   D   sp    %

	
r"   x_sizey_sizez_coordr5   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)rQ   rR   rS   retijr   r   r   _open_ring_2d   s   rX   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   .0rV   r   r   r   
<listcomp>'      z_ring_3d.<locals>.<listcomp>c                 S   s   g | ]}d |d fqS rZ   r   r[   r   r   r   r]   )  r^   c                 S   s   g | ]}|d d fqS rZ   r   r[   r   r   r   r]   +  r^   r   r   zOdd dimensionc                 3   s    | ]}| fV  qd S Nr   )r\   xyzr   r   	<genexpr>6  s    z_ring_3d.<locals>.<genexpr>)r   r   r   c                 s   s     | ]\}}}|||fV  qd S r_   r   )r\   r`   rc   rb   r   r   r   rd   B      c                 s   s     | ]\}}}|||fV  qd S r_   r   )r\   rb   rc   r`   r   r   r   rd   F  re   r%   )r	   loggingwarningextendrX   reversedrT   )rQ   rR   rY   rU   rV   rr   ra   r   _ring_3d   sR   6


 rk   r   r   rF   rG   r:   rH   c           2   	      sB  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rDd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|| qtqt|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sNJ |t  | j"| j# ks^J | j$}+g }t },t|D ].}-g }.t|,D ]}|-|, | }/|/| j# }0|/| j# }1|.|+|0|1ddf  qt||. qlt%| |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.
  )Z
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   )r\   rV   r`   )topology_rankr   r   rd     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 rZ   )r*   Zaranger[   )rF   rG   r   r   r]     s    z%device_assignment.<locals>.<listcomp>c                 S   s   g | ]	}|d t jf qS ).)r*   newaxisr[   r   r   r   r]     s    ZindexingZij)Zaxis)r   )&r&   bytesr   r'   r)   len
mesh_shaper*   arrayr,   r+   r
   anyr(   prodZmissing_devicessizer   	enumeraterN   mathceilminfullr   r    r!   rk   r	   rT   ZconcatenateZmeshgridZreshaperq   Z	num_tasksZnum_tpus_per_taskdevice_coordinatesr"   )2r   rF   rG   r:   rH   rt   Zcomputation_footprintZblock_countsZreplica_countsZmax_replicasrn   Zreplica_shapeZremaining_replicasZremaining_dimsr`   nirV   Ztarget_sizeZreplica_offsetsZenable_3d_tilingZ
assignmentZ
inner_ringZ
outer_ringr   Zouter_xZouter_yZouter_zZper_replica_assignmentindexZinner_xZinner_yZinner_zZpxpyZpzpitposdimZreplica_posouterinnerindicesr~   Zdevices_per_replicarindexZreplica_assignmentZ
logical_idr   Zdevicer   )rF   rG   ro   r   rI   V  s  
0








 




rI   )r   enumrz   typingr   r   r   numpyr*   Ztensorflow.python.platformr   rf   Ztensorflow.python.tpu.topologyr   Z tensorflow.python.util.tf_exportr   ZSINGLE_CORE_ASSIGNMENTr   IntEnumr   objectr"   rN   rX   rk   r    rL   rI   r   r   r   r   <module>   sT    


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