o
    Ih3h                     @   s  U 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m	Z	m
Z
mZmZmZ d dlZd dlmZ d dlmZ d dlmZ ddlmZmZ d dlZd dlmZ 	 g dZdd	d
Zh dZdd Z	d<dedeje dejfddZ i Z!e"edf e#d< G dd dZ$e j%G dd dZ&dede	fddZ'deddfddZ(deddfd d!Z)dede*eef fd"d#Z+d$eddfd%d&Z,d'ej-de.fd(d)Z/ded*ejddfd+d,Z0dej1d-eddfd.d/Z2d0d1 Z3d2d3 Z4d=d5d6Z5d7d8 Z6d>d:d;Z7dS )?    N)FunctionSchemaOperatorName
SchemaKindBaseTypeListTypeBaseTy)get_ctx   )autograd_kernel_indirectionconstruct_autograd_kernel)infer_schema)	custom_opCustomOpr   CPUCUDA)cpucuda>   atatenprimprimstorchpytorchc                   C   s   t dt d S )Nzwtorch._custom_op is deprecated and will be removed in PyTorch 2.6, please use the equivalent torch.library API instead.)warningswarnDeprecationWarning r   r   I/var/www/vscode/kcb/lib/python3.10/site-packages/torch/_custom_op/impl.pywarn_deprecated-   s   r   qualnamemanual_schemareturnc                    s   t    fdd}|S )L
    This API is deprecated, please use torch.library.custom_op instead
    c           	   	      s,  t | stdt|  t\}}t| | j|kr,td d| d| j d d u r6t| ddn }| | }t	|}t
|  d urPt||  t|d}|| t||j}t|||||d	d
}| j|_| j|_| j|_t||jdtt| tj|ttt| |S )NzDcustom_op(...)(func): Expected `func` to be a Python function, got: zcustom_op(qualname='z-', ...)(func): expected `func` to have name 'z' but got 'zX'. Please either change the name of `func` or the qualname that is passed to `custom_op`r   )mutates_argsFRAGMENTT_private_accessAutograd)inspect
isfunction
ValueErrortypeparse_qualnamevalidate_namespace__name__r   r   parsevalidate_schema validate_function_matches_schemalibraryLibrarydefinefind_ophandle_or_thrownamer   
__module____doc__impl_opnamer
   weakrefproxyr   _C#_dispatch_set_report_error_callback	functoolspartialreport_error_callback)	funcnsr6   schema
schema_strfunction_schemalibophandleresultr    r   r   r   inner;   sH   




zcustom_op.<locals>.inner)r   )r   r    rK   r   rJ   r   r   3   s   +r   r   global_registryc                       s   e Zd ZdZdd fdd
Zdd Zd,d	d
Zdd Zdd Zdd Z	dd Z
dd Z	d,dejeeje f dejfddZdd ZdejfddZd,dejfddZdd  Zd!d" Zd#d$ Zd%d& Zd,d'd(Zd-d*d+Z  ZS ).r   r"   Fr%   c                   sn   t    t  |std| d| }|| _|| _|| _|| _|| _|| _	d | _
i | _d| _| t| j	< d S )Nz|The CustomOp constructor is private and we do not guarantee BC for it. Please use custom_op(...) to create a CustomOp object::F)super__init__r   RuntimeError_schema_cpp_ns_lib	_ophandler:   	_qualnamer.   _impls'_registered_autograd_kernel_indirectionrL   )selfrG   cpp_nsrD   operator_namerH   r&   r6   	__class__r   r   rO   w   s"   
zCustomOp.__init__c                 C   s0   | j rJ | j| jtt| d d| _ d S )Nr'   T)rW   rS   r9   r:   r
   r;   r<   rX   r   r   r   %_register_autograd_kernel_indirection   s   

z.CustomOp._register_autograd_kernel_indirection   c              
   C   s   |  |r%| j| }|d usJ |j}td| d| j d| d| d	tt|}|j	 d|j
 }t||| j|< d S )NzAttempting to register a z impl for operator z that already has a z  impl registered from Python at z. This is not supported.:)	_has_implrV   locationrP   rU   r(   getframeinfosys	_getframefilenamelinenoFuncAndLocation)rX   kindrB   
stacklevelfunc_and_locationrb   framer   r   r   _register_impl   s   

zCustomOp._register_implc                 C   s
   | j | S NrV   rX   ri   r   r   r   	_get_impl      
