U
    ªÊ¹j×6  ã                   @   s8  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
m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mZmZ dd
lmZ ddlmZmZm Z  d dl!m"  m#Z$ e %e&¡Z'dd„ Z(edd„ ƒZ)eej*e
dœdd„ƒZ+d0dd„Z,dd„ Z-eej*e
dœdd„ƒZ.G dd„ dej/ƒZ0eej*e
dœdd„ƒZ1edd„ ƒZ2d d!„ Z3ej4j5Z5e5j6e5j7e5j8e5j9e5j:e5j;e5j<e5j=e5j>e5j?e5j@e5jAe5jBe5jCjDe5jCjEe5jFe5jGe5jHe5jIe5jJe5jKe5jLhZMeeMƒZMed"d#„ ƒZNee
ejOf d$œd%d&„ZPd'd(„ ZQd aRd)d*„ ZSd+d,„ ZTd1d.d/„ZUdS )2é    N)Úcontextmanager)Úpartial)ÚCallableÚUnion)ÚSymInt)Úget_decompositions)Úbind_symbolsé   )Úaot_functionÚ
aot_moduleÚmake_boxed_compiler)Ústrip_overloads)Údefault_partitionÚ
draw_graphÚ#min_cut_rematerialization_partitionc                 C   s6   | j jD ] }|jtjjjkrtjjj|_q|  ¡  | S ©N)	ÚgraphÚnodesÚtargetÚtorchÚopsÚatenÚ_to_copyÚtoÚ	recompile)Úfx_gÚnode© r   úY/var/www/html/bwave/python/venv/lib/python3.8/site-packages/torch/_functorch/compilers.pyÚ_canonicalize!   s
    r   c               	   c   s*   t j d¡} z
d V  W 5 t j | ¡ X d S )NF)r   Ú_CZ_jit_set_autocast_mode)Zold_jit_autocast_flagr   r   r   Ú_disable_jit_autocast)   s    
r!   )r   Úreturnc              	   C   s  t ƒ �� t| ƒ | jjD ]F}|jtjjjkrt	|j
ƒdkrt	|jƒdkrd|jkrtjjj|_q| jjD ]<}i }|j ¡ D ]"\}}t|tjƒr–|j}|||< q|||_qj| j ¡  |  ¡  tj | ¡}tj |j¡ tj | ¡ ¡}tj |¡}tdd„ |D ƒƒ�s||Ž  W 5 Q R X |S )a  
    Compiles the :attr:`fx_g` with Torchscript compiler.

    .. warning::
        This API is experimental and likely to change.

    Args:
        fx_g(fx.GraphModule): The input Fx graph module to be compiled.

    Returns:
        Torch scripted model.
    r	   Údtypec                 s   s   | ]}t |tjjƒV  qd S r   )Ú
isinstancer   Z_subclassesZ
FakeTensor)Ú.0Útr   r   r   Ú	<genexpr>_   s     zts_compile.<locals>.<genexpr>)r!   r   r   r   r   r   r   r   r   ÚlenÚargsÚkwargsr   Úitemsr$   ÚdeviceÚtypeZlintr   ÚjitÚscriptr    Z_jit_pass_remove_mutationÚfreezeÚevalZoptimize_for_inferenceÚany)r   Úinpsr   Z
new_kwargsÚkÚvÚfr   r   r   Ú
ts_compile2   s8    
ÿþýü

r7   Tc                 C   s   t | jƒ t| ||d� | S )N)Ú
clear_meta)ÚprintÚcoder   )r   Ú_Únamer8   r   r   r   Ú_draw_graph_compiled   s    
r=   c                 C   s   t tt| d�ƒS )N©r<   )r   r   r=   r>   r   r   r   Údraw_graph_compilej   s    
ÿr?   c                 C   s   | S )zÆ
    Returns the :attr:`fx_g` Fx graph module as it is. This is a no-op compiler
    and can be used to check accuracy.

    .. warning::
        This API is experimental and likely to change.

    r   ©r   r;   r   r   r   Únopp   s    
