a
    h,                     @   sv  d dl Z d dlZd dlZd dlZd dlmZ d dlmZ d dlm	Z	m
Z
mZmZ d dlZd dlmZ d dlmZ eeZG dd deZed	d
G dd dZed	d
G dd dZeee e
dddZe jeeee f edddZedddZeeee f edddZ eeee f eddddZ!eeeee f dddZ"eeeee f d d!d"Z#dS )#    N)	Generator)	dataclass)AnyCallableOptionalUnion)_maybe_get_opdef)FileLikec                   @   s   e Zd ZdZdS )MissingOpProfilezc
    This is raised when we don't have an operator profile available for the
    given inputs.
    N)__name__
__module____qualname____doc__ r   r   I/var/www/auris/lib/python3.9/site-packages/torch/_library/fake_profile.pyr
      s   r
   T)frozenc                   @   sL   e Zd ZU eed< ejed< ejed< ejed< e	e
ed  dddZdS )	TensorMetadatarankdtypedevicelayouttreturnc                 C   s(   t | tjsd S t|  | j| j| jS N)
isinstancetorchTensorr   Zdimr   r   r   r   r   r   r   maybe_from_tensor   s    z TensorMetadata.maybe_from_tensorN)r   r   r   int__annotations__r   r   r   r   staticmethodr   r   r   r   r   r   r   r      s   



r   c                   @   s2   e Zd ZU eee  ed< eeee f ed< dS )	OpProfileargs_profileout_profileN)r   r   r   tupler   r   r!   r   r   r   r   r   r#   &   s   
r#   )op_name
op_profiler   c                    s\   t tt  ttdddttt t f ttjttj f ddd  fdd}|S )	N)r$   argsr   c                    s   t  fddt|D S )Nc                 3   s$   | ]\}}t | | kV  qd S r   )r   r   ).0iargr$   r   r   	<genexpr>.   s   z=_generate_fake_kernel.<locals>._match_args.<locals>.<genexpr>)all	enumerate)r$   r)   r   r-   r   _match_args-   s    z*_generate_fake_kernel.<locals>._match_args)r%   r   c                    sH   t j tt jdfdd t| tr2 | S  fdd| D S d S )Nr   c                    sj    fddt | jD }dg| j }d}|}t | jD ]}|||< |||  }q6tj||| j| j| jdS )Nc                    s   g | ]}   qS r   )Znew_dynamic_size)r*   _ctxr   r   
<listcomp>9       z^_generate_fake_kernel.<locals>._generate_res.<locals>._generate_tensor_out.<locals>.<listcomp>   )r   r   r   )ranger   r   Zempty_stridedr   r   r   )r   Z
fake_shapeZfake_stridesexpectedZfake_strider+   r3   r   r   _generate_tensor_out8   s    zJ_generate_fake_kernel.<locals>._generate_res.<locals>._generate_tensor_outc                    s   g | ]} |qS r   r   )r*   r   )r;   r   r   r5   L   r6   z@_generate_fake_kernel.<locals>._generate_res.<locals>.<listcomp>)r   libraryZget_ctxr   r   r   )r%   r   )r;   r4   r   _generate_res3   s
    

z,_generate_fake_kernel.<locals>._generate_resc                     sP   D ],}|j g | | R r |j  S qtd d| |f dd S )NzNo fake kernel was found for zz, and although we have previously registered some profiles to generate a fake kernel, no profiles match the given inputs: .)r$   valuesr%   r
   )r)   kwargsprofiler=   r1   r'   r(   r   r   _fake_kernelN   s    z+_generate_fake_kernel.<locals>._fake_kernel)	r&   r   r   r   boolr   r   r   list)r'   r(   rC   r   rB   r   _generate_fake_kernel,   s    rF   )op_profilesr   c              
   c   sN  g }i }|   D ]\}}td| |d}|d |d  }}| d| }t||}	t| }
