U
    9%e5                     @   s  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 d dl	Z	d dl
m  mZ d dlmZmZ d dlmZ d dlmZ d dlmZ ddlmZ e	jjZe	jjZe	jjZeeZd	d
 Zee  dddZ!dd Z"G dd de	j#j$Z%e	jj&' dd Z(e	j#j)e	j#j)ee	j*j+ ee	j#j)ee  f dddZ,G dd de	j-Z.e	jj&' dd Z/e	jj&' dd Z0dd Z1dd  Z2ed!d" Z3dS )#    N)CallableListOptionalTuple)dynamo_timedlazy_format_graph_code)fx_graph_cse)freezing_passes)view_to_reshape   )configc              	   C   s   | j }t| dsd| _| j}d| }t| |s2q<|d7 }q|d | _||8 |d|di }|| |j|j || W 5 Q R X | 	|| t
| || d S )N_frozen_param_countr   Z_frozen_paramr   get_attr )graphhasattrr   inserting_beforeZcreate_nodeZreplace_all_uses_withmetaupdate
erase_nodeZregister_buffersetattr)gmnodeconstantgiqualnameZnew_input_noder   r   W/var/www/html/Darija-Ai-API/env/lib/python3.8/site-packages/torch/_inductor/freezing.pyreplace_node_with_constant   s     





r   )returnc           
      C   s   dd | j jD }|dt| }g }dd |jD }tt||D ]6\}\}}	||jksb||krn|| qDt| |	| qD|	t
t|t| |   |S )z
    Replaces the parameters of a PyTorch GraphModule with constants wherever possible.
    Returns a list of indices representing the input parameters that were not converted to constants.
    c                 S   s   g | ]}|j d kr|qS )placeholder)op).0r   r   r   r   
