o
    Ei#                     @   s0  d dl Z d dlm  mZ d dlZd dlmZ d dlm	Z	m
Z
mZ d dlmZ e jjddddZe jjdddZe jjd	ddZe jd
Ze jjdddZdd Ze jdd dd"ddZe jd#ddZe jje jdd d		
	d$dede jdede
e jedf dedej de jfd d!Z!ee!_dS )%    N)partial)CallableUnionAnyPartitionSpecPzjax.sharding)from_NamedShardingMeshjaxnumpynp)as_c                 C   s2   | }|d urt |tjjjrdS |j}|d usdS )NTF)
isinstanceeinxexprstage3Compositionparent)r   node r   W/home/ubuntu/veenaModal/venv/lib/python3.10/site-packages/einx/experimental/op/shard.py_is_composed   s   r   c                       d fdd	S )Nc                    s    | ||S Nr   )expr_in	tensor_inexpr_outbackendctr   r   <lambda>   s
    <lambda>.<locals>.<lambda>r   r   r!   r    r   r   r   r"          r"   )tracec                 C   s   dd l }| |fD ]F}| D ]?}t|tjjjrtdt|tjjjrM|}|j	d urMt|j	tjjj
rEt|j	rE||j	jd urEtd|j	}|j	d us+qqtjj|| j|d}||g\}tj| g|g|d\\} \}tdd | D }	|d u rtt tdd |	D }
t|
tdd |	D d	}nFt||jjrtd
d |	D }tdd |jD }||std| d| nt|tdd |	D }
t|
tdd |	D d	}tdd | D }dd |D }t| }t ||}t!||}tj"| g|g|g|d\}|| fS )Nr   zConcatenation not allowedzhIf device axes are used within a composition they must appear as the left-most member of the composition)r   c                 s   s2    | ]}t |tjjjrtjj|r|V  qd S r   )r   r   r   r   Axis	is_marked.0axisr   r   r   	<genexpr>:   s    
zshard_stage3.<locals>.<genexpr>c                 s       | ]}|j V  qd S r   valuer*   ar   r   r   r,   B       c                 s   r-   r   namer0   r   r   r   r,   C   r2   )
axis_namesc                 s   r-   r   r3   r0   r   r   r   r,   F   r2   c                 s   s    | ]}t |V  qd S r   )strr0   r   r   r   r,   G   s    z9Marked axes must be subset of mesh axes. Got marked axes z and mesh axes c                 s   r-   r   r.   r0   r   r   r   r,   N   r2   c                 s   r-   r   r3   r0   r   r   r   r,   O   r2   c                 s   s$    | ]}t |tjjjr|V  qd S r   )r   r   r   r   r'   r)   r   r   r   r,   R   s   " c                 S   s$   g | ]}t jj|r|jnd qS r   )r   r   r   r(   r4   r)   r   r   r   
<listcomp>S   s   $ z shard_stage3.<locals>.<listcomp>)#r   allr   r   r   r   Concatenation
ValueErrorMarkerr   Listr   childrentracercall_factoryshapeall_to_tensorutilflattentupletnparraytjaxdevicesreshapetMeshshardingr
   setr5   issubsettPtNamedSharding
device_put	unflatten)r   r   r   meshr   r   rootr   childmarked_axesrH   marked_names
mesh_namesaxespartition_specrK   r   r   r   shard_stage3   s\   

"

