
    Vhb                        d dl Z d dlmZ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c mZ d dlmc mZ d dlmZ d dlmZ d dlmZ d dlmZmZmZ d d	lmZ d d
l m!Z! e G d de"             Z#dede$dededef
dZ%dede$defdZ&d Z'd Z(d Z)d Z*ed        Z+dej                  jX                  de$fdZ-dej                  jX                  de$fdZ.de/e   fdZ0d:d Z1d:d!Z2d:d"Z3d# Z4d$ Z5d% Z6d& Z7d' Z8d( Z9d) Z:d* Z;d+ Z<d, Z=d- Z>d. Z?d;d/ej                  d0eAdej                  fd1ZB	 d<d2ed3ede/eC   fd4ZDd5e
eEed6f   e/e   f   fd7ZFdej                  jX                  d8e/e   deEe/eA   eGeAeAf   eGeAeAf   eGeAeAf   f   fd9ZHy)=    N)contextmanager	ExitStack)	dataclass)AnyCallableOptionalUniondetect_fake_mode)OperatorBase)
FakeTensor))_temp_remove_metadata_torch_function_modedisable_proxy_modes_tracingmake_fx)TensorMetadata)StorageWeakRefc                       e Zd ZU eed<   y)!UnsupportedAliasMutationExceptionreasonN)__name__
__module____qualname__str__annotations__     M/home/dcms/DCMS/lib/python3.12/site-packages/torch/_higher_order_ops/utils.pyr   r      s    Kr   r   operatordelayed_errorargskwargsreturnc                    t         j                  j                         5   | |i |}t        j                  | }t        j
                         rt        d |D              r|rkt         j                  j                  j                  dt        |        d      d t        j                  t         j                  fd|      cddd       S t        dt        |              |cddd       S # 1 sw Y   yxY w)a>  If autograd is enabled and any of the arguments require grad this will either
    raise an error or return a DelayedError depending on the value of delayed.

    Args:
        operator: The Operator to call with the *args and **kwargs with
        op_name: The name of the Operator
        delayed_error: If True, return a DelayedError instead of raising an error
        args: The flattened operands to the Operator
        kwargs: The keyword arguments to the Operator

    Raises:
        RuntimeError: If autograd is enabled and any of the arguments to the Operator
    c              3   j   K   | ]+  }t        |t        j                        s|j                   - y wN
isinstancetorchTensorrequires_grad).0fs     r   	<genexpr>z1autograd_not_implemented_inner.<locals>.<genexpr>.   s&      +
 !jELL6QAOO+
s   33zAutograd not implemented for    c                     t        j                  |       st        j                  |       r| j                         } d| _        | S NT)r(   is_floating_point
is_complexdetachr*   )tensors    r   fake_requires_gradz:autograd_not_implemented_inner.<locals>.fake_requires_grad7   s5    ..v6%:J:J6:R!'/3,!Mr   c                        |             S r%   r   )xerr_fnr5   s    r   <lambda>z0autograd_not_implemented_inner.<locals>.<lambda>>   s    F3Ea3H,I r   N)r(   _C_AutoDispatchBelowAutogradpytreearg_tree_leavesis_grad_enabledany
_functionsDelayedErrorr   tree_map_onlyr)   RuntimeError)r   r   r    r!   resultflat_operandsr8   r5   s         @@r   autograd_not_implemented_innerrF      s      
	,	,	. 4*6*..5  "s +
