U
    Mh                     @   s@  U 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
mZ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mZ d dlmZ d dlmZ d dlmZ d dlm Z  d d	l!m"Z" z~d dl#Z#d dl$Z$d d
l%m&Z' e(d 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/m0Z0 d dl1m2Z2m3Z3m4Z4 dZ5W n e6k
rj   dZ5Y nX dddddgZ7e8dddZ9i Z:ee;e<f e=d< dYe>eej?j@ e;dddZAee; dddZBe;dddZCd d! ZDe;d"d#d$ZEeFeGZHG d%d& d&eZIej?j@dd'd(d)ZJee;d*f dd+d,ZKej?j@eed*f d'd-d.ZLej?j@ed'd/d0ZMej?j@ee;d*f d'd1d2ZNee;d*f ee;d*f d3d4d5ZOeeejPejQe<ejReSejTe8f d*f ed6 d7d8d9ZUeejPd*f ed6 eejPd*f d:d;d<ZVeejPd=d>d?ZWeejPe<eSe8f d@ejPdAdBdCZXejPeejPejQe<ejReSejTe8f eejPe<eSe8f dDdEdFZYdGee;d*f eejPd*f ed6 ee;d*f eejPd*f ed6 e8edH eeejPejQe<ejReSejTe8f d*f eeejPe<eSe8f d*f dIdJdKZZdGee;d*f eejPd*f ed6 ee;d*f eejPd*f ed6 e8edH eeejPejQe<ejReSejTe8f d*f eeejPe<eSe8f d*f dIdLdMZ[G dNdO dOZ\e j]G dPdQ dQZ^ee;ee;e
e;ef f f Z_ee=d< e j]ddReddSG dTd dZ`eddSG dUd dZaeddSddVej?j@eee`e
e;ef f  dWdXdZbdS )Z    N)AnyCallableDictFinalListMappingOptionalSequenceSetTupleUnion)	TypeAlias)
FakeTensor)compatibility)FakeTensorProp)OperatorSupport)CALLABLE_NODE_OPS)_pytree)_pybind_state
onnxscript)fx_onnx_interpreter)_TORCH_DTYPE_TO_NUMPY_DTYPE(_TORCH_DTYPE_TO_ONNX_TENSOR_ELEMENT_TYPE,from_python_type_to_onnx_tensor_element_typeTFis_onnxrt_backend_supportedtorch_compile_backendOrtExecutionProviderOrtBackendOptions
OrtBackend)returnc                   C   s   t S )a!  Returns ``True`` if ONNX Runtime dependencies are installed and usable
    to support TorchDynamo backend integration; ``False`` otherwise.

    Example::

        # xdoctest: +REQUIRES(env:TORCH_DOCTEST_ONNX)
        >>> import torch
        >>> if torch.onnx.is_onnxrt_backend_supported():
        ...     @torch.compile(backend="onnxrt")
        ...     def f(x):
        ...             return x * x
        ...     print(f(torch.randn(10)))
        ... else:
        ...     print("pip install onnx onnxscript onnxruntime")
        ...
    )_SUPPORT_ONNXRT r!   r!   R/var/www/html/venv/lib/python3.8/site-packages/torch/onnx/_internal/onnxruntime.pyr   F   s    _dumped_onnx_model)model_stringgraph_moduler   c              	   C   s   t jdd}|sdS t|dd }| | d}t|d}||  W 5 Q R X |t|< |dk	r| | d}t|d	d
d}|t|j W 5 Q R X |S )a  Stores the onnx model into a file.
    The name is "{ONNXRT_DUMP_PATH}{N}.onnx"
    where *N* is the number of files already stored with
    this prefix.
    If graph_module is not None, the graph is stored as a string with
    the same filename except the extension (.txt).
    ONNXRT_DUMP_PATHN    z.onnxwbz.txtwzutf-8)encoding)osenvirongetr#   openwritestrgraph)r$   r%   prefixnfilenamefZfilename_txtr!   r!   r"   _dump_onnx_model]   s    
