o
    H&iz                     @   s   U d dl Z d dlZd dlZd dlmZmZ d dlZd dlmZm	Z	 G dd dZ
dede
defd	d
Zdd Zeaeed< e jdd ZG dd dZdS )    N)CallableOptional)KernelRegistrationHandlec                   @   s4   e Zd ZdZdefddZdededefdd	Zd
S )AbstractImplHolderz4A holder where one can register an abstract impl to.qualnamec                 C   s   || _ d | _d | _d S N)r   kernellib)selfr    r   GC:\wamp64\www\opt\env\Lib\site-packages\torch/_library/abstract_impl.py__init__   s   
zAbstractImplHolder.__init__funcsourcereturnc                    s    j durtd j d j j dtj jdr$td j dtj jdr5td j dt|| _  jdu rP j	d	d
 }tj
|d _t j } j j|d  fdd}t|S )zRegister an abstract impl.

        Returns a RegistrationHandle that one can use to de-register this
        abstract impl.
        Nz!impl_abstract(...): the operator z, already has an abstract impl registered at .ZMetaz already has an DispatchKey::Meta implementation via a pre-existing torch.library or TORCH_LIBRARY registration. Please either remove that registration or don't call impl_abstract.ZCompositeImplicitAutograda-   already has an implementation for this device type via a pre-existing registration to DispatchKey::CompositeImplicitAutograd.CompositeImplicitAutograd operators do not need an abstract impl; instead, the operator will decompose into its constituents and those can have abstract impls defined on them.z::r   ZFRAGMENTc                      s     j r j   d  _ d  _d S r   )r
   Z_destroyr	   r   r   r   r   deregister_abstract_impl@   s   

z=AbstractImplHolder.register.<locals>.deregister_abstract_impl)r	   RuntimeErrorr   r   torchZ_CZ%_dispatch_has_kernel_for_dispatch_keyr   r
   splitZlibraryLibraryconstruct_meta_kernelimplr   )r   r   r   nsmeta_kernelr   r   r   r   register   s0   


zAbstractImplHolder.registerN)	__name__
__module____qualname____doc__strr   r   r   r   r   r   r   r   r   
   s    r   r   abstract_impl_holderr   c                    s.    j d usJ t j j fdd}|S )Nc                     s`   j d usJ j j  fdd}t| j | i |W  d    S 1 s)w   Y  d S )Nc                      s   t d  d d)Nz<Attempted to call get_ctx() for the meta implementation for z (implemented at z)You have presumably called get_ctx() because the operator has a data-dependent output shape; if so, there is no such meta implementation and this error is the correct behavior.)r   r   )r   r   r   r   error_on_ctxS   s   z@construct_meta_kernel.<locals>.meta_kernel.<locals>.error_on_ctx)r	   r   set_ctx_getter)argskwargsr$   r#   r   )r   r   r   N   s   

$z*construct_meta_kernel.<locals>.meta_kernel)r	   	functoolswrapsr   )r   r#   r   r   r(   r   r   I   s   r   c                   C   s   d S r   r   r   r   r   r   get_nonec   s   r+   global_ctx_getterc                 c   s"    t }z
| a d V  W |a d S |a w r   )r,   )Z
ctx_getterprevr   r   r   r%   j   s   r%   c                   @   sH   e Zd ZdZdd Zddddejfdd	Zd
dddejfddZdS )AbstractImplCtxzS
    Context object for writing abstract implementations for custom operators.
    c                 C   s   || _ || _d S r   )
_shape_env_op)r   r/   r0   r   r   r   r   z   s   
zAbstractImplCtx.__init__   Nminmaxr   c                C   s   t d | j||dS )NzIcreate_unbacked_symint is deprecated, please use new_dynamic_size insteadr2   )warningswarnnew_dynamic_size)r   r3   r4   r   r   r   create_unbacked_symint~   s   z&AbstractImplCtx.create_unbacked_symintr   c                C   s   | j du s	| j jstjj| jt|tjst|tjr(t	d| d| d|dk r4t	d| d| j 
 }tjjjj|||d |S )a=	  Constructs a new symint (symbolic int) representing a data-dependent value.

        This is useful for writing the abstract implementation (which is necessary
        for torch.compile) for a CustomOp where an output Tensor has a size
        that depends on the data of the input Tensors.

        Args:
            min (int): A statically known inclusive lower bound for this symint. Default: 0
            max (Optional[int]): A statically known inclusive upper bound for this
                symint. Default: None

        .. warning:

            It is important that the ``min`` and ``max`` (if not None) values are set
            correctly, otherwise, there will be undefined behavior under
            torch.compile. The default value of ``min`` is 2 due to torch.compile
            specializing on 0/1 sizes.

            You must also verify that your implementation on concrete Tensors
            (e.g. CPU/CUDA) only returns Tensors where the size that corresponds
            to the symint also has respects these constraint.
            The easiest way to do this is to add an assertion in the CPU/CUDA/etc
            implementation that the size follows these bounds.

        Example::

            >>> # An operator with data-dependent output shape
            >>> lib = torch.library.Library("mymodule", "FRAGMENT")
            >>> lib.define("mymodule::custom_nonzero(Tensor x) -> Tensor")
            >>>
            >>> @torch.library.impl_abstract("mymodule::custom_nonzero")
            >>> def custom_nonzero_abstract(x):
            >>>     # Number of nonzero-elements is data-dependent.
            >>>     # Since we cannot peek at the data in an abstract impl,
            >>>     # we use the ctx object to construct a new symint that
            >>>     # represents the data-dependent size.
            >>>     ctx = torch.library.get_ctx()
            >>>     nnz = ctx.new_dynamic_size()
            >>>     shape = [nnz, x.dim()]
            >>>     result = x.new_empty(shape, dtype=torch.int64)
            >>>     return result
            >>>
            >>> @torch.library.impl(lib, "custom_nonzero", "CPU")
            >>> def custom_nonzero_cpu(x):
            >>>     x_np = x.numpy()
            >>>     res = np.stack(np.nonzero(x_np), axis=1)
            >>>     return torch.tensor(res, device=x.device)

        Nzctx.new_dynamic_size(min=z, max=zZ): expected min and max to be statically known ints but got SymInt. This is not supported.r   zc, ...): expected min to be greater than or equal to 0: this API can only create non-negative sizes.r2   )r/   Zallow_dynamic_output_shape_opsr   Z_subclassesZfake_tensorZDynamicOutputShapeExceptionr0   
isinstanceSymInt
ValueErrorr8   ZfxZexperimentalZsymbolic_shapesZ_constrain_range_for_size)r   r3   r4   resultr   r   r   r7      s"   
3


z AbstractImplCtx.new_dynamic_size)	r   r   r    r!   r   r   r:   r8   r7   r   r   r   r   r.   u   s
    r.   )
contextlibr)   r5   typingr   r   r   Ztorch._library.utilsr   r   r   r"   r   r+   r,   __annotations__contextmanagerr%   r.   r   r   r   r   <module>   s&   
 ?