zCustomOp._get_implc                 C   s
   || j v S rn   ro   rp   r   r   r   ra      rr   zCustomOp._has_implc                 C   s6   | ` ttj| j}t|| jrt|| j t| j	= d S rn   )
rS   getattrr   opsrR   hasattrr:   delattrrL   rU   )rX   opnamespacer   r   r   _destroy   s
   zCustomOp._destroyc                 C   s   d| j  dS )Nz<CustomOp(op="z")>)rU   r]   r   r   r   __repr__   s   zCustomOp.__repr__c                 O   s   t j| jg|R i |}|S rn   )r=   _dispatch_call_boxedrT   )rX   argskwargsrI   r   r   r   __call__   s   zCustomOp.__call__device_typesr!   c                    s6   t trgD ]}t| q
 fdd}|S )T
        This API is deprecated, please use torch.library.custom_op instead
        c                    sJ   t D ]}| j||  d t| }tjj||  q| S )Nrj   )set_check_doesnt_have_library_implrm   SUPPORTED_DEVICE_TYPE_TO_KEYr2   r9   rS   r:   )fdevice_typedispatch_key_stacklevelr~   rX   r   r   rK      s   
zCustomOp.impl.<locals>.inner)
isinstancestrvalidate_device_type)rX   r~   r   r   rK   r   r   r   r9      s   

zCustomOp.implc                 C   s@   |  |rd S t| }t| j|rtd| d| j dd S )Nzimpl(..., device_types=z): the operator zs already has an implementation for this device type via a pre-existing torch.library or TORCH_LIBRARY registration.)ra   r   r=   ._dispatch_has_computed_kernel_for_dispatch_keyrU   rP   )rX   r   keyr   r   r   r      s   
z(CustomOp._check_doesnt_have_library_implc                    s    fdd}|S )z2Register an implementation for a factory function.c                    s&     d|  t j jd|  | S )NfactoryBackendSelect)rm   r2   r9   rS   r:   r   r]   r   r   rK      s   z$CustomOp.impl_factory.<locals>.innerr   )rX   rK   r   r]   r   impl_factory   s   zCustomOp.impl_factoryc                        fdd}|S )r   c                    sZ      jd d djjt  fdd}jj	|d  S )Nabstractr   c                     sN   fdd}t jj|  | i |W  d    S 1 s w   Y  d S )Nc                         t d d  )Nz<Attempted to call get_ctx() for the meta implementation for a  .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. Otherwise, please remove the call to get_ctx() in the implementation registered with impl_abstract at rP   r   )rb   r   r   r   error_on_ctx   s   zOCustomOp.impl_abstract.<locals>.inner.<locals>.f_with_ctx.<locals>.error_on_ctx)r   _library	fake_implset_ctx_getter)r{   r|   r   r   rb   r   r   r   
f_with_ctx   s   $z9CustomOp.impl_abstract.<locals>.inner.<locals>.f_with_ctxMeta)
$_check_doesnt_have_library_meta_implrm   rq   rb   rU   r?   wrapsrS   r9   r:   )r   r   r   rX   r   r   rK      s   z%CustomOp.impl_abstract.<locals>.innerr   rX   r   rK   r   r   r   impl_abstract   s   zCustomOp.impl_abstractc                    s    fdd}j    tjkr|d  j} js|d t|dks'J tdd |D }|r6|d ttj	d	ttj
d
ttjdttjdttjdtttjd di} jD ]}|j|v rdq\|dt|  d|j d q\d S )Nc                    s   t d|  dj d  )NzCCannot use torch._custom_ops APIs to register backward formula for z. Got operator z with schema: )rP   rU   )detailrD   rX   r   r   error  s   z4CustomOp._check_can_register_backward.<locals>.errorznon-functional operatorzoperator with no returnsr   c                 s   s$    | ]}|j d uo|j j V  qd S rn   )
annotationis_write).0rr   r   r   	<genexpr>#  s    
z8CustomOp._check_can_register_backward.<locals>.<genexpr>zoperator that returns viewsintSymIntboolfloatTensorzList[Tensor]zoperator with return not in z (got ))rQ   ri   r   
functionalreturnslenanyr   r   r   r   r   r   r   r   r+   listvalues)rX   r   retsis_non_mutating_viewallowed_return_typesretr   r   r   _check_can_register_backward  s2   






"z%CustomOp._check_can_register_backwardc                 C   s^   | j rd S t| jdrtd| j ddD ]}t| j|r,td| j d| dqd S )NCompositeImplicitAutogradz3impl_backward/impl_save_for_backward: the operator a3   already has an implementation for this device type via a pre-existing registration to DispatchKey::CompositeImplicitAutograd.CompositeImplicitAutograd operators do not need an autograd formula; instead, the operator will decompose into its constituents and those can have autograd formulas defined on them.)r'   AutogradCPUAutogradCUDAz; already has an Autograd kernel registered to DispatchKey::z vi a pre-existing torch.library or TORCH_LIBRARY registration. Please either remove those registrations or don't use the torch._custom_ops APIs)rW   r=   %_dispatch_has_kernel_for_dispatch_keyrU   rP   )rX   r   r   r   r   (_check_doesnt_have_library_autograd_impl7  s"   
z1CustomOp._check_doesnt_have_library_autograd_implc                 C   sr   |  drd S t| jdrt| jdsd S t| jdr'td| j dt| jdr7td| j dd S )Nr   CompositeExplicitAutogradr   r   z!impl_abstract(...): the operator a-   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 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.)ra   r=   r   rU   rP   r]   r   r   r   r   O  s    
z-CustomOp._check_doesnt_have_library_meta_implc              	   C   sX   |  dsJ |  dsJ t| j| j| t| j| dj| dj}| d| d S )Nbackwardsave_for_backwardautograd)	ra   r   rQ   _output_differentiabilityget_oprU   rq   rB   rm   )rX   kernelr   r   r   _register_autograd_kernelx  s   

z"CustomOp._register_autograd_kernelc                    r   )zyRegister a function that tells us what to save for backward.

        Please see impl_backward for more details.
        c                    sH        js  jd|  d dr"  d S d S )Nr   r   r   )r   r   rW   r^   rm   ra   r   r   r   r   r   rK     s   
z.CustomOp.impl_save_for_backward.<locals>.innerr   r   r   r   r   impl_save_for_backward  s   zCustomOp.impl_save_for_backwardNc                    sl   dur,fdd}t ts|  D ]
}t |ts|  qtjjtkr,|   fdd}|S )r   Nc                      s   t d  )Nzimpl_backward(output_differentiability): expected output_differentiability to be a list of bools with length equal to the number of outputs of this CustomOp got: r   r   )output_differentiabilityr   r   yell  s
   z$CustomOp.impl_backward.<locals>.yellc                    sN        js  jd|  d _dr%  d S d S )Nr   r   r   )r   r   rW   r^   rm   r   ra   r   r   r   r   rX   r   r   rK     s   
z%CustomOp.impl_backward.<locals>.inner)r   r   r   r   rQ   r   )rX   r   r   r   diffrK   r   r   r   impl_backward  s   

	zCustomOp.impl_backward)r_   )Nr_   )r.   r7   __qualname__r8   rO   r^   rm   rq   ra   rx   ry   r}   typingUnionr   IterableCallabler9   r   r   r   r   r   r   r   r   r   __classcell__r   r   r[   r   r   r   s2    



#%)
c                   @   s    e Zd ZU ejed< eed< dS )rh   rB   rb   N)r.   r7   r   r   r   __annotations__r   r   r   r   r   rh     s   
 
rh   rY   rZ   c                 C   s0   |j d u rdn|j }t|  dt|j |S )N rM   )overload_namer=   _dispatch_find_schema_or_throwr   r6   )rY   rZ   r   r   r   r   r5     s
   r5   rC   c                 C   s:   d| v rt d|  d| tv rt d|  d|  dd S )N.zcustom_op(..., ns="zC"): expected ns to not contain any . (and be a valid variable name)zcustom_op(..., ns='z'): 'z9' is a reserved namespace, please choose something else. )r*   RESERVED_NS)rC   r   r   r   r-     s   
r-   rD   c                 C   s:   t jj| std|  | jjd urtd|  d S )Nzcustom_op only supports functional operators (ops that do not mutate any inputs, do not return views of the inputs, and has at least one return). Got the following non-functional schema: zUcustom_op does not support arguments named 'self'. Please rename your argument. Got: )r   r   utilsis_functional_schemar*   	argumentsself_arg)rD   r   r   r   r0     s   r0   c                 C   sR   |  dd}t|dkrtd|  dd|d v r!td|  |d |d fS )	NrM   r	   r_   z$Expected there to be a namespace in z;, i.e. The operator name should look something like ns::foor   zThe torch.custom_ops APIs do not handle overloads, i.e. operator names with '.' in them. Please name your operator something like ns::foo. Got: r   )splitr   r*   )r   namesr   r   r   r,     s   r,   r   c                 C   s&   | t vrtd|  dt   dd S )NzCustomOp.impl(device_types=[z(, ...]): we only support device_type in r   )r   r*   keys)r   r   r   r   r     s   r   paramc                 C   s   | j tjjtjjfv S rn   )ri   r(   	ParameterPOSITIONAL_OR_KEYWORDKEYWORD_ONLY)r   r   r   r   supported_param  s   r   rB   c                    s   t |tdd j D std tdd j D s+jt jj	ur2td dd j D }dd j D }fd	d
 fdd fdd}||j
j ||j
j d S )Nc                 s   s    | ]	\}}t |V  qd S rn   )r   r   _pr   r   r   r      s    z3validate_function_matches_schema.<locals>.<genexpr>zcustom_op(..., manual_schema)(func): positional-only args, varargs, and kwargs are not supported. Please rewrite `func` to not have them. Got `func` with signature: c                 s   s"    | ]\}}|j tjjuV  qd S rn   )r   r(   r   emptyr   r   r   r   r     s
    
zcustom_op(..., manual_schema)(func): When passing in a manual schema, we expect `func` to have no type annotations to avoid ambiguity. Got `func` with signature: c                 S   &   g | ]\}}|j tjjkr||fqS r   )ri   r(   r   r   r   r6   r   r   r   r   
<listcomp>  
    z4validate_function_matches_schema.<locals>.<listcomp>c                 S   r   r   )ri   r(   r   r   r   r   r   r   r     r   c                      r   )Nzcustom_op(..., manual_schema)(func): When passing in a manual schema, we expect `func`'s signature to match `manual_schema` (aside from type annotations). func's signature: , manual_schema: r*   r   rD   sigr   r   r        z/validate_function_matches_schema.<locals>.errorc                      r   )Nzycustom_op(..., manual_schema)(func): neither func nor manual_schema should have default arguments. Got func's signature: r   r   r   r   r   r   error_default_args'  r   z<validate_function_matches_schema.<locals>.error_default_argsc                    s`   t | t |kr   t| |D ]\\}}}||jkr   |jtjjus*|jd ur-  qd S rn   )r   zipr6   defaultr(   r   r   )sig_argsschema_argsr6   r   arg)r   r   r   r   compare/  s   