r8   c                   C   s   dgS )NCPUExecutionProviderr!   r!   r!   r!   r"   _infer_default_epsv   s    r:   namec                 C   s   t j rt jj|  dS )zIf PyTorch is installed with CUDA support, this starts NVTX range.

    Check torch.cuda.nvtx.range_push's document for more details.
    N)torchcudais_availablenvtxZ
range_pushr;   r!   r!   r"   _nvtx_range_push|   s    
rA   c                   C   s   t j rt jj  dS )zIf PyTorch is installed with CUDA support, this terminates NVTX range.

    Check torch.cuda.nvtx.range_pop's document for more details.
    N)r=   r>   r?   r@   Z	range_popr!   r!   r!   r"   _nvtx_range_pop   s    
rB   Zdevice_typec                 C   sF   | dkrt j S | dkr$t j S | dkr6t j S td|  d S )Nr>   cpuZmaiazUnsupported device type: )ORTC	OrtDevicer>   rD   Znpu
ValueErrorrC   r!   r!   r"   _get_ort_device_type   s    


rH   c                       sZ   e Zd ZdZee eeef d fddZe	ee
jjf e
jjed fddZ  ZS )OrtOperatorSupporta0  Operator support for ONNXRuntime backend.

    It has two-level of support decision. One is via support_dict and the other one
    is via extra_support_dict. The logic of using support_dict is implemented in
    OrtOperatorSupport and extra_support_dict is used by OperatorSupport.is_node_supported.
    )support_dictextra_support_dictc                    s   t  | || _d S N)super__init___onnx_support_dict)selfrJ   rK   	__class__r!   r"   rN      s    zOrtOperatorSupport.__init__)
submodulesnoder   c                    s   |j tkrdS |j dkr>|j| jkr>td|jt|j dS t ||rftd|jt|j dS t	d|jt|j dS )NFZcall_functionz0support_dict supports node.target: %s (type: %s)Tz6extra_support_dict supports node.target: %s (type: %s)zLsupport_dict and extra_support_dict don't support node.target: %s (type: %s))
opr   targetrO   loggerinfotyperM   is_node_supportedwarning)rP   rS   rT   rQ   r!   r"   rZ      s,    
z$OrtOperatorSupport.is_node_supported)__name__
__module____qualname____doc__r
   r   r   r2   rN   r   r=   nnModulefxNodeboolrZ   __classcell__r!   r!   rQ   r"   rI      s    	 rI   r%   r   c                 C   sh   | j }g }d}|jD ].}|jdkr,|| |dkr|jdkr|}q|dkrPdS |D ]}|| qTdS )z
    In torch.fx.Graph, placeholder is a special assignment node. If it's not
    executed in the beginning, it could overwrite values computed by upstream
    nodes.
    Nplaceholder)r3   nodesrU   appendprepend)r%   r3   placeholdersZfirst_not_placeholderrT   rg   r!   r!   r"   _move_placeholder_to_front   s    


rl   .c                  G   sP   g }| D ]>}t |dr|j}|jdkr2|d q|jdkr|d qt|S )zBReturn the first valid device (i.e., GPU or CPU) in argument list.devicer>   CUDAExecutionProviderrD   r9   )hasattrrm   rY   ri   tuple)argsepsargrm   r!   r!   r"   _infer_ep_from_device   s    


rt   c                 C   sX   g }| j jD ]B}|jdkrt|drDd|jkrDt|jd tjsDt|	| qt
|S )Nrg   metaval)r3   rh   rU   ro   ru   
isinstancer=   TensorAssertionErrorri   rp   )r%   rk   rT   r!   r!   r"   _extract_graph_module_inputs   s    
rz   c                 C   s2   | j jD ]}|jdkr|jd   S qtddS )zHCollect "val" fields from outputs metadata in this torch.fx.GraphModule.outputr   z2No output node found in this torch.fx.GraphModule.N)r3   rh   rU   rq   rG   )r%   rT   r!   r!   r"   _extract_graph_module_outputs   s    
r|   c                 C   s(   t t| \}}dd |D }t| S )z[Return the all valid devices (i.e., GPU or CPU) among outputs of this torch.fx.GraphModule.c                 S   s*   g | ]"}t |d rd|jkr|jd qS )ru   rv   ro   ru   ).0Z
output_argr!   r!   r"   
<listcomp>  s   
 