rA   c                       s(   e Zd Z‡ fdd„Z‡ fdd„Z‡  ZS )ÚDebugInterpreterc                    s"   t | jf|žŽ | _tƒ j|Ž  d S r   )r   ÚmoduleÚsymbol_mappingÚsuperÚrun)Úselfr)   ©Ú	__class__r   r   rF   }   s    zDebugInterpreter.runc           
         sÜ   ‡fdd„‰‡fdd„‰‡fdd„‰ ‡ ‡fdd„}t ƒ  |¡}d	|jkrØt |jd	 ¡\}}t |¡\}}t|ƒt|ƒks”tt|ƒ› d
t|ƒ› �ƒ‚ttt|ƒƒ||ƒD ].\‰}}	t	|	t
jƒsÀq¨|||	‡‡fdd„ƒ q¨|S )Nc                    sB   t | tƒs| S t | jj ˆ j¡¡}t|j	ƒdks:t
|ƒ‚t|ƒS )Nr   )r$   r   ÚsympyÚexpandr   ÚexprZxreplacerD   r(   Zfree_symbolsÚAssertionErrorÚint)ÚniÚr)rG   r   r   Úsubst_symintƒ   s
    
z/DebugInterpreter.run_node.<locals>.subst_symintc                    s   t ‡ fdd„| D ƒƒS )Nc                 3   s   | ]}ˆ |ƒV  qd S r   r   )r%   rO   ©rQ   r   r   r'   ‹   s     zHDebugInterpreter.run_node.<locals>.subst_symint_tuple.<locals>.<genexpr>)Útuple)ZnisrR   r   r   Úsubst_symint_tupleŠ   s    z5DebugInterpreter.run_node.<locals>.subst_symint_tuplec                    sT   ˆ |   ¡ ƒdkrPt| jƒD ]4}ˆ |  |¡ƒ| |¡krˆ |  |¡ƒdkr dS qdS )Nr   r	   FT)ZnumelÚrangeÚndimÚstrideÚsize)ÚaÚbÚidxrR   r   r   Úcheck_significant_strides�   s
    *z<DebugInterpreter.run_node.<locals>.check_significant_stridesc              	      s¼   t |ƒst‚| j|jks6t|ƒ › d| j› d|j› �ƒ‚ˆ|  ¡ ƒ| ¡ kszt|ƒ › d|  ¡ › dˆ|  ¡ ƒ› d| ¡ › �ƒ‚ˆ | |ƒ}|s¸t|ƒ › d|  ¡ › dˆ|  ¡ ƒ› d| ¡ › �ƒ‚d S )Nz: ú != z aka )ÚcallablerM   r#   rX   rW   )ÚnvÚrvÚdescZsame_strides)r\   rT   r   r   Úcheck”   s    **ÿ