z1validate_function_matches_schema.<locals>.compare)r(   	signatureall
parametersitemsr*   r   return_annotation	Signaturer   r   flat_positionalflat_kwarg_only)rD   rB   
positional	kwargonlyr   r   )r   r   rD   r   r   r1     s8   
	r1   r   c              	   C   sp   |dkrt |  d|dkrt |  d|dv r.| }t |  d| d| d| d	t |  d
| d)N	Undefineda  : There were no Tensor inputs to this operator (e.g. you passed an empty list of Tensors). If your operator is a factory function (that is, it takes no Tensors and constructs a new one), then please use CustomOp.impl_factory to register an implementation for itr   z: when running with device='Meta' tensors: there is no abstract impl registered for this CustomOp. Please register one via CustomOp.impl_abstract to get this CustomOp to work with Meta tensors)r   r   z: when running with device='z' tensors: there is no zW impl registered for this CustomOp. Please register one via CustomOp.impl(device_type='z')z%: No implementation for dispatch key z. It is likely that we have not added this functionality yet, please either open an issue or if you're feeling adventurous, use the low-level torch.library API)NotImplementedErrorlower)r   r   devicer   r   r   rA   <  s(   rA   c                 C   s\   | j }tj|d}|  dd }t| j}|dd }t	|}t
||||| ddS )Nr$   rM   Tr%   )	namespacer   r2   r3   r6   r   r   rQ   r   r/   r   )oprC   rG   r6   rE   rD   r   r   r   custom_op_from_existingZ  s   