z/_infer_ep_from_graph_module.<locals>.<listcomp>)r   Ztree_flattenr|   rt   )r%   Zflattened_output_args_Zselected_output_argsr!   r!   r"   _infer_ep_from_graph_module  s    r   )rr   r   c                 C   s*   t tddd}t| }tt||ddS )z:Sort execution providers in eps based on pre-set priority.)epr   c                 S   s   | dkrdS | dkrdS dS )Nr9      rn   r)   r   r!   )r   r!   r!   r"   get_execution_provider_priority  s
    z2_sort_eps.<locals>.get_execution_provider_priorityT)keyreverse)r2   intsetrp   sorted)rr   r   Z
unique_epsr!   r!   r"   	_sort_eps  s    r   zORTC.OrtDevice.)valuesr   c                    sr   t t ddd ttjtjt tjttjtf t d fddt	| dkrdt
fdd	| D }|S d
fS d S )N)	device_idr   c                 S   s   | pdS )Nr   r!   )r   r!   r!   r"   _device_id_or_zero1  s    z-_get_onnx_devices.<locals>._device_id_or_zero)valuer   c                    s|   t | tjr0tt| jjtj  | jj	S t | tj
ttjttjtfrdttdtj dS tdtt|  d S )NrD   r   zUnsupported value type: )rw   r=   rx   rE   rF   rH   rm   rY   Zdefault_memoryindexSymIntr   SymFloatfloatSymBoolrd   rG   r2   r   )r   r!   r"   _map_tensor_or_sym_to_device4  s     

   z7_get_onnx_devices.<locals>._map_tensor_or_sym_to_devicer   c                 3   s   | ]} |V  qd S rL   r!   )r~   r   )r   r!   r"   	<genexpr>I  s     z$_get_onnx_devices.<locals>.<genexpr>r)   )r   r   r=   rx   r   r   r   r   rd   lenrp   )r   Zort_devicesr!   )r   r   r"   _get_onnx_devices)  s    r   )tensorsdevicesr   c                 C   sn   t  }|t|  g }g }g }| D ]0}|t|j  ||  ||  q&|	| |||| |S rL   )