%2+
 (
 ,,993CM?C
" ++LL"I6% , #%B3x=/#RSS/  s   B$C1C11C:opdeferred_errorc                       fd}|S )Nc                  $    t        g| i |S r%   )rF   )r    r!   rH   rG   s     r   innerz'autograd_not_implemented.<locals>.innerF   s    -b.R4R6RRr   r   )rG   rH   rK   s   `` r   autograd_not_implementedrL   E   s    S Lr   c                       }t         t        j                  j                        rt	        j
                         r fd}|}|S )Nc                      t        j                         5  t        j                  j	                        j
                  |  cd d d        S # 1 sw Y   y xY wr%   )fx_tracebackpreserve_node_metar(   fxInterpreterrun)r    fns    r   graph_with_interpreterz;_maybe_run_with_interpreter.<locals>.graph_with_interpreterP   sA    002 ;xx++B/33T:; ; ;s   +AA)r'   r(   rQ   GraphModulerO   has_preserved_node_meta)rT   maybe_interpreted_fnrU   s   `  r   _maybe_run_with_interpreterrY   L   s;    "ehh**+0T0T0V	;  6r   c           	         t         j                  j                         sddlm} t               5  t         j                  j                  j                         5  t               5 }|r	 ||      }nd} t        j                  | |d      | cd d d        cd d d        cd d d        S  | | S # 1 sw Y   nxY w	 d d d        n# 1 sw Y   nxY wd d d        y # 1 sw Y   y xY w)Nr   )+make_eager_backend_with_torch_function_modeeagerT)backend	fullgraph)
r(   _dynamois_compiling torch._dynamo.backends.debuggingr[   _set_compilation_envutilsdisable_cache_limitr   compile)rT   r    r[   metadata_moder]   s        r   _maybe_compile_and_run_fnrg   X   s    ==%%'	
 "# 	QU]]%8%8%L%L%N 	Q:< Q I-XG%GIu}}RDI4PQ Q	Q 	Q 	Q 4yQ Q Q	Q 	Q 	Q 	Q 	Q 	QsA   )CC#(B,	C	C,B51C9	CC	CC c                 R     ddl m t        j                          fd       }|S )Nr   _CURRENT_MAKE_FX_TRACERc                  N    J d        j                   t              g|  S )NzECannot reenter make_fx when we're not under a make_fx tracing session)trace_subgraphrY   )r    rj   rT   s    r   wrappedz reenter_make_fx.<locals>.wrappedl   sC     $/	SR	S/5&55'+
.2
 	
r   )"torch.fx.experimental.proxy_tensorrj   	functoolswraps)rT   rm   rj   s   ` @r   reenter_make_fxrq   i   s(    J__R
 
 Nr   c                 >    ddl m} |t        |       S d } ||       S )Nr   ri   c                 B     t        j                          fd       }|S )Nc                  `    ddl m}  ||       }| t        d      |  S  t              |  S )Nr   r
   fake)tracing_mode)torch._guardsr   r   )r    r   	fake_moderT   s      r   rm   zN_maybe_reenter_make_fx.<locals>._maybe_make_fx_with_fake_mode.<locals>.wrapped   s=    :,T2	$ <72F;TBB"wr{D))r   )ro   rp   )rT   rm   s   ` r   _maybe_make_fx_with_fake_modez=_maybe_reenter_make_fx.<locals>._maybe_make_fx_with_fake_mode   s%    __R 	* !	* Nr   )rn   rj   rq   )rT   rj   ry   s      r   _maybe_reenter_make_fxrz   x   s(    J*r""	 -R00r   c               #   $  K   t         j                  j                  j                  } t         j                  j
                  j                  }	 dt         j                  j                  _        dt         j                  j
                  _        d  | t         j                  j                  _        |t         j                  j
                  _        y # | t         j                  j                  _        |t         j                  j
                  _        w xY ww)NFT)r(   rQ   _symbolic_trace_is_fx_tracing_flagr_   configallow_empty_graphs)_old_is_tracing_old_allow_empty_graphss     r   rb   rb      s     hh..BBO#mm22EEJ 8=  426/7F  42I/ 8G  42I/s    A	DAC ?DA DDgmc                 h   | j                   j                  d      D cg c]  }|j                  j                  dd         }}t	        | |      \  }}}}t        |      dkD  ry| j                         D ]7  \  }}t        |t        j                  j                        s+t        |      s7 y yc c}w Nplaceholder)rG   valr   TF)graph