rZ   Tc                    s  dd l }tjj| \} tjj| tdkr$t	dt  fdd}|d u r{z|g }W n tjj
yz }	 z5tjjtjjd d }
tj|
t| g}z||g}W n tjj
yo   |	w W Y d }	~	nTd }	~	ww t||jjrtjjtjjjdd |jD }
tj|
|jj}||g}n&t|ttfrtjjtjjd d }
tj|
t|g}||g}| }||fS )Nr      z%Expected exactly one expression, got c                    s>   t jjt jd d g|  dd  D   dd S )Nr   c                 S   s4   g | ]\}}t jj|t|d tjf dddqS ).N)depth1depth2)r   r   Equationr   asarraynewaxis)r*   kvr   r   r   r7   q   s    "z(parse.<locals>.solve.<locals>.<listcomp>)cse)r   r   solver^   items)eqsrc   op
parameterstensor_shaper   r   rd   m   s   zparse.<locals>.solvec                 S   s   g | ]	}t jj|qS r   )r   r   stage1	NamedAxis)r*   r4   r   r   r   r7      s    zparse.<locals>.<listcomp>)r   r   rh   rB   !_clean_description_and_parametersr   rk   parse_oplenr:   SolveExceptionr   
get_markedr^   rH   r   rK   r
   r;   r<   mayber5   r@   listrD   __deepcopy__)descriptionrj   rc   rR   jax_devicesri   r   rd   r   e	expr_meshmesh_eqr   r   rg   r   parse`   sH    	 
rz   c                    r   )Nc                    s    | |fd|i|S )NrR   r   )ru   tensorrR   r   kwargsr   r   r   r"      s    r#   NNr   r$   r   r   r   r"      r%   ru   r{   rR   r   rc   ri   returnc                 K   sP   |j dkr	tdt| tj|f||d|\}}t|||||d\}}|S )a
  Shards a tensor over a mesh of devices.

    *This function is currently experimental and will likely change in future versions.*

    *This function is currently only supported for Jax: A sharding is created
    based on the given expression, and applied to the tensor using* ``jax.device_put``.

    The tensor is sharded across the marked axes in the input expression. The marked axes
    match the axis names and shape of the mesh:

    >>> x = jnp.ones((2, 4, 128))
    >>> x = einx.experimental.shard("[d1 d2] c")
    >>> x.sharding
    NamedSharding(mesh=Mesh('d1': 2, 'd2': 4), spec=PartitionSpec('d1', 'd2', None))

    Axis compositions can be used to apply the
    `sharding rules of Jax <https://jax.readthedocs.io/en/latest/notebooks/Distributed_arrays_and_automatic_parallelization.html>`_,
    where tensor axes are evenly divided by the number of shards:

    >>> x = jnp.ones((128, 640, 480, 3))
    >>> x = einx.experimental.shard("([batch] _) ...", x)
    >>> x.sharding
    NamedSharding(mesh=Mesh('batch': 8), spec=PartitionSpec('batch',))

    If possible, the sharding is created over all devices. ``_`` is a regular axis name,
    and its value is determined by :doc:`einx's expression solver </faq/solver>`.

    Optionally, an existing mesh can be passed:

    >>> from jax.sharding import Mesh
    >>> devices = np.asarray(jax.devices()).reshape(4, 2)
    >>> mesh = Mesh(devices, axis_names=("d1", "d2"))
    >>> x = jnp.ones((4, 1024, 1024))
    >>> x = einx.experimental.shard("a ([d2] b) ([d1] c)", x, mesh=mesh)
    >>> x.sharding
    NamedSharding(mesh=Mesh('d1': 4, 'd2': 2), spec=PartitionSpec(None, 'd2', 'd1'))

    The array is replicated over all mesh axes that are not part of the expression:

    >>> x = jnp.ones((1024, 1024))
    >>> x = einx.experimental.shard("a ([d1] b)", x, mesh=mesh)
    >>> x.sharding
    NamedSharding(mesh=Mesh('d1': 4, 'd2': 2), spec=PartitionSpec(None, 'd1',))

    Args:
        description: Description string in Einstein notation (see above).
        tensor: Input tensor or tensor factory matching the description string.
        mesh: Mesh or list of devices to shard the tensor over. If not given, a new mesh over all
            available devices will be created matching the axes in the given expression.
            Defaults to ``None``.
        cse: Whether to apply common subexpression elimination to the expressions. Defaults
            to True.
        graph: Whether to return the graph representation of the operation instead of
            computing the result. Defaults to False.
        **parameters: Additional parameters that specify values for single axes, e.g. ``a=4``.

    Returns:
        The sharded tensor if ``graph=False``, otherwise the graph
        representation of the operation.
    r   z;einx.experimental.shard is currently only supported for Jax)rR   rc   )rR   r   )r4   NotImplementedErrorrz   r   r>   	get_shaperZ   )ru   r{   rR   r   rc   ri   r   r   r   r   r   shard   s   
J
r   r}   )TNN)Nr   T)"r   einx.op.utilrh   rB   r   r   	functoolsr   typingr   r   r   numpy.typingnptr>   import_rN   rO   rJ   rG   rE   r   jitrZ   	lru_cacherz   traceback_utilfilterr6   TensorBackendbool	ArrayLiker   r   r   r   r   <module>   sR    	A9
M