rE   OrtValueVectorZreserver   ri   r   dtypesizeZdata_ptrpush_back_batch)r   r   Z	ortvaluesZdtypesZshapesZ	data_ptrstensorr!   r!   r"   !_get_ortvalues_from_torch_tensorsO  s    r   )r   r   c                 C   s*   | j rtdtj|  | j| jd}|S )Nz#sparse tensor is not yet supported.)r   rm   )Z	is_sparserG   r=   emptyr   r   rm   )r   outr!   r!   r"   _to_real_tensor`  s    r   onnx.ValueInfoProto)dynamo_value
value_infor   c                 C   s   t | tjr4t|jjjjdkr4| jdkr4t| S t | t	rNtj
| tjdS t | trhtj
| tjdS t | trtj
| tjdS t | tjst|  S dS )z9Helper function to wrap PyTorch variables as torch.Tensorr   )r)   )r   N)rw   r=   rx   r   rY   tensor_typeshapedimZsqueezer   r   Zint64r   Zfloat32rd   ry   
contiguous)r   r   r!   r!   r"   _adjust_scalar_from_fx_to_onnxg  s    





r   )r   
prim_valuer   c                 C   s<   t | tjstdt |tjttjttjt	fr8| 
 S | S )zFHelper function to wrap ORT-produced torch.Tensor as PyTorch variableszORT's output must be tensor.)rw   r=   rx   ry   r   r   r   r   r   rd   item)r   r   r!   r!   r"   _adjust_scalar_from_onnx_to_fx  s    r   onnxruntime.InferenceSessionr   .)sessinput_namesinputsinput_devicesoutput_namesoutputsoutput_devicespreallocate_outputinput_value_infosnormalized_prim_outputsr   c
                 C   s
  t d tdd t||D }t  t d t||}
|rZtdd |D }t||}nt }t  t d t }|	dd | 
|||
||| t  |rt d	 td
d t||	D }t  |S t d	 tjjj|}tdd t||	D }t  |S d S )Nr   c                 s   s   | ]\}}t ||V  qd S rL   r   r~   rs   r   r!   r!   r"   r     s   z8_run_onnx_session_with_ortvaluevector.<locals>.<genexpr>r   c                 s   s$   | ]}t |trt|n|V  qd S rL   )rw   r   r   )r~   tr!   r!   r"   r     s    run_with_ortvaluevectorZ'disable_synchronize_execution_providers1zafter run_with_ortvaluevectorc                 s   s   | ]\}}t ||V  qd S rL   r   r~   onnx_outputprim_outputr!   r!   r"   r     s   c                 s   s   | ]\}}t ||V  qd S rL   r   r   r!   r!   r"   r     s   )rA   rp   ziprB   r   rE   r   onnxruntimeZ
RunOptionsZadd_run_config_entryr   ZtrainingZ	ortmoduleZ_utilsZ_ortvalues_to_torch_tensor)r   r   r   r   r   r   r   r   r   r   Z
ort_inputspth_outputsort_outputsZrun_optionsr!   r!   r"   %_run_onnx_session_with_ortvaluevector  sT    
     
r   c
                 C   sT   t dd t||D }dd t||D }
| ||
}t dd t||	D }|S )Nc                 s   s   | ]\}}t ||V  qd S rL   r   r   r!   r!   r"   r     s   z/_run_onnx_session_with_fetch.<locals>.<genexpr>c                 S   s&   i | ]\}}|t j|  qS r!   )r   ZOrtValueZortvalue_from_numpyrD   numpy)r~   r<   r   r!   r!   r"   
<dictcomp>  s    z0_run_onnx_session_with_fetch.<locals>.<dictcomp>c                 s   s"   | ]\}}t t||V  qd S rL   )r   r=   Z
from_numpy)r~   r   r   r!   r!   r"   r     s
   )rp   r   run)r   r   r   r   r   r   r   r   r   r   feedr   r   r!   r!   r"   _run_onnx_session_with_fetch  s    r   c                   @   sh   e Zd ZdZdeedf ed eedf ed ed ed eeejdf ejf dddZ	d	d
 Z
dS )OrtExecutionInfoPerSessionzWInformation required to execute torch.fx.GraphModule using onnxruntime.InferenceSessionr   .r   r   sessionr   r   r   output_value_infosr   r   example_outputsc	           	      C   s4   || _ || _|| _|| _|| _|| _|| _|| _d S rL   r   )	rP   r   r   r   r   r   r   r   r   r!   r!   r"   rN     s    z#OrtExecutionInfoPerSession.__init__c                 G   s  t |t | jkrdS t|| jD ]\}}t|tjttfsB dS t|tttfrt	t
|}||j
jjkrr dS t |j
jjjdkr" dS q"t|j }||j
jjkr dS t|j|j
jjjD ]D\}}t|tr|j|ks|jrqqt|tjr|jrqq  dS qq"dS )NFr   T)r   r   r   rw   r=   rx   r   r   rd   r   rY   r   Z	elem_typer   r   r   r   Z	dim_valueZ	dim_paramr   )rP   rq   rs   r   Z
onnx_dtyper   Zonnx_dimr!   r!   r"   is_supported4  s4    

z'OrtExecutionInfoPerSession.is_supportedN)r\   r]   r^   r_   r   r2   r   r=   rx   rN   r   r!   r!   r!   r"   r     s   

!r   c                   @   s:   e Zd Zdd ZejjdddZejjedddZ	d	S )
"OrtExecutionInfoForAllGraphModulesc                 C   s
   i | _ d S rL   )execution_info_per_graph_module)rP   r!   r!   r"   rN   Y  s    z+OrtExecutionInfoForAllGraphModules.__init__r%   c                 G   s8   || j krd S | j | }|D ]}|j| r|  S qd S rL   )r   r   )rP   r%   rq   
candidates	candidater!   r!   r"   &search_reusable_session_execution_info`  s    