r|
jdurx|
j||< |
|	 qtj	
|d}tj	j||	|dd	 || qzL|V  W |D ]}|  q|  D ]&\}}t|}
|
dusJ |
| qnJ|D ]}|  q|  D ]*\}}t|}
|
dus:J |
| q0 dS )
aH  
    Registers a fake kernel based on the given operator profiles. This fake
    kernel registration will override any existing fake kernel registrations.

    The input is a dictionary mapping operator names to a set of operator
    profiles, which we will use to generate fake kernels. The operator profiles
    are a record of the input and output tensor metadata. Based on this
    information we will match a given input to the recorded profile, and return
    an output with the same metadata as in the recorded profile. If a profile
    doesn't exist then an exception will be thrown.

    The fake kernel generation is considerd unsafe because it relies on the
    rigid, pre-defined operator profiles that do not account for potential
    variations in output behavior. Specifically, the generated kernels assume a
    fixed relationship between input and output ranks. However, in reality, it's
    possible that data-dependent operations may produce outputs of different
    ranks even when given inputs of the same rank. The generated fake kernels
    are inflexible and unable to accommodate these nuances, making them
    potentially unsafe.

    Args:
        op_profiles (dict[str, set[OpProfile]]): A dictionary mapping operator
            name to a set of operator profiles from which we will generate fake
            kernels.

    Examples:

        >>> # Example: Registering an op-profile from draft-export
        >>> import torch
        >>> from torch.export._draft_export import draft_export
        >>>
        >>> @torch.library.custom_op("mylib::foo", mutates_args=())
        >>> def foo(x: Tensor, y: Tensor) -> Tensor:
        >>>     return x + y
        >>>
        >>> class M(torch.nn.Module):
        >>>     def forward(self, a, b):
        >>>         res = torch.ops.mylib.foo(a, b)  # no fake impl
        >>>         return res
        >>>
        >>> ep = draft_export(M(), (torch.ones(3, 4), torch.ones(3, 4))
        >>>
        >>> with torch._library.fake_profile.unsafe_generate_fake_kernels(ep._report.op_profiles):
        >>>     decomp = ep.run_decompositions()

    zZRegistering fake profile for %s. This will override any existing fake kernel registration.r>   r   r8   z::NZFRAGMENTT)libZallow_override)itemslogwarningsplitrF   r   Z_abstract_fnZregister_faker   r<   LibraryappendZ_destroy)rG   ZlibsZold_fake_implsr'   profilesZop_name_split	namespaceZop_name_strZop_strZfake_kernelZopdefZnewlibrH   Zold_faker   r   r   unsafe_generate_fake_kernels\   sD    1




rQ   )r   c                  C   s*   t jd} t| d  dt| d  S )Nr>   r   r8   )r   __version__rL   r    )versionr   r   r   get_torch_version   s    rT   c                    sn   ddl }ddlm m ttd fddttdfdd	fd
d|  D }|jt	 |dddS )z
    Generates a yaml string from the given operator profiles which can be saved
    to a file. The yaml string can be loaded back into an operator profile
    structure using `read_profiles_from_yaml`.
    r   N_TORCH_TO_SERIALIZE_DTYPE_TORCH_TO_SERIALIZE_LAYOUTr   c                    s&   | j  | j jt| j| j jdS )Nr   r   r   r   )r   r   valuestrr   r   r   rU   r   r   serialize_tensor_metadata   s
    

z>generate_yaml_from_profiles.<locals>.serialize_tensor_metadata)opr   c                    s@    fdd| j D t| jtr( | jn fdd| jD dS )Nc                    s   g | ]}|d ur |qS r   r   r*   r,   r[   r   r   r5      s   zMgenerate_yaml_from_profiles.<locals>.serialize_op_profile.<locals>.<listcomp>c                    s   g | ]} |qS r   r   r*   outr^   r   r   r5      r6   r$   r%   )r$   r   r%   r   )r\   r^   r   r   serialize_op_profile   s    