<listcomp>:   s     
 z1replace_params_with_constants.<locals>.<listcomp>Nc                 S   s   g | ]}|j d k	r|j qS N)Zbase_idx)r"   Zout_infor   r   r   r#   =   s   
)r   nodeslenZoutput_info	enumeratezipZmutated_inp_indicesappendr   extendrange	recompile)
r   Zflat_paramsfw_metadataparamsZfake_inp_nodespreserved_arg_indicesZaliased_input_argsr   Z
real_inputr   r   r   r   replace_params_with_constants5   s    
r0   c                  O   s   dS )NTr   )argskwargsr   r   r   return_trueN   s    r3   c                       s`   e Zd Zdeeejgef  d fddZej	j
jdddZ fd	d
Z fddZ  ZS )ConstantFolderFN)insertable_tensor_checkc                    s@   t  | i | _t | _t | _|| _|d k	r6|nt	| _
d S r$   )super__init__node_replacementscollectionsCounterreplaced_usesobjectunknown_valueskip_constructorsr3   r5   )selfr   r>   r5   	__class__r   r   r7   S   s    
zConstantFolder.__init__)r   c                 C   s   |j tjjjjkrdS dS )NTF)targettorchopsZquantized_decomposedZdequantize_per_channeldefault)r?   r   r   r   r   	is_impured   s    zConstantFolder.is_impurec           
         s  t jj}| |\}}|jdkr,t |S t||fd }| j	|krN| j	S |j
dkrl|j|jjkrl| j	S | jr|j
dkrtdd |D s| j	S t|jt jjrt jj|jjkr| j	S t |}|j
dkrt|t jr| |s|S | |r| j	S || j|< t|j|jfd }|D ],}t|t jjs:q"| j|  d7  < q"| j|g D ]*}	| j|	 t |	j!kr^| j"|	d  q^|S )Noutputr   call_functionr   c                 s   s   | ]}t |tjV  qd S r$   )
isinstancerC   Tensorr"   er   r   r   	<genexpr>   s     z*ConstantFolder.run_node.<locals>.<genexpr>r   )#rC   rD   atenZfetch_args_kwargs_from_envrB   r6   run_nodepytreetree_flattenr=   r!   Z_efficientzerotensorrE   r>   anyrI   Z_opsZ
OpOverloadTagZnondeterministic_seededtagsrJ   r5   rF   r8   r1   r2   fxNoder;   Zuser_to_last_usesgetr&   userspop)
r?   r   rN   r1   r2   Zflattened_inputsoutZflattened_node_inpsnZ	to_deleter@   r   r   rO   m   sP    




zConstantFolder.run_nodec                    s6   i }| j jjD ]}|jdkr| j||< qt j|dS )Nr    )Zinitial_env)moduler   r%   r!   r=   r6   run)r?   envr[   r@   r   r   r]      s
    
zConstantFolder.run)FN)__name__
__module____qualname__r   r   rC   rJ   boolr7   rU   r   rV   rF   rO   r]   __classcell__r   r   r@   r   r4   R   s     	=r4   c                 C   s   t | dd}|  |j D ]\}}t| || qg }| jjD ]2}|jdkr@t|j	dkr@t
| |j || q@|D ]}| j| qx| j  | j  |   d S )NT)r>   r   r   )r4   r]   r8   itemsr   r   r%   r!   r&   rX   delattrrB   r)   r   Zeliminate_dead_codelintr,   )r   cfr   r   Zerased_paramsr   r   r   constant_fold   s    

rh   )	dynamo_gmaot_autograd_gmexample_inputsr   c                    s   t | tjj j}tjj j}|dk	r4|dk	s8tt|||}t	|j
}||_
|   fdd|D }t|| t| tjrt  t|  tdtd| ||fS )a5  
    Inlines parameters that are not mutated into constants and optimizes the graph through constant propagation
    and other techniques. If enabled, the function also discards the original parameters of the module for memory efficiency.

    Assumes that this function is run in dynamo tracing post aot_autograd.

    Args:
        dynamo_gm (torch.fx.GraphModule): The Dynamo constructed GraphModule.
        aot_autograd_gm (torch.fx.GraphModule): The aot_autograd constructed GraphModule to be frozen.
        example_inputs (List[torch.Tensor]): A list of example input tensors to be used in the freezing process.

    Returns:
        Tuple[torch.fx.GraphModule, List[int]]: A tuple containing the frozen GraphModule and a list of indices
        of the inputs that were preserved (not turned into constants).
    Nc                    s   g | ]} | qS r   r   )r"   indrk   r   r   r#      s     zfreeze.<locals>.<listcomp>z%szFROZEN GRAPH)r
   rC   _guardsTracingContextrW   r-   params_flatAssertionErrorr0   r   r   r,   r	   rh   r   Zfreezing_discard_parametersinvalidate_eager_modulesdiscard_traced_gm_paramslogdebugr   )ri   rj   rk   r-   rp   r/   Z	cse_graphZaot_example_inputsr   rm   r   freeze   s(      

rv   c                       s@   e Zd Ze fddZee dddZed
dd	Z	  Z
S )ErasedTensorc                    s   t  | |jddS )Nr   )Zdevice)r6   __new__to)clselemnameZ
owning_modr@   r   r   rx      s    zErasedTensor.__new__)r|   c                 C   s   || _ t|| _d S r$   )erased_nameweakrefrefowning_mod_ref)r?   r{   r|   modr   r   r   r7     s    zErasedTensor.__init__r   Nc                 C   sX   dd t ||fd D }t|dks,t|d }td| d|j d|  d S )Nc                 S   s   g | ]}t |tr|qS r   )rI   rw   rK   r   r   r   r#     s   
z3ErasedTensor.__torch_dispatch__.<locals>.<listcomp>r   zTrying to Run Pytorch Eager Module After Dynamo Freezing. The original parameters have been discarded for memeory efficiency. Found in op z for erased parameter z of )rP   rQ   r&   rq   RuntimeErrorr}   r   )rz   functypesr1   r2   Zerased_tensorsrL   r   r   r   __torch_dispatch__  s    zErasedTensor.__torch_dispatch__)r   N)r_   r`   ra   staticmethodrx   r   strr7   classmethodr   rc   r   r   r@   r   rw      s
   rw   c                  C   s   t jj jj D ]} t| t jj	s(qt
t| jdd| jddD ]V\}}t jj  t||| }W 5 Q R X t|t jjr|d d|_t| || qHqd S NF)recurseT)rC   rn   ro   rW   Zmodule_contextZ
nn_modulesvaluesrI   nnModulelist	itertoolschainnamed_parametersnamed_buffers	_dispatchpythonno_python_dispatcherrw   	Parameterrequires_grad_	_is_paramr   r   	attr_nameZtensorZe_tr   r   r   rr     s    
 