find_nodesmetagetcheck_input_alias_and_mutationlennamed_childrenr'   r(   rQ   rV   _detect_input_mutation)r   phexample_inputsinp_mutation_modules         r   r   r      s    +-88+>+>-+>+P%'E4 N  ;2~NL!Q
<1&&( 	6fehh223%f-
 s   #B/c                     | j                   j                  d      D cg c]  }|j                  j                  dd         }}t	        | |      \  }}}}t        |      dkD  st        |      dkD  ryyc c}w r   )r   r   r   r   r   r   )r   r   r   r   inp_inp_alias_mapinp_out_alias_maps         r   _detect_input_aliasr      s    +-88+>+>-+>+P%'E4 N  2P
N2.A+Q !S):%;a%?s   #A3inputsc                     t        |      }d}|d}t               5   t        | ||d      | cd d d        S # 1 sw Y   y xY w)Nrealru   F)rv   pre_dispatch_error_on_data_dependent_ops)r   r   r   )rT   r   r   rx   rv   s        r   _maybe_fake_tracingr      s[     (IL
 
%	& 
w%%).	

   s	   8Ac                     	 t        | ||      } t        |       xs t	        |       S # t        $ r Y yt        $ r}|d }~ww xY wr0   )r   r   	Exceptionr   r   )r   r   r   es       r   %has_potential_input_alias_or_mutationr      sQ     V\: ""%@)<R)@@ -   s   ' 	AA<Ac                 n    	 t        | ||      }t        |      S # t        $ r Y yt        $ r}|d}~ww xY w)z
    Dispatch-trace the branch with inputs and check if
    producing graph has mutable op on the input. This is
    bit restrictive as the branch must be traceable.
    TN)r   r   r   r   branchr   r   r   r   s        r   $_has_potential_branch_input_mutationr      sF     > ""%% -       	44/4c                 n    	 t        | ||      }t        |      S # t        $ r Y yt        $ r}|d}~ww xY w)z
    Dispatch-trace the branch with inputs and check if
    producing graph has output aliasing the branch input. This is
    bit restrictive as the branch must be traceable.
    TN)r   r   r   r   r   s        r   !_has_potential_branch_input_aliasr      sF     > r"" -   r   c                 z    d}d}|s2| d| }t        | j                  j                  |      r|dz  }n|}|s2||fS )zKReturns a unique name and id for a graph to be added to a proxy_mode tracerNr   r   r.   )hasattrtracerroot)
proxy_modeprefix	next_namei	candidates        r   unique_graph_idr     sU    
 I	AhasO	:$$))95FA!I  i<r   c                 H   ddl m} ddlm} t	        | t
        j                        r| j                  t
        j                  k7  rTt        j                  | j                         | j                         | j                  | j                  | j                        S | }t	        | |      r-t        j                  |         ||       }|j#                         S t        j                  |       r*t        j                  |        t        j                   |       }|j#                         S | S )Nr   )from_fun)FunctionalTensor)dtyper*   device)torch._functorch.aot_autogradr   #torch._subclasses.functional_tensorr   r'   r(   r)   r   boolempty_stridedsizestrider*   r   _sync_is_functional_tensor_from_functional_tensorclone)tr   r   maybe_unfunc_ts       r   	_from_funr     s    6D!U\\"77ejj &&
ggooxx  N!-.A!)! "'')) ,,Q/ A!&!>!>q!A!''))Hr   c                     | D ch c]5  }t        |t        j                        rt        |j	                               7 c}fd}|S c c}w )Nc                     t        | t        j                        r+t        | j	                               v r| j                         S | S r%   )r'   r(   r)   r   _typed_storager   )r   input_storages    r   maybe_clonez2clone_outputs_aliasing_inputs.<locals>.maybe_clone=  s8    q%,,'q//12mC779r   )r'   r(   r)   r   r   )r    argr   r   s      @r   clone_outputs_aliasing_inputsr   6  sK     c5<<( 	s))+,M s   :A
c                       fd}|S )Nc                       |  }||D cg c],  }t        |t        j                        r|j                  rdnd. c}fS c c}w )NTFr&   )r    fw_outretrT   s      r   fw_with_masksz,prepare_fw_with_masks.<locals>.fw_with_masksI  sN    T
 sELL1c6G6GDUR
 
 	
 
