o
    i0(                     @   sJ   d dl mZmZ e rddlZdd Zdd Zdd	 ZG d
d deZdS )   )PushToHubMixinis_torch_available    Nc                 C   sV   d}zt |  }W n ty   td| w |jj}|dkr)tjjdur)dS |S )z
    Infers the device type from the model parameters.
    Args:
        model: The model instance.

    Returns:
        The device type.
    z
    {
        "RMSNorm": {
            "cuda":
                "kernels-community/layer_norm:LlamaRMSNorm",
            ...
        },
        ...
    }
    zPCannot determine model device, please provide a device to the mapping. Example: cudaNrocm)	next
parametersStopIteration
ValueErrordevicetypetorchversionhip)modelEXAMPLE_MAPPINGparamdev_type r   b/sda-disk/www/egybert/egybert_env/lib/python3.10/site-packages/transformers/utils/kernel_config.pyinfer_device   s   	
r   c                 C   sZ   ddl m} |dvrtd| |dd }|dd }|||||dii|| < d S )Nr   LayerRepositoryr   r   xpunpu5Only cuda, rocm, xpu and npu devices supported, got: :   )repo_id
layer_name)kernelsr   r
   split)r    r   	repo_namemodecompatible_mappingr   repo_layer_namer   r   r   r   add_to_mapping9   s   r'   c           
      C   sz   ddl m} ddlm} |dvrtd| |dd }|dd }|dd	 }	||||||	|d
ii|| < d S )Nr   )Path)LocalLayerRepositoryr   r   r   r   /)	repo_pathpackage_namer    )pathlibr(   r!   r)   r
   r"   )
r    r   r#   r$   r%   r(   r)   r&   r,   repo_package_namer   r   r   add_to_mapping_localJ   s   r0   c                   @   sB   e Zd ZdZi dfddZdddZdd	 Zd
d ZdddZdS )KernelConfigze
    Kernel configuration class. This class is used to configure the kernel mapping for a model.
    Fc                 C   s   || _ i | _|| _d S N)kernel_mappingregistered_layer_namesuse_local_kernel)selfr3   r5   r   r   r   __init__d   s   
zKernelConfig.__init__Nc                 C   s,   ddl m} ||||||dii| j|< d S )Nr   r   )r   r    revision)r!   r   r3   )r6   r   registered_namer    r   r$   r8   r   r   r   r   update_kerneli   s   zKernelConfig.update_kernelc                 C   s,   |  D ]\}}t|dr|j| j|< qd S )Nkernel_layer_name)named_moduleshasattrr;   r4   )r6   r   namemoduler   r   r   store_registered_layer_namesv   s
   
z)KernelConfig.store_registered_layer_namesc                 C   s  d}|  | t| jtstd| dt| j | j D ]e\}}|| j vr2td| dt|t	rJd|vs?d|vrItd| d	| qt|tr{| D ]&\}}|d
vrbtd| t|t	rod|vsod|vrytd| d	| qSqtd| d| dS )aJ  
        Validates the kernel_mapping to ensure that:
        1. Each layer_name in the mapping is registered in the model (i.e., the model contains a module with a matching kernel_layer_name).
        2. Each kernel value is either a string of the form 'org/repo:layer_name' or a dict mapping device types ("cuda", "rocm", "xpu", "npu") to such strings.
        3. Each device key in a dict is one of "cuda", "rocm", "xpu", or "npu".
        4. Each repo_name is a valid repository and layer name in the format 'org/repo:layer_name' (i.e., a string containing both a slash and a colon).
        5. If a local path is detected, it should be in the format '/abs/path:layer_name'. The absolute path must include the `package_name`, like "/home/user/layer_norm".

        Args:
            model: The model instance whose modules are checked for registered kernel_layer_name attributes.

        Raises:
            ValueError: If a layer_name is not registered in the model, if a device is not supported,
                        or if a repo_name is not a valid 'org/repo:layer_name' string.
        a  
        For single device form remote
        {
            "RMSNorm":
                "kernels-community/layer_norm:LlamaRMSNorm",
            ...
        },
        For multiple devices form remote
        {
            "RMSNorm": {
                "cuda":
                    "kernels-community/layer_norm:LlamaRMSNorm",
                "rocm":
                    "kernels-community/layer_norm:LlamaRMSNorm",
                ...
            },
            ...
        }
        For single device form local
        {
            "RMSNorm":
                "/abs/path:LlamaRMSNorm",
            ...
        },
        For multiple devices form local
        {
            "RMSNorm": {
                "cuda":
                    "/abs/path:LlamaRMSNorm",
                "rocm":
                    "/abs/path:LlamaRMSNorm",
                ...
            },
            ...
        }
        z7Kernel mapping must be a dict of the following format: z, got: zLayer z` is not registered in the model, please register it first using register_kernel_forward_from_hubr*   r   zKernel mapping for 'zl' must be a valid repo name with a layer name (e.g., 'org/repo:layer_name' or '/abs/path:layer_name'), got: r   r   z'Kernel mapping must follow the format: N)
r@   
isinstancer3   dictr
   r   itemsr4   valuesstr)r6   r   MAPPING_FORMATr    kernelr   r#   r   r   r   sanitize_kernel_mapping{   s:   
$


	z$KernelConfig.sanitize_kernel_mappingc                 C   s   ddl m} i }t|}| j D ]W\}}|jr|jn|j}|r%||jB }t	|t
rA|}	| js8t|||	|| qt|||	|| qt	|trh| D ]\}
}	|
|krSqJ| js_t||
|	|| qJt||
|	|| qJq|| _dS )aW  
        Transforms a simple kernel_mapping of the form:
            {
                "RMSNorm":
                    "kernels-community/layer_norm:LlamaRMSNorm",
                ...
            },

            or for local path:

            {
                "RMSNorm":
                    "/home/user/liger_kernels:LigerRMSNorm",
                ...
            },

        into a nested mapping:

            {
                "RMSNorm": {
                    "cuda": {
                        Mode.INFERENCE: LayerRepository(
                            repo_id="kernels-community/layer_norm",
                            layer_name="LlamaRMSNorm",
                        )
                    }
                }
            }

            or for local path:

            {
                "RMSNorm": {
                    "cuda": {
                        Mode.INFERENCE: LocalLayerRepository(
                            repo_path=Path("/home/user/liger_kernels"),
                            package_name="liger_kernels",
                            layer_name="LigerRMSNorm",
                        )
                    }
                }
            }

        that's compatible with the kernels library.

        The device is inferred from the model's parameters if not provided.
        The Mode is inferred from the model's training state.
        r   )ModeN)r!   rI   r   r3   rC   trainingTRAINING	INFERENCETORCH_COMPILErA   rE   r5   r'   r0   rB   )r6   r   compilerI   r%   current_devicer    rG   r$   r#   r   r   r   r   create_compatible_mapping   s*   1



z&KernelConfig.create_compatible_mappingr2   )F)	__name__
__module____qualname____doc__r7   r:   r@   rH   rP   r   r   r   r   r1   _   s    
Sr1   )utilsr   r   r   r   r'   r0   r1   r   r   r   r   <module>   s   #