U
    Kc",                     @   s  d dl Z d dlmZ d dlmZmZmZmZ d dlm	Z	 d dl
Z
d dlZ
d dlZ
d dlZ
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 e ddd	 Ze dd
d ZG dd de
jjZG dd de
jjZdd ZddddZ G dd deZ!dS )    N)nullcontext)AnyCallableDictSequence)warn)NvfuserPrimOperatorSupport)torch_function_passthrough)get_isolated_graphmodulec               *   C   s  t t jft jt jjft jjt jjjft jt jjft jt jjft jt jjfg} t jjt jj	t jj
t jjt jjt jjt jjt jjt jjt jjt jjt jjt jjt jjt jjt jjt jjt jjt jjt jjt jjt jjt jjt jjt jjt jjt jj t jj t jj!t jj!t jj"t jj"t jj#t jj#t jj$t jj$t jj%t jj%t jj&t j'j(t jj)t j'j)i}| D ]0\}}|j*D ]}|j+,|||j+,|< q^qPt-t jD ].}|t jj*krt jj+,||t.t j|< q|S )z}
    Mapping of torch API functions to torch._refs functions.
    E.g. torch_to_refs_map()[torch.add] == torch._refs.add
    )/torchZ_refsnnZ
functionalspecialZfftZlinalgZTensor
__invert__Zbitwise_not__xor__Zbitwise_xor__and__Zbitwise_and__or__Z
bitwise_or__eq__eq__rsub__Zrsub__rtruediv__Zrtruediv__floordiv__Zfloor_divide__rfloordiv__Z	rfloordiv__pow__pow__rpow__ZrpowZ	new_emptyZnew_fullZ	new_zerosZnew_onesZfill_Zzero_toZsum_to_sizeZcopy__primsZcopy_toresize__all____dict__getdirgetattr)modulesrZ	mod_torchZmod_refss r&   8/tmp/pip-unpacked-wheel-gikjz4vx/torch/_prims/context.pytorch_to_refs_map   sr    	                     
 r(   c                   C   s   dd t jjD S )zJ
    Set of all prim functions, e.g., torch._prims.add in all_prims()
    c                 S   s   h | ]}t jj|qS r&   )r   r   r   r    ).0r%   r&   r&   r'   	<setcomp>L   s     zall_prims.<locals>.<setcomp>)r   r   r   r&   r&   r&   r'   	all_primsG   s    r+   c                   @   s8   e Zd ZdZddddZd
