o
    2hW!                     @   s   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dZd	d
 Zdd Zdd Zdd Zdd Zdd Zdd Zdd Zdd Zdd ZdS )z5Utilities for distribution strategy with JAX backend.    N)global_state)seed_generator)	jax_utils)	rng_utilsc                 C   s*   | r|   nd} tj| d}dd |D S )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backendc                 S   s   g | ]}|j  d |j qS ):)platformid).0device r   a/var/www/html/chatgem/venv/lib/python3.10/site-packages/keras/src/backend/jax/distribution_lib.py
<listcomp>   s    z list_devices.<locals>.<listcomp>)lowerjaxdevices)device_typejax_devicesr   r   r   list_devices   s   r   c                 C   s
   t | |S )a  Create a distributed variable for JAX.

    Since JAX doesn't have a variable class, this will just return a `jax.Array`
    with the corresponding layout/sharding specified.

    Note that this function should be used in eager context, not in jitted
    function.

    Args:
        value: the initial value of the variable.
        layout: `TensorLayout` for the created variable, or a
            JAX-supported layout instance (e.g. `jax.sharding.Sharding`).

    Returns:
        jax.Array which is the distributed variable.
    )distribute_tensor)valuelayoutr   r   r   distribute_variable   s   
r   c                 C   s   ddl m} t||r|j}t rtj| |S t| tj	rVt|tj
jr3| j
j|t| jdr3| S t|drEt| dd}||krD| S nt|drVt| dd}||krV| S t| |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)ndimr   N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_layoutr   r   r   r   2   s,   


r   c                 C   s(   ddl m} t||r|j}t|| 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   r   r   r   distribute_data_input_   s   
r2   c                  C   s   t  } | du r5td}td}tjjt g| tjj	d}tj
dd d|d|d} t |  td	}|durX| d
 }|du rZtd	tj| |j|jd dS dS dS )zInitializes the global random number generator across processes.

    This is required for consistent initialization in multi-host settings.
    Ncpu)dtypec                 S   s   t j| dS )Nall)r   r"   psum)xr   r   r   <lambda>   s    z initialize_rng.<locals>.<lambda>r5   )	axis_namer   r   global_seed_generatorseed)r;   namer   )r   get_random_seedr   r   local_device_countnumpyasarrayr   make_default_seeduint32pmapitemset_random_seedr   get_global_attribute
get_configset_global_attributeSeedGeneratorr<   r   )global_seedcpu_devicesnum_local_cpu_devices
local_seedr:   r;   r   r   r   initialize_rngv   sD   


rN   c                 C   sr   | r)d| v r)|  d} |d ur$|t| kr$td|  dt|  d| | d }n| }tjj|||d t  d S )N,zThe provided job_addresses z has z jobs, but num_processes is r   )coordinator_addressnum_processes
process_id)splitr(   
ValueErrorr   distributed
initializerN   )job_addressesrQ   rR   rP   r   r   r   rV      s$   


rV   c                   C      t  S )zDReturn the number of processes for the current distribution setting.)r   process_countr   r   r   r   rQ         rQ   c                   C   rX   )z;Return the current process ID for the distribution setting.)r   process_indexr   r   r   r   rR      rZ   rR   c                 C   sb   t | tjr| S | d\}}tj|d}|D ]}|j|kr)|jt|kr)|  S qtd|  )Nr   r   zDevice not found: )	r   r   DevicerS   r   r	   r
   intrT   )device_namer   	device_idr   r   r   r   r   _to_backend_device   s   r`   c                 C   s<   | j j}dd | j  D }t||}tj|| j	S )zConvert the DeviceMesh to JAX backend specific Mesh.

    Args:
        device_mesh: DeviceMesh instance to convert.

    Returns:
        A `jax.sharding.Mesh` instance.
    c                 S   s   g | ]}t |qS r   )r`   )r   dr   r   r   r      s    z$_to_backend_mesh.<locals>.<listcomp>)
r   r)   flattennparrayreshaper   r%   Mesh
axis_names)device_meshr)   r   r   r   r   _to_backend_mesh   s   	ri   c                 C   s6   | j du r	tdtjj| j }| j j}tj||S )zConvert the TensorLayout to JAX backend specific Sharding.

    Args:
        tensor_layout: TensorLayout instance to convert.

    Returns:
        A `jax.sharding.NamedSharding` instance.
    NzDCannot create sharding when device mesh is not set for TensorLayout.)rh   rT   r   r%   PartitionSpecaxesbackend_meshNamedSharding)tensor_layoutpartition_specjax_meshr   r   r   _to_backend_layout   s   
	rq   )N)__doc__r   r?   rc   keras.src.backend.commonr   keras.src.randomr   keras.src.utilsr   r   r   r   r   r2   rN   rV   rQ   rR   r`   ri   rq   r   r   r   r   <module>   s$    
-.