o
    Me                     @   sN   d Z ddlZddlm  mZ ddlmZ g dZ	dd Z
dd Zd	d
 ZdS )z(Keras Utilities for DTensor related API.    N)dtensor_api)alphabetaZbiasZ	depthwiseZ
embeddingsgammaZkernelZmoving_meanZmoving_varianceZ	pointwiseZ	recurrentc                        fdd}t jjj |dS )a  A decorator for injecting layout information to layer.__init__.

    Layout will be a new param for any of the weights for all the keras layers.
    Adding the param to all the __init__ method will be a big/duplicated work.

    This decorator is design to reduce and code duplication and make it easy to
    add/remove the dtensor feature if needed.

    Sample usage:
    ```python
    class Dense(tf.keras.layer.Layer):

      @allow_initializer_layout
      def __init__(self, units,
                   kernel_initializer='zeros',
                   bias_initializer='zeros',
                   **kwargs):
         super().__init__(**kwargs)

    d = Dense(units=8, kernel_layout=layout1, bias_layout=layout2)
    d.kernel_layout == layout1
    d.bias_layout == layout2
    ```

    By adding this annotation, it will:

    1. Filter out the kwargs based on some keywords, eg if the
      'kernel_initialzer' appears in method signature, then it will try to pop
      the 'kernel_layout' if it presents. Same for "bias" and
      "recurrent_kernel", etc. This will make sure the layout related param is
      not passed to `BaseLayer.__init__`, which will raise error about unexpect
      keyword args.
    2. Set the self.kernel/bias_layout attribute after the `__init__` method is
       called. Keras framework will use those fields to create weights down the
       stream.

    Args:
      init_method: the `__init__` method of the Keras layer to annotate.

    Returns:
      the annotated __init__ method.
    c                    s~   t  }i }tD ]}|d |jv r"||d d }|r"|||d < q	 | g|R i | | D ]
\}}t| || q2d S )NZ_initializerZ_layout)inspect	signatureKERAS_VARIABLE_NAMES
parameterspopitemssetattr)Zlayer_instanceargskwargsr   Zlayout_argsZvariable_namelayoutZlayout_param_nameinit_method CD:\Projects\ConvertPro\env\Lib\site-packages\keras/dtensor/utils.py_wrap_functionU   s   
z0allow_initializer_layout.<locals>._wrap_functiontargetZdecorator_functfZ__internal__	decoratorZmake_decoratorr   r   r   r   r   allow_initializer_layout)   s   ,r   c                    r   )a  Inject DTensor mesh information to an object.

    This is useful for keras object like `Metric` and `Optimizer` which need
    DTensor mesh to create the weights, but doesn't want to change the current
    public API interface.

    This is for temporary usage and eventually the mesh/layout information will
    be public arguments in the `__init__` method.

    Sample usage:
    ```python
    class Accuracy(tf.keras.metrics.Metric):

      @inject_mesh
      def __init__(self, name='accuracy', dtype=None):
         super().__init__(**kwargs)

      acc = Accuracy(mesh=mesh)
      assert acc._mesh == mesh
    ```

    Args:
      init_method: the `__init__` method of the Keras class to annotate.

    Returns:
      the annotated __init__ method.
    c                    s4   | dd }|d ur|| _ | g|R i | d S )Nmesh)r   Z_mesh)instancer   r   r   r   r   r   r      s   z#inject_mesh.<locals>._wrap_functionr   r   r   r   r   r   inject_meshl   s   	r   c                 O   sX   |r%t |j | |i |}t ||W  d   S 1 s w   Y  | |i |S )a  Invoke the function with inputs and relayout the result.

    Args:
      fn: the function to invoke.
      layout: if not None, the output of the fn will be relayout with this.
      *args: positional arguments to be called with fn.
      **kwargs: keyword arguments to be called with fn.

    Returns:
      The output of fn, with potential relayout with the layout specified.
    N)dtensorZrun_onr   Zrelayout)fnr   r   r   resultr   r   r   call_with_layout   s   
 r#   )__doc__r   Ztensorflow.compat.v2compatv2r   Zkeras.dtensorr   r    r	   r   r   r#   r   r   r   r   <module>   s   C+