s   1Ar   )rT   r   s   ` r   prepare_fw_with_masksr   H  s    
 r   c           
         t         j                  t        t         j                  ft	        fd|D              s$J d d|D cg c]  }t        |       c}        g }t        | |      D ]Y  \  }}||j                  |       |j                  t        |t         j                        rt        j                  |      nd        [ |S c c}w )Nc              3   6   K   | ]  }t        |        y wr%   )r'   )r+   oallowed_typess     r   r-   z(unmask_none_gradients.<locals>.<genexpr>X  s      )*
1m$s   zoperands can only be of 	 but got )
r(   r)   intSymIntalltypezipappendr'   
zeros_like)gradsoperandsr   unmasked_gradsgr   s        @r   unmask_none_gradientsr   V  s    \\35M .6  X	!-	H:Uq47:U9VWX  NE8$ 	1=!!!$
 !!'1!U\\'B  #	  ;Vs   Cc                     t               5 }t        |      x}F|j                  |       |j                  )|j                  |j                  j	                                 | | cd d d        S # 1 sw Y   y xY wr%   )r   r   enter_context	shape_envignore_fresh_unbacked_symbols)rT   r    	ctx_stackrx   s       r    _maybe_fake_prop_ignore_unbackedr   k  sq    	 	)$//I<##I."".''''EEG 4y  s   AA--A6c           	          ddl m}m  |d d d i ddd      |D cg c]  }t        |       }}t	        |       t               | } fd}r@t        |      t        |      z   }	 t        |      t        |      t        |	      f      }
||
fS t        |      }	 t        |      t        |      t        |	      z    }
||
fS c c}w )Nr   )	AOTConfigcreate_jointFfw_compilerbw_compilerpartition_fndecompositionsnum_params_buffersaot_idkeep_inference_input_mutationsc                  (   r| d   }| d   dd  }n
| d  }| d  } t        
      	      } |t        |      |D cg c]  }||j                  s| c}      \  }}t        ||      }t	        |       }t        j                  ||      S c c}w )Nr   r.   )
aot_config)r   listr*   r   r   r<   tree_map)joint_operands_gradsr   r   jointgradr   r   r   r   dummy_aot_configrT   	num_gradsuse_output_and_grad_bws           r   joint_fnz$create_fw_bw_graph.<locals>.joint_fn  s    !(+E)!,RS1F()4E))*5F226CSTL#Odt'7D<N<NTO
5 /uf= 44HI{N;; Ps   B
B
B
)r   r   r   r   r   rz   r   )rT   r   	fw_inputs
fw_outputsr   outexample_gradfw_graphr   example_xs_outjoint_graphr   r   r   s   ``         @@@r   create_fw_bw_graphr  x  s    E" !', /99sIcN9L9L!I)%b)95H< <. i4
+;;6,X6,n!56
 [   i6,X6< 4#77
 [  M :s   Cc                 V   t        j                  |       \  }t        d D              st        d       t        fdD              s&t        dD  cg c]  } | j                   c}        t         }|D cg c]  }t        j                  ||       }}|S c c} w c c}w )Nc              3   P   K   | ]  }t        |t        j                           y wr%   r'   r(   r)   )r+   xss     r   r-   z"_unstack_pytree.<locals>.<genexpr>  s     >z"ell+>   $&zLeaves of xs must be Tensor c              3   b   K   | ]&  }|j                   d    d    j                   d    k(   ( yw)r   N)shape)r+   r  flat_xss     r   r-   z"_unstack_pytree.<locals>.<genexpr>  s-     Dbrxx{gaj..q11Ds   ,/z3Leaves of xs must have same leading dimension size )r<   tree_flattenr   rC   r  r   tree_unflatten)r  inspecatuplepytreesr  s        @r   _unstack_pytreer    s    ))"-OGV>g>>9'CDDDGDDAV]B^PR288B^A_`
 	
 	WAABCv$$UF3CGCN C_
 Ds   B!
 B&c                    g }d }| D ]+  }t        j                  |      \  }}|j                  |       - |J t        | }g }|D ]k  }t	        d |D              r%|j                  t        j                  |             :t	        d |D              r|j                  d        ^t        d| d       t        j                  ||      S )Nc              3   P   K   | ]  }t        |t        j                           y wr%   r
  r+   leafs     r   r-   z _stack_pytree.<locals>.<genexpr>  s     A$z$-Ar  c              3   $   K   | ]  }|d u  
 y wr%   r   r  s     r   r-   z _stack_pytree.<locals>.<genexpr>  s     1$1s   zCannot stack .)	r<   r  r   r   r   r(   stackrC   r  )r  flat_outout_specptflat_ptbstacked_outleavess           r   _stack_pytreer%    s    HH !"//3 ! XAK 	:A&AAu{{6231&11 t$vha899	:   h77r   c                 h   t        d |D              sJ |       g g g}g }|D ]E  }t        |t        j                        rdnd}||   j	                  |       |j	                  |       G t        | d      rJ d       t        | d      rJ d        | j                  |d     |d   | _        || _        y )Nc           
   3      K   | ]=  }t        |t        j                  t        j                  t        t        d       f       ? y wr%   )r'   r(   r)   r   r   r   r+   r   s     r   r-   z8save_tensors_and_symints_for_backward.<locals>.<genexpr>  s1      KN