z9generate_yaml_from_profiles.<locals>.serialize_op_profilec                    s$   i | ]\}}| fd d|D qS )c                    s   g | ]} |qS r   r   r*   rA   rb   r   r   r5      r6   z:generate_yaml_from_profiles.<locals>.<dictcomp>.<listcomp>r   r*   operatorrO   rd   r   r   
<dictcomp>   s   z/generate_yaml_from_profiles.<locals>.<dictcomp>)torch_version	operatorsF)	sort_keys)
yamltorch._export.serde.serializerV   rW   r   dictr#   rI   dumprT   )rG   rk   Zserialized_datar   )rV   rW   rb   r[   r   generate_yaml_from_profiles   s    

ro   )rG   fr   c                 C   s   t | }t|ttjfrXt|}t|d}|| W d   q1 sL0    Y  n,t|tj	rv||
d ntd| dS )z
    Serializes the given operator profiles into a yaml format and saves it to
    the given file. The operator profile can be loaded back using `load_op_profiles`.
    wNutf-8Invalid type of file )ro   r   rZ   osPathLikefspathopenwriteioBytesIOencode
ValueError)rG   rp   yaml_strfiler   r   r   save_op_profiles   s    
*r   )r}   r   c                    s   ddl }ddlm m ttd fddttdfdd|| }|d	 }|t krtt	d
| dt  |d }fdd|
 D S )zW
    Reads the yaml saved by `save_op_profiles` and returns the operator profiles.
    r   N_SERIALIZE_TO_TORCH_DTYPE_SERIALIZE_TO_TORCH_LAYOUT)datar   c                    s.   t | d  | d  t| d | d  dS )Nr   r   r   r   rX   )r   r   r   )r   r   r   r   deserialize_tensor_metadata  s    

z<read_profiles_from_yaml.<locals>.deserialize_tensor_metadatac                    sV   t  fdd| d D }| d }t|trBt  fdd|D n |}t||dS )Nc                 3   s   | ]} |V  qd S r   r   r]   r   r   r   r.     s   zJread_profiles_from_yaml.<locals>.deserialize_op_profile.<locals>.<genexpr>r$   r%   c                 3   s   | ]} |V  qd S r   r   r_   r   r   r   r.     r6   ra   )r&   r   rE   r#   )r   r$   Zout_profile_datar%   r   r   r   deserialize_op_profile  s    z7read_profiles_from_yaml.<locals>.deserialize_op_profilerh   zBUnable to load outdated profile. It was saved with torch version: z# but the current torch version is: ri   c                    s$   i | ]\}}| fd d|D qS )c                    s   h | ]} |qS r   r   rc   r   r   r   	<setcomp>.  r6   z5read_profiles_from_yaml.<locals>.<dictcomp>.<setcomp>r   re   r   r   r   rg   -  s   z+read_profiles_from_yaml.<locals>.<dictcomp>)rk   rl   r   r   rm   r   r#   Z	safe_loadrT   RuntimeErrorrI   )r}   rk   Zloaded_dataZloaded_torch_versionZoperators_datar   )r   r   r   r   r   read_profiles_from_yaml  s$    


r   )rp   r   c                 C   s~   t | ttjfrLt| } t| }| }W d   qv1 s@0    Y  n*t | tjrh|  	d}nt
d|  t|S )zD
    Loads the saved operator profiles from `save_op_profiles`.
    Nrr   rs   )r   rZ   rt   ru   rv   rw   readry   rz   decoder|   r   )rp   r~   r}   r   r   r   load_op_profiles3  s    

(r   )$
contextlibry   loggingrt   collections.abcr   Zdataclassesr   typingr   r   r   r   r   Ztorch._library.custom_opsr   Ztorch.typesr	   	getLoggerr   rJ   r   r
   r   r#   rZ   setrF   contextmanagerrm   rQ   rT   ro   r   r   r   r   r   r   r   <module>   s.   
0a-/