z(DebugInterpreter.run_node.<locals>.checkÚvalr]   c                      s   dˆ › dˆj › �S )Nzoutput z where )rD   r   )ÚirG   r   r   Ú<lambda>ª   ó    z+DebugInterpreter.run_node.<locals>.<lambda>)rE   Úrun_nodeÚmetaÚpytreeZtree_flattenr(   rM   ÚziprU   r$   r   ÚTensor)
rG   Únrb   rP   Zn_valsZn_specZr_valsZr_specr_   r`   rH   )r\   rd   rG   rQ   rT   r   rg   �   s    
*zDebugInterpreter.run_node)Ú__name__Ú
__module__Ú__qualname__rF   rg   Ú__classcell__r   r   rH   r   rB   |   s   rB   c                 C   s
   t | ƒjS )z¨
    Returns a (slow) interpreter over the FX graph module that also checks
    various debugging properties (e.g., that tracing strides matched real
    strides.)
    )rB   rF   r@   r   r   r   Ú	debug_nop®   s    rq   c                 C   s(   t | ƒ tj | ¡}tj | ¡ ¡}|S r   )r   r   r.   r/   r0   r1   )r   r;   r6   r   r   r   Úsimple_ts_compile·   s    rr   c                 C   s
   t | tƒS r   )r
   rr   )r6   r   r   r   Únnc_jit¿   s    rs   c                 C   s   t | jƒ | S r   )r9   r:   r@   r   r   r   Úprint_compileà   s    
rt   )Úfnc                 K   sB   t t ttdœ}| |¡ t| tjjƒr2t| f|ŽS t	| f|ŽS dS )a  
    Wrapper function over :func:`aot_function` and :func:`aot_module` to perform
    memory efficient fusion. It uses the
    :func:`min_cut_rematerialization_partition` partitioner to perform efficient
    recomputation. It uses NVFuser to compile the generated forward and backward
    graphs.

    .. warning::
        This API is experimental and likely to change.

    Args:
        fn (Union[Callable, nn.Module]): A Python function or a ``nn.Module``
            that takes one ore more arguments. Must return one or more Tensors.
        **kwargs: Any other overrides you want to make to the settings

    Returns:
        Returns a ``Callable``  or ``nn.Module`` that retains the eager behavior
        of the original :attr:`fn`, but whose forward and backward graphs have
        gone through recomputation optimizations, and the graphs have been
        compiled with nvfuser.

    ©Zfw_compilerZbw_compilerZpartition_fnZdecompositionsN)
r7   r   Údefault_decompositionsÚupdater$   r   ÚnnÚModuler   r
   )ru   r*   Úconfigr   r   r   Úmemory_efficient_fusionæ   s    ü
r|   c                 C   sH   |   d¡ tddd„ |D ƒ› d�ƒ ddlm} |ƒ  ¡ |Ž  t| |ƒS )NÚfooaQ  
##############################################################
# To minimize FX graph, copy and paste the below and run it  #
##############################################################

import torch
import torch.fx as fx
from functorch.compile import minifier, check_nvfuser_subprocess, check_nvfuser_correctness_subprocess

inps = c                 S   s   g | ]}|j |jf‘qS r   )Úshaper#   )r%   rd   r   r   r   Ú
<listcomp>  s     z!debug_compile.<locals>.<listcomp>a?  
inps = [torch.ones(shape, dtype=dtype, device='cuda') for (shape, dtype) in inps]
from foo import FxModule
mod = FxModule().cuda()

with torch.jit.fuser("fuser2"):
  # check_nvfuser_subprocess can be replaced with check_nvfuser_correctness_subprocess
  minifier(fx.symbolic_trace(mod), inps, check_nvfuser_subprocess)
r   )ÚFxModule)Ú	to_folderr9   r}   r€   Úcudar7   )r   r3   r€   r   r   r   Údebug_compile  s    
	÷ÿrƒ   c                 C   s¶   g }t | dƒ�ž}t |¡}g }|D ]„}t|ƒdkrD|}|t ¡ ƒ}nX|\}}}}	}
|	tjtjtj	tj
tjtjtthkrŒtjdd||	|
d�}ntj||	|
d�}| |¡ q"W 5 Q R X |S )zZ
    Return a random input for the given inputs meta generated from _save_fx_default.
    Úrbr	   r   )r#   r,   )ÚopenÚpickleÚloadr(   ÚrandomZrandr   rN   Zint32Zint64ÚboolZuint8ÚfloatÚrandintÚappend)Zinput_data_pathÚinputsr6   Zinputs_metarh   r-   Úinputr~   rW   r#   r,   r   r   r   Ú
get_inputs-  s.    
ø
r�   c           	         sb   ddl m} ‡fdd„‰‡ ‡‡‡fdd„‰‡fdd„}‡fd	d
„}‡fdd„}||||||td�S )aO  
    The forward, backward, and joint computation graph will be stored in
    {folder_name}/{current_name}/{current_name}_forward_{graph_index},
    {folder_name}/{current_name}/{current_name}_backward_{graph_index}, and
    {folder_name}/{current_name}/{current_name}_joint_{graph_index} respectively.
    The input shape of the graphs will be stored in the .input files.
    These files can be loaded with pickle,
    and is a list of format (type, shape, stride, dtype, device).
    In the case of type = int or float, it is just (type,).
    For joint graph input, it is a nested list [[],[]]
    where the two inner lists have the same format.
    If dump_example_input is True, example_inputs will be stored in .pt file.
    Since each function might produce multiple graphs,
    the graph_index is used to distinguish difference graphs
    r   )Úaot_module_simplifiedc                    sœ   g }t | ƒdkrBt| d tƒrB|ˆ | d ƒ7 }|ˆ | d ƒ7 }|S | D ]P}t|ƒtksbt|ƒtkrt| t|ƒf¡ qF| t|ƒ|j| ¡ |j	|j
f¡ qF|S )Nr   r	   )r(   r$   rS   r-   rN   rŠ   rŒ   r~   rW   r#   r,   )r)   Ú
input_metaÚarg)Úget_input_metar   r   r“   ^  s    ÿz(_save_fx_default.<locals>.get_input_metac                    s2  t | jjƒdkr(t tjdˆ |t¡ d S t | ¡}|j 	t
jj ¡ ¡ | ¡  ˆ|ƒ}tj ˆ› dˆ › �¡}|s„t ˆ› dˆ › �¡ | ˆ› dˆ › dˆ › d|› dt› �	¡ t |tˆ› dˆ › dˆ › d|› dt› dˆ › d|› dt› d�dƒ¡ ˆ�r.t
 |ˆ› dˆ › dˆ › d|› dt› dˆ › d|› dt› d�¡ d S )Nr   z!No nodes in graph {%s}_{%s}_{%s}.ú/r;   z.inputÚwbz.pt)r(   r   r   ÚlogÚloggingÚWARNINGÚgraph_indexÚcopyÚdeepcopyZset_codegenr   ÚfxZCodeGenr   ÚosÚpathÚexistsÚmakedirsr�   r†   Údumpr…   Úsave)Z
gm_to_saver)   Ú	type_nameÚgmr‘   ZisExist)Úcurrent_nameÚdump_example_inputÚfolder_namer“   r   r   Úgraph_saver_helperm  s>    û
ÿ2þþ2þz,_save_fx_default.<locals>.graph_saver_helperc                    s   ˆ | |dƒ | S )NÚforwardr   )r¤   Zfw_args©r¨   r   r   Úgraph_saver_forward’  s    z-_save_fx_default.<locals>.graph_saver_forwardc                    s   ˆ | |dƒ t d7 a | S )NZbackwardr	   )r™   )r¤   Zbw_argsrª   r   r   Úgraph_saver_backward–  s    z._save_fx_default.<locals>.graph_saver_backwardc                    s   ˆ | |dƒ t | |ƒS )NZjoint)r   )r¤   Z
joint_argsrª   r   r   Úgraph_saver_jointœ  s    z+_save_fx_default.<locals>.graph_saver_jointrv   )Zfunctorch.compiler�   rw   )	r¥   r§   r¦   r¤   Zexample_inputsr�   r«   r¬   r­   r   )r¥   r¦   r§   r“   r¨   r   Ú_save_fx_defaultL  s    %úr®   Fc                 C   s   da tt| ||ƒS )as  
    Dump the forward, backward, and joint computation graph.
    Example Usage:
    save_fx_func = graph_dumper_aot(current_name, folder_name, dump_example_input = False)
    optimize_ctx = torchdynamo.optimize(
        save_fx_func
    )
    with torch.enable_grad():
        with optimize_ctx:
            result = forward_and_backward_pass(model, example_inputs)
    r   )r™   r   r®   )r¥   r§   r¦   r   r   r   Úgraph_dumper_aot«  s    r¯   )T)F)Vrš   r—   r�   r†   rˆ   Ú
contextlibr   Ú	functoolsr   Útypingr   r   rJ   r   r   Ztorch.fxrœ   Ztorch.nnry   Ztorch._decompr   Z%torch.fx.experimental.symbolic_shapesr   Zaot_autogradr
   r   r   Zcompile_utilsr   Zpartitionersr   r   r   Ztorch.utils._pytreeÚutilsZ_pytreeri   Ú	getLoggerrm   r–   r   r!   ZGraphModuler7   r=   r?   rA   ZInterpreterrB   rq   rr   rs   r   r   ÚdetachZgelu_backwardZleaky_relu_backwardZsigmoid_backwardZthreshold_backwardZhardtanh_backwardZhardsigmoid_backwardZhardswish_backwardZtanh_backwardZsilu_backwardZelu_backwardZcudnn_batch_normZcudnn_batch_norm_backwardZmasked_fillZScalarrk   ZeluZ
leaky_reluZhardtanhZ	hardswishZhardsigmoidZconj_physicalZis_same_sizerw   rt   rz   r|   rƒ   r™   r�   r®   r¯   r   r   r   r   Ú<module>   sˆ   

1
2
ê
ÿ'_