zIOrtExecutionInfoForAllGraphModules.search_reusable_session_execution_info)r%   rX   c                 C   s,   || j kr|g| j |< n| j | | d S rL   )r   ri   )rP   r%   rX   r!   r!   r"   cache_session_execution_infop  s    
z?OrtExecutionInfoForAllGraphModules.cache_session_execution_infoN)
r\   r]   r^   rN   r=   rb   GraphModuler   r   r   r!   r!   r!   r"   r   W  s    r   )frozen)Zis_backward_compatiblec                   @   s   e Zd ZU dZdZeee  ed< dZ	e
ed< dZeee  ed< dZe
ed< dZe
ed	< dZed
 ed< dZed ed< dZeeedgdf   ed< dS )r   aJ  Options for constructing an ``OrtBackend``, the ONNX Runtime
    backend (``"onnxrt"``) for ``torch.compile``.

    Example::

        >>> @torch.compile(
        ...     backend="onnxrt",
        ...     options=torch.onnx._OrtBackendOptions(...),
        ... )
        ... def ort_function(x):
        ...     return x ** x
    Npreferred_execution_providersTinfer_execution_providersdefault_execution_providersFr   use_aot_autogradztorch.onnx.ExportOptionsexport_optionszonnxruntime.SessionOptionsort_session_optionszonnx.ModelProtopre_ort_model_transforms)r\   r]   r^   r_   r   r   r	   r   __annotations__r   rd   r   r   r   r   r   r   r   r!   r!   r!   r"   r     s   

c                   @   s   e Zd ZU dZdee dddZejj	e
eeeeef f  dddZejj	d	d
dZejj	ejj	dddZejj	ejj	dddZdZeed< g Zeed   ed< edeeeeeef f  d dddZedd Zedd ZdS )r   a	  A backend compiles (sub-)graphs in torch.fx.GraphModule to onnxruntime.InferenceSession calls.

    The compiler entry point is OrtBackend.compile, which
        1. partitions the original graph into supported sub-graphs (type: torch.fx.GraphModule) and unsupported
           sub-graphs.
        2. For each supported sub-graph, it replaces its _wrapped_call function with _ort_accelerated_call.
        3. Inside _ort_accelerated_call, it creates onnxruntime.InferenceSession and calls it to execute the sub-graph.
    Noptionsc                 C   s   |d krt  n|| _tjjj| jjd kr4tj n| jj| _	tjjj
j| j	j}d d d d d d}t||| _i | _t | _d| _d| _ttjdrtnt| _d S )N)getattrz_operator.getitemz_operator.mulz_operator.addz_operator.subFr   r   )r   _optionsr=   onnx	_internalZexporterZResolvedExportOptionsr   ZExportOptions_resolved_onnx_exporter_optionsrb   decomposition_tableZ'_create_onnx_supports_op_overload_tableonnx_registryrI   _supported_ops_partitioner_cacher   _all_ort_execution_info_assert_allclose_to_baselineexecution_countro   rE   r   r   r   r   )rP   r   rJ   rK   r!   r!   r"   rN     s2    


zOrtBackend.__init__rf   c                 G   s   t  }| jjr0t|  }r |}nt| }r0|}g }| jjp>g t|| jjpPt D ]T}t	|t
rl|i f}n"t	|t r|d d kr|d i f}|d k	rT||krT|| qT|S )Nr)   r   )rp   r   r   rt   r   r   r   r   r:   rw   r2   ri   )rP   r%   rq   Zinferred_epsZeps_from_argsZeps_from_graph_moduleZselected_epsr   r!   r!   r"   _select_eps$  s$    