eeee eddd	Z	dS )NvfuserPrimsModea`  
    Switches the interpretation of torch.ops.prims.* functions to
    use nvFuser's prims in torch.ops.nvprims.*

    >>> # xdoctest: +SKIP("undefined vars")
    >>> with NvfuserPrimsMode():
    ...     torch.ops.prims.add(x, y)  # calls torch.ops.nvprims.add(x, y)

    By default, this context manager will fall back on the torch.ops.prims* if the
    nvprim does not exist.
    It's possible to skip certain prims by passing their names to the skip_ops
    argument. skip_ops is expected to be a sequence of strings, e.g.,
    ["prims.add.default"] In order to check the expected name of a prim, one can
    use the `torch.overrides.resolve_name`.

    >>> # xdoctest: +SKIP("undefined vars")
    >>> with NvfuserPrimsMode(skips_ops=("prims.add.default")):
    ...     torch.ops.prims.add.default(x, y)  # does not call torch.ops.nvprims.add.default(x, y)
    r&   skip_opsc                C   s
   || _ d S Nr-   selfr.   r&   r&   r'   __init__d   s    zNvfuserPrimsMode.__init__N	orig_functypesargskwargsc                 C   s   |d kri }t j|| jkr(|||S t|t jjsDt|t jjrt|	dd }t|	dd }|dkrt
t jj|d }|d k	r|||S |||S )N.r      Zprims)r   	overridesresolve_namer.   
isinstance_ops
OpOverloadOpOverloadPacketstrsplitr"   opsnvprims)r1   r4   r5   r6   r7   	namespacenameZnvfuncr&   r&   r'   __torch_function__g   s    
 
z#NvfuserPrimsMode.__torch_function__)r&   N)
__name__
__module____qualname____doc__r2   r   r   r   r   rF   r&   r&   r&   r'   r,   O   s     r,   c                   @   s>   e Zd ZdZddd efddZdeeee e	d	d
dZ
dS )TorchRefsModeaB  
    Switches the interpretation of torch.* functions and Tensor methods to
    use PrimTorch refs in torch._refs.  (Direct calls to _refs are unaffected.)

    >>> # xdoctest: +SKIP
    >>> with TorchRefsMode():
    ...     torch.add(x, y)  # calls torch._refs.add(x, y)

    By default, this context manager will fall back on the torch.* if the
    ref does not exist; set strict=True to error if this occurs.
    If the ref exists we still would like to fall back on the torch.* sometimes,
    this behavior can be customized by passing a function to should_fallback_fn.
    Fc                  G   s   dS )NFr&   )_r&   r&   r'   <lambda>       zTorchRefsMode.<lambda>c                 C   s   || _ || _|| _d S r/   strictshould_fallback_fnprims_mode_cls)r1   rP   rQ   rR   r&   r&   r'   r2      s    zTorchRefsMode.__init__r&   Nr3   c              
   C   s   |d kri }|t ks|t krD|   |||W  5 Q R  S Q R X t }||d }|d kr|t|tjjr|tj	j
|d }|d k	r| | ||||r|||S |  |||W  5 Q R  S Q R X | jrtdtj| |||S )Nzno _refs support for )r	   r+   rR   r(   r    r<   r   r=   r>   _decompZdecomposition_tablerQ   rP   RuntimeErrorr:   r;   )r1   r4   r5   r6   r7   mappingfuncr&   r&   r'   rF      s&    

z TorchRefsMode.__torch_function__)r&   N)rG   rH   rI   rJ   r   r2   r   r   r   r   rF   r&   r&   r&   r'   rK      s   
  rK   c                 C   s   | j dkot| jdd d k	S )Ncall_functionZimpl_nvfuser)opr"   target)noder&   r&   r'   _is_node_supported_nvfuser   s    
r[   r&   r-   c          
         s   t j||krdS | d zt|||}W nL tk
rv } z.td|j d t|  W Y W 5 Q R  dS d}~X Y nX W 5 Q R X t  t	dd |j
j}t fdd|D }	|	S )	a  
    This function traces the `func` under `torch_function_mode` and checks if
    any of the traced nodes are not supported by nvFuser. If so, we should
    fallback to the original function.

    `skip_ops` argument is expected to be a list of strings of function names
    that would match with `torch.overrides.resolve_name`.

    Args:
        torch_function_mode: The torch_function_mode context manager. orig_func:
        The original function, its name will be used to check if
                   it should be skipped.
        func: The function to be traced. args: The args to be passed to the
        function. kwargs: The kwargs to be passed to the function.
    Keyword args:
        skip_ops: A list of ops to skip when checking if the function is
        supported.
    Tz2get_isolated_graphmodule failed on decomposition: z with error message: Nc                 S   s
   | j dkS )NrW   )rX   )nr&   r&   r'   rM      rN   z._is_func_unsupported_nvfuser.<locals>.<lambda>c                 3   s   | ]}  d | V  qd S r/   )Zis_node_supported)r)   rZ   Zsupported_opsr&   r'   	<genexpr>   s    z/_is_func_unsupported_nvfuser.<locals>.<genexpr>)r   r:   r;   r
   	Exceptionr   rG   r@   r   filtergraphZnodesany)
Ztorch_function_moder4   rV   r6   r7   r.   ZgmeZcall_function_nodesZany_unsupportedr&   r]   r'   _is_func_unsupported_nvfuser   s,    ,rd   c                       sX   e Zd Zdd fdd
Zdd Zdd Zd	d
 Zdeeee	 e
d fddZ  ZS )TorchRefsNvfuserCapabilityModer&   r-   c                   s*   t  jdtjt|dtjt|dd d S )NFr-   rO   )superr2   	functoolspartialrd   r,   r0   	__class__r&   r'   r2      s     z'TorchRefsNvfuserCapabilityMode.__init__c                 C   s8   dt j|kp6t|t jjs,t|t jjo6dt|kS )Nztorch.var_meanzaten.var_mean)r   r:   r;   r<   r=   r>   r?   r@   r1   rV   r&   r&   r'   _is_var_mean  s    
z+TorchRefsNvfuserCapabilityMode._is_var_meanc                 C   s.   dt j|kp,|t jjjjkp,|t jjjkS )Nztorch.native_batch_norm)r   r:   r;   rB   atennative_batch_normdefaultrk   r&   r&   r'   _is_native_batch_norm  s    z4TorchRefsNvfuserCapabilityMode._is_native_batch_normc                 C   s2   dt j|kp,|t jjjkp,|t jjjjk}|S )Nztorch.rand_like)r   r:   r;   rB   rm   	rand_likero   )r1   rV   resultr&   r&   r'   _is_rand_like  s    z,TorchRefsNvfuserCapabilityMode._is_rand_likeNr3   c                    s~   |d kri }|  |r&tjjj||S | |r@tjjj||S | |rlt|dkr^t	d tjjj
| S t ||||S )Nr   zrand_like has ignored kwars!)rl   r   rB   rC   Zvar_meanrp   rn   rs   lenr   rq   rf   rF   )r1   r4   r5   r6   r7   ri   r&   r'   rF     s    


z1TorchRefsNvfuserCapabilityMode.__torch_function__)r&   N)rG   rH   rI   r2   rl   rp   rs   r   r   r   r   rF   __classcell__r&   r&   ri   r'   re      s   		
  re   )"rg   
contextlibr   typingr   r   r   r   warningsr   r   Ztorch._decompZtorch._primsZtorch._refsZtorch._refs.nnZtorch._refs.nn.functionalZtorch._refs.specialZtorch.overridesZtorch._prims.nvfuser_executorr   Ztorch._prims_commonr	   Z"torch.fx.experimental.proxy_tensorr
   	lru_cacher(   r+   r:   ZTorchFunctionModer,   rK   r[   rd   re   r&   r&   r&   r'   <module>   s0   
0
3A/