3u||S$t*EFs   AAr   r.   sym_int_argsz'ctx already has sym_int_args attribute.poszctx already has pos attribute.)	r   r'   r(   r)   r   r   save_for_backwardr)  r*  )ctxr    partitioned_argsr*  r   idxs         r   %save_tensors_and_symints_for_backwardr/    s     RV    $&r(
C c5<<0aa$$S)

3
 sN+V-VV+sE"D$DD"C+A./'*CCGr   c                    g }d}d}| j                   }| j                  D ]D  }|dk(  r|j                  ||          |dz  }"|j                  | j                  |          |dz  }F ||z   t	        | j                        k(  sJ t        |      S )Nr   r.   )saved_tensorsr*  r   r)  r   r  )r,  r    t_idxs_idxr1  ps         r   saved_tensors_and_symintsr5    s    DEE%%MWW 6KKe,-QJEKK((/0QJE 5=CL(((;r   c            	      ,    ddl m}   | d d d i ddd      S )Nr   r   Fr   )r   r   r7  s    r   get_dummy_aot_autograd_configr8    s'    7', r   r   dimc                 0    t        j                  | |d      S )Nr   )r(   select_copy)r   r9  s     r   first_slice_copyr<  "  s    QQ''r   meta1meta2c                    ddl m} g }t        j                  D ]C  }|s|dk(  rt	        | |      }t	        ||      }	 ||k7  r|j                  d| d| d| d       E |S # |$ r%}|j                  d| d| d| d       Y d }~md }~ww xY w)Nr   )GuardOnDataDependentSymNoder*   'z: z vs )%torch.fx.experimental.symbolic_shapesr@  r   _fieldsgetattrr   )	r=  r>  
check_gradr@  
pair_diffs	meta_nameval1val2r   s	            r   diff_tensor_metarJ  '  s     RJ#++ 
	i?:ui(ui(	t|!!Ai[4&TF!"DE
  + 	)BtfDa@A	s    A!!B&BBlifted_args.c           	          t         j                  t        t         j                  f}t	        d | D              sJ |  d| dt        d | D                      y )Nc              3   z   K   | ]3  }t        |t        j                  t        t        j                  f       5 y wr%   )r'   r(   r)   r   r   r(  s     r   r-   z/validate_subgraph_args_types.<locals>.<genexpr>F  s+      ?B