zOrtBackend._select_epsr   c                 O   sl  | j j|f| }|rJ|j}|j}|j}|j}|j}	|j}
|j}|j	}n:t
jjjj| jj| }| jjrd| _t|}dd }t||}n>zt|j||}W n( tk
r   td| d| _ Y nX tj| jjd}t
jjjj| jj| }|j|| jj | jj!d}|j"| jj#j$d}z0dd	l%m&} dd
l'm(} |)|}|*|}W n  t+k
rv   td Y nX | j,j-r| j,j-D ]}|| q|. }t/j01ddrt2||d t(j3|| j,j4| j5|f| d}t6dd |j7j8D }t6dd |j7j9D }t:|}
t;|t6r(t:|}n
t:|f}t6dd |j7j8D }t6dd |j7j9D }	t<|||||	|
||d}| j =|| |  j>d7  _>t;|t
j?}|r|fn|}t;|t6st@tAdd |D st@tBd | ||||
|||| j,j||
}tC  | jDrZt
jEjFjG|f|ddi}|r2|fn|}tH||D ]\}}t
jIJ|| q@|rh|d S |S )a  This function replaces GraphModule._wrapped_call in compiled model.

        The _wrapped_call is the underlying implementation of forward method. Replacing
        it means we delegate the computation to _ort_acclerated_call and therefore
        onnxruntime.InferenceSession.
        Fc                 S   s&   t | drd| jkr| jd S | S d S )Nru   rv   r}   r   r!   r!   r"   maybe_map_to_meta_valm  s    
z>OrtBackend._ort_acclerated_call.<locals>.maybe_map_to_meta_valzFakeTensorProb failed for %s)diagnostic_context)Zfx_graph_moduleonnxfunction_dispatcherop_level_debug)opset_versionr   )	optimizer)r   zONNXScript optimizer is not available. Skipping optimization. Please `pip install onnxscript -U` to enable post-export optimization.r&   Nr   )Zpath_or_bytesZsess_options	providersc                 s   s   | ]}|j V  qd S rL   r;   r~   inputr!   r!   r"   r     s     z2OrtBackend._ort_acclerated_call.<locals>.<genexpr>c                 s   s   | ]}|j V  qd S rL   r;   r~   r{   r!   r!   r"   r     s     c                 s   s   | ]
}|V  qd S rL   r!   r   r!   r!   r"   r     s     c                 s   s   | ]
}|V  qd S rL   r!   r   r!   r!   r"   r     s     r   r)   c                 s   s"   | ]}t |tjtjtfV  qd S rL   )rw   r=   rx   r   r   )r~   elemr!   r!   r"   r     s   Z$run_onnx_session_with_ortvaluevectorexecutorZaten)Kr   r   r   r   r   r   r   r   r   r   r=   r   r   rb   ZpassesZMovePlaceholderToFrontr   r   r   dynamic_shapesr   r|   r   Ztree_mapr   	propagate	ExceptionrW   r[   r   ZFxOnnxInterpreterZInsertTypePromotionr   r   Zto_model_protor   r   r   r   Zonnxscript.rewriterr   optimizeZrewriteImportErrorr   r   ZSerializeToStringr-   r.   r/   r8   ZInferenceSessionr   r   rp   r3   r   r{   r   rw   r   r   r   rx   ry   allrA   rB   r   Z_primsr   executer   ZtestingZassert_close)rP   r%   rq   kwargsZ!cached_execution_info_per_sessionZonnx_sessionr   r   r   r   r   r   Zprim_outputsZextracted_outputsr   Zfx_interpreterZexportedZ
onnx_modelr   Zort_rewriterZ	transformZonnx_model_bytesZexecution_info_per_sessionZis_single_tensor_outputr   Zonnx_outputsZbaseline_outputsZnormalized_baseline_ouptutsr   Zbaseline_outputr!   r!   r"   _ort_acclerated_callE  s   

   


	

  zOrtBackend._ort_acclerated_callc           	      C   s   ddl m} || jkr"| j| }n\|}||| jdd}| }|| j|< |jjD ],}|jdkrPd|jkrPt	||j}| j
|_qP|S )Nr   )CapabilityBasedPartitionerT)Zallows_single_node_partitionZcall_moduleZfused_)Z!torch.fx.passes.infra.partitionerr
  r   r   Zpartition_and_fuser3   rh   rU   r<   r   r	  Z_wrapped_call)	rP   r%   rq   r
  Zpartitioned_prim_graph_moduleZprim_graph_moduleZpartitionerrT   Zfused_moduler!   r!   r"   compile  s     


