
    ijC                         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Z	ddZ
d Zd	 Zd
 Zd Zd Zd Zd Zd Zd Zy)z5Utilities for distribution strategy with JAX backend.    N)seed_generator)	jax_utils)	rng_utilsc                     | r| j                         nd} t        j                  |       }|D cg c]  }|j                   d|j                    c}S c c}w )a  Return all the available devices based on the device type.

    Note that this should return the global devices in a distributed setting.

    Args:
        device_type: string of `"cpu"`, `"gpu"` or `"tpu"`. Defaults to `"gpu"`
            or `"tpu"` if available when device_type is not provided. Otherwise
            will return the `"cpu"` devices.

    Return:
        List of devices that are available for distribute computation.
    Nbackend:)lowerjaxdevicesplatformid)device_typejax_devicesdevices      {/var/www/html/emotional.easysim.app/public_html/venv/lib/python3.12/site-packages/keras/src/backend/jax/distribution_lib.pylist_devicesr      sL     *5+##%$K++k2K;FGvq,GGGs   "Ac                 T    | r| j                         nd} t        j                  |       S )a  Returns the number of available JAX devices.
    Args:
        device_type: Optional device type to count (e.g., "cpu", "gpu", "tpu").
            If `None`, it defaults to counting "gpu" or "tpu" devices if
            available, otherwise it counts "cpu" devices. It does not
            return the sum of all device types.
    Returns:
        int: The total number of JAX devices for the specified type.
    N)r
   r   device_count)r   s    r   get_device_countr      s'     *5+##%$KK((    c                 4   ddl m} t        ||      r|j                  }t	        j
                  |       r t        j                  j                  | |      S t        | t        j                        rt        |t        j                  j                        r2| j                  j                  |t        | j                              r| S t        |d      rt!        | dd      }||k(  r"| S t        |d      rt!        | dd      }||k(  r| S t        j"                  | |      S )a  Distribute the tensor based on the layout.

    Note that this function can be used both in eager context, or within a
    jitted function.

    Args:
        tensor: `jax.Array` that need to be distributed.
        layout: `TensorLayout` for the created variable, or a
            JAX-supported layout instance (e.g. `jax.sharding.Sharding`).

    Returns:
        Distributed value.
    r   TensorLayout)ndimlayoutNformat)keras.src.distributionr   
isinstancebackend_layoutr   is_in_jax_tracing_scoper   laxwith_sharding_constraintArrayshardingShardingis_equivalent_tolenshapehasattrgetattr
device_put)tensorr   r   current_layouts       r   distribute_tensorr/   +   s     4&,'&&((0ww//?? &#))$CLL))
oo..vC<M.NMVX&$VXt<N'VX&$VXt<N'>>&&))r   c                 j    ddl m} t        ||      r|j                  }t	        j
                  ||       S )a  Distribute the input data with the corresponding layout.

    Note that the inputs here is a local worker batch. Within the local worker,
    the data need to be further partitioned to map to each of the devices.

    Args:
        inputs: `jax.Array` that is already sharded to a local process size.
        layout: `TensorLayout` for the distribution information, or a
            `jax.sharding.Sharding` instance.

    Returns:
        A global batch distributed according to `layout`.
    r   r   )r   r   r   r    r   "make_array_from_process_local_data)per_process_batchr   batch_dim_namer   s       r   distribute_data_inputr4   V   s0     4&,'&&11&:KLLr   c                     t        j                         } | t        j                  d      }t        j                  d      }t        j
                  j                  t        j                         g|z  t        j
                  j                        } t        j                  d d|      |      j                  d      } t        j                  |        yy)zInitializes the global random number generator across processes.

    This is required for consistent initialization in multi-host settings.
    Ncpu)dtypec                 B    t         j                  j                  | d      S )Nall)r   r"   psum)xs    r   <lambda>z initialize_rng.<locals>.<lambda>   s    cggll1e, r   r9   )	axis_namer   r   )r   get_random_seedr   r   local_device_countnumpyasarrayr   make_default_seeduint32pmapitemset_random_seed)global_seedcpu_devicesnum_local_cpu_devices
local_seeds       r   initialize_rngrK   m   s    
 ++-K  kk%( # 6 6u = YY&&--/03HH))"" ' 



chh,
 	 d1g	 	 	!!+.% r   c                     | rHd| v rD| j                  d      } |+|t        |       k7  rt        d|  dt        |        d|       | d   }n| }t        j                  j                  |||       t                y )N,zThe provided job_addresses z has z jobs, but num_processes is r   )coordinator_addressnum_processes
process_id)splitr(   
ValueErrorr   distributed
initializerK   )job_addressesrO   rP   rN   s       r   rT   rT      s    - &++C0 $#m:L)L-m_E}%&&B /# 
 ,A.+OO/#   r   c                  *    t        j                         S )zDReturn the number of processes for the current distribution setting.)r   process_count r   r   rO   rO          r   c                  *    t        j                         S )z;Return the current process ID for the distribution setting.)r   process_indexrX   r   r   rP   rP      rY   r   c                 8   t        | t        j                        r| S t        |       } d| vr| d}}n| j	                  d      \  }}t        j
                  |      }|D ].  }|j                  |k(  s|j                  t        |      k(  s,|c S  t        d|        )Nr	   r   r   zDevice not found: )
r   r   DevicestrrQ   r   r   r   intrR   )device_namer   	device_idr   r   s        r   _to_backend_devicerb      s    +szz*k"K
+!,aY!,!2!23!7Ykk+.G ??k)fii3y>.IM )+7
88r   c                 4   | j                   j                  }| j                   j                         D cg c]  }t        |       }}t	        j
                  |      j                  |      }t        j                  j                  || j                        S c c}w )zConvert the DeviceMesh to JAX backend specific Mesh.

    Args:
        device_mesh: DeviceMesh instance to convert.

    Returns:
        A `jax.sharding.Mesh` instance.
    )r   r)   flattenrb   nparrayreshaper   r%   Mesh
axis_names)device_meshr)   dr   s       r   _to_backend_meshrl      sy     %%E.9.A.A.I.I.KL!!$LGLhhw''.G<<Wk&<&<== Ms   Bc                     | j                   t        d      t        j                  j                  | j
                   }| j                   j                  }t        j                  j                  ||      S )zConvert the TensorLayout to JAX backend specific Sharding.

    Args:
        tensor_layout: TensorLayout instance to convert.

    Returns:
        A `jax.sharding.NamedSharding` instance.
    zDCannot create sharding when device mesh is not set for TensorLayout.)rj   rR   r   r%   PartitionSpecaxesbackend_meshNamedSharding)tensor_layoutpartition_specjax_meshs      r   _to_backend_layoutru      sf       ( 
 	
 \\//1C1CDN((55H<<%%h??r   )N)__doc__r   r@   re   keras.src.randomr   keras.src.utilsr   r   r   r   r/   r4   rK   rT   rO   rP   rb   rl   ru   rX   r   r   <module>ry      sR    ; 
  + % %H$)(*VM./:6

9 >@r   