3sELL9:s   9;z can only be of r   c              3   2   K   | ]  }t        |        y wr%   )r   r(  s     r   r-   z/validate_subgraph_args_types.<locals>.<genexpr>H  s     DfSVT#YDfs   )r(   r)   r   r   r   r  )rK  r   s     r   validate_subgraph_args_typesrO  D  s^    \\35M FQ  i
&}oYuDfZeDf?f>ghi r   	fake_argsc           
         t               5  	 ddlm} dt        t           fd}dt
        fd}t               5 }|j                  t        j                  d             |D cg c]&  }t        |t        j                        r ||      n|( }}|D cg c]
  } ||       }}t        | |      }	t        |	t        t        f      s|	gn|	}	|D cg c]
  } ||       }
}t        t!        ||
            D cg c]  \  }\  }}||k7  s| }}}}d d d        t        |      D ci c](  \  }}t        |t        j                        r	 ||      |* }}}t        |      D ci c]9  \  }}t        |t        j                        r| ||         |k7  r|| ||         ; }}}t        	      D ci c](  \  }}t        |t        j                        r	 ||      |* }}}t        |	      D ci c]9  \  }}t        |t        j                        r| ||         |k7  r|| ||         ; }}}t              D ci c]5  \  }}t        |t        j                        r ||      |v r|| ||         7 }}}|||fcd d d        S c c}w c c}w c c}w c c}}}w # 1 sw Y   xY wc c}}w c c}}w c c}}w c c}}w c c}}w # 1 sw Y   y xY w)Nr   )clone_preserve_stridesr"   c                 ~    t        | t        j                        r#t        | t              sJ d       | j                  S y )NzOnly fake tensor is allowed)r'   r(   r)   r   _versionr   s    r   _tensor_versionz7check_input_alias_and_mutation.<locals>._tensor_versionW  s3    !U\\*!!Z0O2OO0zz!r   c                 4    t        | j                               S r%   )r   r   rU  s    r   _tensor_storagez7check_input_alias_and_mutation.<locals>._tensor_storage]  s    !!"2"2"455r   F)r   torch._prims_commonrR  r   r   r   r   r   r(   inference_moder'   r)   r   r   r  	enumerater   )r   rP  rR  rV  rX  r   r   clonedbeforeoutputsafterr   v1v2mutated_inputsinpinp_storage_mapr   r  out_storage_mapout_out_alias_mapr   s                         r   r   r   K  s    
%	& >W	
 	?	(3- 		6. 	6 [ 	I ##E$8$8$?@ % 0:#u||/L&s+RUUF  7==soc*=F=6r6BG'1'D%='IwiwG5;<c_S)<E<%.s65/A%B !a"bbBhN 	& $I.
3#u||, C !#
 
 $I.
3#u||, 45: s344
 
 $G,
3#u||, C !#
 
 $G,
3#u||, 45: s344
 
 $F+
3#u||,1E1X s344
 

 02CEVV}>W >W, > =	 	"






s>W >Ws   -K)J#!+JJ#J!-J#JJ#8J	JJ#K'-J0K%>J6#K4-J<!K2>K0K:K;KJ##J-	(&KK)F)r   )T)Iro   
contextlibr   r   dataclassesr   typingr   r   r   r	   r(   torch.fx.tracebackrQ   	tracebackrO   torch.utils._pytreerc   _pytreer<   rw   r   
torch._opsr   torch._subclasses.fake_tensorr   rn   r   r   r   torch.fx.passes.shape_propr    torch.multiprocessing.reductionsr   rC   r   r   rF   rL   rY   rg   rq   rz   rb   rV   r   r   r   r   r   r   r   r   r   r   r   r   r   r  r  r%  r/  r5  r8  r)   r   r<  r   rJ  r  rO  dictr   r   r   r   <module>rs     s1    0 ! 1 1  ) ) $ $ * # 4 
 6 ;   ''+/'8;'GJ''T t  	 "12 J J,uxx33   	EHH00 	T 	DI $
A&$#$ <$*B!J 8H$ ( (3 (u|| ( >B"0	#Y:ieE#s(OT#Y4N.O iBWBWJBW 49d38nd38nd38nDEBWr   