r  c                    sf    fdd}t  \}}ttj|s|  ttj|}t||s#|  t||}t|ds0|  |jS )Nc                      s   t d  d)NzCould not find the operator z~. Please make sure you have already registered the operator and (if registered from C++) loaded it via torch.ops.load_library.r   r   r   r   r   error_not_foundf  s   
zget_op.<locals>.error_not_foundr   )r,   ru   r   rt   rs   r   )r   r  rC   r6   rw   packetr   r  r   r   e  s   


r   Fc                 C   s8   | t v rt |  S |std|  dt| }t|}|S )NzCould not find custom op "z5". Did you register it via the torch._custom_ops API?)rL   rP   r   r  )r   also_check_torch_libraryoverloadrI   r   r   r   _find_custom_opx  s   
r  c                 C   sF   | t jjjvr	d S t jjj|  }|d u rd S |dsd S |djS )Nr   )r   
_custom_opr9   rL   ra   rq   rB   )r   r   r   r   r   get_abstract_impl  s   
r  Tc              	   C   s   |  d\}}| | }t|}t| |rtjjjgng }t	|d}|j
||d t||j}	t|||||	dd}
|
  tj|	ttt|
 t| S )NrM   r$   )tagsTr%   )r   r   r/   r0   r   r=   Tagneeds_fixed_stride_orderr2   r3   r4   r5   r6   r   r^   r>   r?   r@   rA   r;   r<   r   )r   rD   r  rC   r6   rE   rF   r  rG   rH   rI   r   r   r   _custom_op_with_schema  s   
r  rn   )F)T)8dataclassesr?   r(   rd   r   r;   r   torchgen.modelr   r   r   r   r   r   r   torch._Cr=   torch.libraryr2   r   r   r
   r   torch._library.infer_schemar   __all__r   r   r   r   Optionalr   r   rL   dictr   r   	dataclassrh   r5   r-   r0   tupler,   r   r   r   r   r1   AnyrA   r  r   r  r  r  r   r   r   r   <module>   sn   
 	
<  C	
A