rr   c              
   C   s|   t t| jdd| jddD ]V\}}tjj  t	||| }W 5 Q R X t
|tjjrj|d d|_t| || q d S r   )r   r   r   r   r   rC   r   r   r   rw   rI   r   r   r   r   r   r   r   r   r   rs   )  s    
 

rs   c              	   C   s   | j j^ }}|jd }| j |f |D ]Z}t|jd tjr*tj	|jd sTq*|jd }| j 
tjj|| f}||| q*W 5 Q R X | j   |   dS )z
    Make sure the output node's layout does not change due to compiler optimizations
    by adding aten.as_strided nodes with the expected strides.

    Only used for inference so we can assume all graph outputs are model outputs.
    r   valN)r   r%   r1   r   rI   r   rC   rJ   Z_prims_commonZis_non_overlapping_and_denserH   primsinductor_force_stride_orderrE   stridereplace_input_withrf   r,   )r   _Zoutput_nodeZout_listr[   ftnew_noder   r   r   enforce_output_layout8  s&    
 
 

r   c              
      s   t jjjjt jjjjt jjjjg  fdd| jjD }|D ]^}| j	|H |j
d jd }| jtjj|j
d | f}||j
d | W 5 Q R X q<| j  |   dS )z
    Make sure the as_strided node's input's layout does not change due to compiler
    optimizations, because the as_strided strides info depends on input tensor stride info.
    c                    s   g | ]}|j  kr|qS r   )rB   r"   r[   Zas_strided_opsr   r   r#   b  s     
 z3enforce_as_strided_input_layout.<locals>.<listcomp>r   r   N)rC   rD   rN   Z
as_stridedrE   Zas_strided_Zas_strided_scatterr   r%   r   r1   r   rH   r   r   r   r   rf   r,   )r   Zstrided_nodesr[   r   r   r   r   r   enforce_as_strided_input_layoutW  s    


 
r   c              
   C   s   dd | j jD }|D ]z}|jd }t|jd  dks|jd jtjdrPq| j 	|. | j 
tjj|fdtji}||| W 5 Q R X qt|  t|  dS )	z
    Convert 4d convolution weight tensor to channels last format.

    This pass is performed before freezing so the added nodes can be constant
    folded by freezing.
    c                 S   s   g | ]}|j tjjkr|qS r   )rB   rN   ZconvolutionrE   r   r   r   r   r#   x  s      z9convert_conv_weights_to_channels_last.<locals>.<listcomp>r   r      )memory_formatr   N)r   r%   r1   r&   r   sizeZis_contiguousrC   Zchannels_lastr   rH   rN   clonerE   r   r   r   )r   ZconvsconvZweight_noder   r   r   r   %convert_conv_weights_to_channels_lastp  s$    
r   )4r9   r   loggingr~   typingr   r   r   r   rC   Ztorch.utils._pytreeutilsZ_pytreerP   Ztorch._dynamo.utilsr   r   Ztorch._functorch.compile_utilsr   Z+torch._inductor.fx_passes.freezing_patternsr	   Z#torch._inductor.fx_passes.post_gradr
    r   rD   rN   r   	getLoggerr_   rt   r   intr0   r3   rU   ZInterpreterr4   Z_python_dispatchZ_disable_current_modesrh   ZGraphModuleZ_subclassesZ
FakeTensorrv   rJ   rw   rr   rs   r   r   r   r   r   r   r   <module>   sF   
`


4