zOrtBackend.compilec                 C   sF   | j jr:ddlm} ddlm} || j|| jjd||S | ||S )zIf ``OrtBackendOptions.use_aot_autograd`` is ``True``, the `auto_autograd` compiler
        will be invoked, wrapping this ``OrtBackend`` instance's ``compile`` method. Otherwise,
        the ``compile`` method is invoked directly.r   )#min_cut_rematerialization_partition)aot_autograd)Zfw_compilerZpartition_fnZdecompositions)	r   r   Zfunctorch.compiler  Ztorch._dynamo.backends.commonr  r  r   r   )rP   r%   rq   r  r  r!   r!   r"   __call__O  s     zOrtBackend.__call__   %_OrtBackend__instance_cache_max_count_OrtBackend__instance_cache)r   r   c                    s   t t dddt t s(t f  p$i  t fddtjD d}|dkrttjtjk sztdtj dt d	t d
tjt  } |S )a  Returns a possibly cached instance of an ``OrtBackend``. If an existing
        backend was created previously through this function with the same options,
        it will be returned. Otherwise a new backend will be created, cached, and
        returned.

        Note: if ``options`` sets ``ort_session_options``, a new ``OrtBackend``
        will always be returned, since ``onnxruntime.SessionOptions`` cannot
        participate in caching.abc                 S   s   | j |j ksH| j|jksH| j|jksH| j|jksH| j|jksH| j|jkrLdS | jd k	s`|jd k	rddS | j|jkrtdS | jd k	r|jd k	r| jj|jjko| jj	|jj	ko| jj
|jj
ko| jj|jjko| jj|jjkS dS )NFT)r   r   r   r   r   r   r   r   r  r   Zdiagnostic_optionsr   Zfake_contextr  r!   r!   r"   reusabler  s@    





z<OrtBackend.get_cached_instance_for_options.<locals>.reusablec                 3   s   | ]}|j  r|V  qd S rL   )r   )r~   r  r   r  r!   r"   r     s      z=OrtBackend.get_cached_instance_for_options.<locals>.<genexpr>NzNo more than z instances of z allowed. Please instantiate `z` explicitly to pass to `torch.compile`. See https://github.com/pytorch/pytorch/pull/107973#discussion_r1306144795 for discussion.)	r   rw   nextr   r  r   r  ry   ri   )r   backendr!   r  r"   get_cached_instance_for_optionse  s    %
	z*OrtBackend.get_cached_instance_for_optionsc                   C   s   t j  d S rL   )r   r  clearr!   r!   r!   r"   clear_cached_instances  s    z!OrtBackend.clear_cached_instancesc                   C   s
   t tjS rL   )rp   r   r  r!   r!   r!   r"   get_cached_instances  s    zOrtBackend.get_cached_instances)N)N)r\   r]   r^   r_   r   r   rN   r=   rb   r   r	   r   r2   r   r   r   r	  r  r  r  r   r   r  r   staticmethodr   r  r  r  r!   r!   r!   r"   r     s.   
	S! U7 G
r   )r%   r   c                C   s   t || |S rL   )r   r  )r%   rq   r   r!   r!   r"   r     s    )N)cdataclasses	importlibloggingr-   typingr   r   r   r   r   r   r   r	   r
   r   r   typing_extensionsr   r=   Ztorch._CZ
torch._opsZtorch._prims.executorZtorch.fxZtorch._subclasses.fake_tensorr   Ztorch.fx._compatibilityr   Z torch.fx.passes.fake_tensor_propr   Z torch.fx.passes.operator_supportr   Ztorch.fx.passes.tools_commonr   Ztorch.utilsr   r   r   Zonnxruntime.capir   rE   import_moduleZ
torch.onnxZtorch.onnx._internalZ torch.onnx._internal.diagnosticsZtorch.onnx._internal.exporterZ+torch.onnx._internal.fx.decomposition_tableZtorch.onnx._internal.fx.passesZtorch.onnx._internal.fxr   Z"torch.onnx._internal.fx.type_utilsr   r   r   r    r  __all__rd   r   r#   r2   r   r   bytesrb   r   r8   r:   rA   rB   rH   	getLoggerr\   rW   rI   rl   rt   rz   r|   r   r   rx   r   r   r   r   r   r   r   r   r   r   r   r   	dataclassr   r   r   r   r   r!   r!   r!   r"   <module>   s,   4

	  
		
2

 ' !	

O

$G!$
?   q