a
    dsa                     @   s  d dl mZmZ d dlmZ d dlZd dlmZ d dlZd dl	Z	d dl
m  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mZ dd	lmZ d dlZejZG d
d dZe Zdd Z dd Z!dd Z"ej#dddZ$d1ej#dddZ%ej#eej#ej#f dddZ&dd Z'dd Z(ej)e*dd d!Z+d"d# Z,e-dd$d% Z.d2ej#eej#ej#f dd'd(Z/d3ejj#e0e0d+d,d-Z1d4d/d0Z2dS )5    )is_sym_nodepy_sym_types)hint_intNdefaultdict)graph_drawer)Tuple   )fx_graph_cseget_aten_target)configc                   @   s   e Zd Zdd ZdS )InvalidNodeBasec                 C   s   dS )NzInvalid Node )selfr   r   f/var/www/html/stable-diffusion-webui/venv/lib/python3.9/site-packages/torch/_functorch/partitioners.py__repr__   s    zInvalidNodeBase.__repr__N)__name__
__module____qualname__r   r   r   r   r   r      s   r   c           	         sX  t  }i  |D ] }||j}|j|_| |< q| jD ]}||v rHq8q8|jdkr\t |< q8|jdkrt	|j
|jfd } fdd|D }t|rt |< q8|| fdd |< q8|jdkr|| fd	d |< q8|jd
kr8q8g }|D ]F}t|t jr.| vrtd| d| |  q|| q|| |  |  |S )a  
    Given a graph, extracts out a subgraph that takes the specified nodes as
    inputs and returns the specified outputs.

    This includes specifying non-placeholder nodes as inputs.

    The general strategy is to initialize all inputs with proxies as we
    encounter them, and trace through the graph, only keeping values which take
    in valid proxies. Then, all dead code is eliminated.
    placeholdercall_functionr   c                    s&   g | ]}t |tjrt  | tqS r   )
isinstancefxNoder   ).0xenvr   r   
<listcomp>9       z6_extract_graph_with_inputs_outputs.<locals>.<listcomp>c                    s    |  S Nr   r   r   r   r   <lambda>=   r   z4_extract_graph_with_inputs_outputs.<locals>.<lambda>Zget_attrc                    s    |  S r    r   r!   r   r   r   r"   ?   r   outputzNode z couldn't be found in env)r   ZGraphr   namemetanodesopInvalidNodepytreetree_flattenargskwargsanyZ	node_copyr   r   RuntimeErrorappendr#   eliminate_dead_codeZlint)	Zjoint_graphinputsoutputs	new_graphnodenew_nodeall_argsZoutput_valuesr   r   r   r   "_extract_graph_with_inputs_outputs   sB    








r7   c                 C   s   | j dkod| jvS Nr   tangentsr'   targetr4   r   r   r   
_is_primalQ   s    r=   c                 C   s   | j dkod| jv S r8   r:   r<   r   r   r   _is_tangentU   s    r>   )joint_modulec                C   s<   t dd | jjD d }|d | }||d  }||fS )Nc                 S   s   g | ]}|j d kr|jqS r#   )r'   r+   r   r4   r   r   r   r   Z   r   z,_extract_fwd_bwd_outputs.<locals>.<listcomp>r   )r)   r*   graphr&   )r?   num_fwd_outputsr2   fwd_outputsbwd_outputsr   r   r   _extract_fwd_bwd_outputsY   s    rF   r   c                C   s  t | |d\}}ttt| jj}ttt| jj}t| j||| | }t| j|| | |}	|	jD ]\}
|
jdkrf|
j	sf|D ]}|j
|
j
kr~||  qq~|D ]}|j
|
j
kr||  qfqqft| j||| | }t| j|| | |}	t| |}t| |	}||fS )NrC   r   )rF   listfilterr=   rB   r&   r>   r7   r'   usersr$   remover   GraphModule)r?   saved_valuessaved_sym_nodesrC   rD   rE   primal_inputsZtangent_inputsZ	fwd_graphZ	bwd_graphr4   Zsaved_valueZ	saved_symZ
fwd_moduleZ
bwd_moduler   r   r   _extract_fwd_bwd_modules`   s(    


rP   )r?   returnc                   s8  t tt| jj}t| |d\}}t| j||}dd |jD  g }g }| jjD ]}	|	j vr`qPt|	rt|	|	 qPd|	j
vr|	jdkr|	j}
tdd |
D sJ |
D ]}|	| qqP fdd	|	jD }d|	j
v rtd
d |D r|D ]}|	| qqP|	|	 qPt t|}t t|}t| |||dS )a  
    Partitions the :attr:`joint_module` in a manner that closely resembles the
    behavior observed in the original ``.forward()`` and ``.backward()`` of the
    callable, i.e., the resulting forward graph contains those operators that
    are executed in the original ``.forward()`` callable passed to
    :func:`aot_function`.

    The default partitioner collects the operators that are between the forward
    inputs and the forward outputs. This helps in finding the tensors which have
    to be stashed for the backward pass. These stashed tensors become the output
    of the generated forward graph. The remaining operators are then placed in
    the backward graph.

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

    Args:
        joint_module(fx.GraphModule): The joint forward and backward graph. This
            is the result of AOT Autograd tracing.

    Returns:
        Returns the generated forward and backward Fx graph modules.
    rG   c                 S   s   h | ]}|j d kr|jqS r@   r'   r$   rA   r   r   r   	<setcomp>   r   z$default_partition.<locals>.<setcomp>tensor_metar   c                 s   s   | ]}|j tjkV  qd S r    )r;   operatorgetitemr   userr   r   r   	<genexpr>   r   z$default_partition.<locals>.<genexpr>c                    s   g | ]}|j  vr|qS r   )r$   r   nZforward_node_namesr   r   r      r   z%default_partition.<locals>.<listcomp>c                 s   s   | ]}t |V  qd S r    r   rZ   r   r   r   rY      r   rN   rC   )rH   rI   r=   rB   r&   rF   r7   r$   r   r/   r%   r'   rJ   allsetrP   )r?   _joint_inputsrC   rO   rD   rE   forward_only_graphrM   rN   r4   rJ   rX   Zbackward_usagesr   r\   r   default_partition   s6    
 	rc   c                 C   s   d}| D ]}||9 }q|S Nr	   r   )r   sir   r   r   _prod   s    
rg   c                 C   sj   t jdt jdt jdt jdt jdt jdt jdt jdt j	dt j
dt jdt jdi}||vr^td|| ||  S )N         r	   zDon't know the size of dtype )torchfloatfloat16Zbfloat16float32float64intZint8int16int32int64Zuint8boolNotImplementedError)numeldtypesizesr   r   r   _tensor_nbytes   s     
ry   )r4   rQ   c                 C   s   d| j v rt| j d }t|tr"dS t|ttfrBtdd |D S t|tjrbtt	|
 |jS tdt| d| j v r| j d }ttt|j}|j}ndS t||S )Nvalr	   c                 s   s.   | ]&}t |tjrtt| |jV  qd S r    )r   rk   Tensorry   r   rv   rw   rZ   r   r   r   rY      r   z_size_of.<locals>.<genexpr>zUnknown metadata type rT   r   )r%   r   r   rH   tuplesumrk   r{   ry   r   rv   rw   r.   typerg   mapZto_size_hintshape)r4   rz   metadatarv   rw   r   r   r   _size_of   s    




r   c                 C   s\   ddl m} |t}| jD ]"}|jdkr||jj  d7  < qtt|	 dd dd d S )	Nr   r   r   r	   c                 S   s   | d S rd   r   r!   r   r   r   r"      r   z_count_ops.<locals>.<lambda>Tkeyreverse)
collectionsr   rp   r&   r'   r;   r   printsorteditems)rB   r   Zcntr4   r   r   r   
_count_ops   s    

r   c                  C   sl   g } t tjjD ]V}ttjj|}t|tjjs2q| D ]*}t||}tj	j
|jv r:| |  qq:q| S r    )dirrk   opsatengetattrr   Z_opsZOpOverloadPacketZ	overloadsTagZ	pointwisetagsr/   )r   	attr_nameZopoverloadpacketoverloadZop_overloadr   r   r   pointwise_ops  s    

r   nvfuserc          ,   K      s  zddl }W n. ty: } ztd|W Y d}~n
d}~0 0 | j  |   | j}tjrht|}|| _| j}	i | jj	D ]}
|
|
j
< qz
fdd}|| \}}}dd }t|dkrt| |
dS t| jj	D ]>}
|
vrd|
_n*td	|
_|
jD ]}t|
j|jd
 |
_qqtjjtjj}jjjjjjjjjjjj j!j"j#j$j%j&j'j(j)j*j+j,j-j.j/j0j1j2j3j4j5j6j7j8j9j:j;j<j=j>j?j@jAjBjCjDjEjFjGjHjIjJjKjLjMjNjOjPjQjRjSjTjUjVjWjXjYjZt[j\j]j^j_j`gK}j]j^jagdkr(||j|jbjcj`jd|je|jTjejf|jgjhjijjjkjljmjnjojpjqjrjsjtjujvjwjxjyjzj{j|j}g 7 }jkjmjij~|jgjljzg7 |jg7 }|7 }|t 7 }durLtnt|jjjg}jjjjjjjjjjjjjg}|| t|B trdd | jj	D }|dd D  }td| t  d fdd fdd}fddfddtdfdd}| |	j	D ]>}
|
jdkrbqL|
|v rj|
j
d dtjd qL|
jd krd!|
jv rjd"|
j
d tjd ||
r|
v rjd"|
j
d tjd d#|
jvod$|
jvpd#|
jv ot|
jd# tj }t|
r,d
}n|r:tj}n||
}j|
j
d |
j
d% |d |
jD ]$}j|
j
d% |j
d tjd qdqL|d"d\}}|\}	t }fd&d'|D D ]$\}|	fd(d'|D  qt } |D ]>\}!}"|!dd) |"dd* ksJ |!dd) }#| |# qd+d, t| jj	D tfd-d'| D fd.d/d0}$ttd1d/ |$}%ttd2d/ |$}$t| |$|%
d3\}&}'trztd4tTd5d6 |$D d	  d7d |&jj	D }(d8d |'jj	D })|(|)@ }*tt}+|&jj	D ]8}
|
j
|*v r4t|
jd9r4|+t|
jj  d
7  < qtd:t|* d;t|( d;t|)  td<t|+ d=d/ d>d? |&|'fS )@ay  
    Partitions the joint graph such that the backward recomputes the forward.
    Recomputing helps in trading off memory bandwidth with computation.

    To create the fwd and bwd graph, we copy the joint graph, manually set the
    outputs to just original forward or backward outputs. And then we run the
    resulting graphs through dead code elimintation.

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

    Args:
        joint_module(fx.GraphModule): The joint forward and backward graph. This
            is the result of AOT Autograd tracing.
        _joint_inputs: The inputs to the joint graph. This is unused.
        compiler: This option determines the default set of recomputable ops.
            Currently, there are two options: ``nvfuser`` and ``inductor``.
        recomputable_ops: This is an optional set of recomputable ops. If this
            is not None, then this set of ops will be used instead of the
            default set of ops.
        num_fwd_outputs: The number of outputs from the forward graph.

    Returns:
        Returns the generated forward and backward Fx graph modules.
    r   NzANeed networkx installed to perform smart recomputation heuristicsc                    s   t   | jjD ]@}|jdkr0d|jv r0 | | v r|jD ]} | q>qttt	| jj}t
| d\}}t| j||}fdd|jD  fdd| jjD }| |fS )Nr   r9   rG   c                    s    h | ]}|j d kr |j qS r@   rR   rA   name_to_noder   r   rS   Q  s   
zNmin_cut_rematerialization_partition.<locals>.classify_nodes.<locals>.<setcomp>c                    s    h | ]}|vr| vr|qS r   r   rA   required_bw_nodesrequired_fw_nodesr   r   rS   S  s   )r`   rB   r&   r'   r;   addrJ   rH   rI   r=   rF   r7   )r?   r4   rX   rO   rD   _rb   unclaimed_nodes)r   rC   r   r   classify_nodesE  s    

z;min_cut_rematerialization_partition.<locals>.classify_nodesc                 S   s6   t | tjsdS d| jv p4d| jv o4t | jd tjS )NFrT   rz   )r   r   r   r%   rk   r{   r!   r   r   r   is_tensor_nodeY  s    z;min_cut_rematerialization_partition.<locals>.is_tensor_noderG   g    eAr	   inductorc                 S   s.   h | ]&}|j d krt|jdrt|jjqS )r   _overloadpacket)r'   hasattrr;   strr   rA   r   r   r   rS     s   z6min_cut_rematerialization_partition.<locals>.<setcomp>c                 S   s   h | ]}t |qS r   )r   r   rf   r   r   r   rS     r   z#Ops banned from rematerialization: Fc                    sb   | h}t |dkr^| }|jD ]:}|vr< ||s< dS |vr t|v r || q qdS )Nr   TF)lenpoprJ   r   r   )r4   Z	cur_nodescurrX   )
is_fusibler   view_opsr   r   is_materialized_backwards  s    
zFmin_cut_rematerialization_partition.<locals>.is_materialized_backwardsc                    s    r| j dkot| v S | j dkr(dS t| vr8dS | jtjkrHdS | jjjjjfv rbdS | rndS dkr| jt	j
krdS tdd | jD }t| }|d |k S d S )Nr   FTr   c                 s   s"   | ]}t |tjrt|V  qd S r    )r   r   r   r   r   r   r   r   rY     r   zQmin_cut_rematerialization_partition.<locals>.ban_recomputation.<locals>.<genexpr>rh   )r'   r   r;   rU   rV   lift_fresh_copydefaultZ
lift_freshdist_from_bwr   Zmax_dist_from_bwr}   r+   r   )r4   Zinput_tensors_sizeZoutput_size)AGGRESSIVE_RECOMPUTATIONr   compilerr   recomputable_opsunrecomputable_opsr   r   ban_recomputation  s"    
z>min_cut_rematerialization_partition.<locals>.ban_recomputationc                    s   t |  v ot | v S r    )r   )ab)fusible_opsr   r   r     s    z7min_cut_rematerialization_partition.<locals>.is_fusiblec                    s*    j dkrdS t fdd jD  S )Nr   Tc                 3   s   | ]} |V  qd S r    r   rW   )r   r4   r   r   rY     r   zOmin_cut_rematerialization_partition.<locals>.is_materialized.<locals>.<genexpr>)r'   r_   rJ   r<   )r   r<   r   is_materialized  s    
z<min_cut_rematerialization_partition.<locals>.is_materialized)rQ   c                    s>   t | }t|dtt| jdd  } | r2|S |d S d S )Ng?d   r	   ri   )r   rp   maxminr   )r4   Zmem_sz)r   r   r   get_node_weight  s
    z<min_cut_rematerialization_partition.<locals>.get_node_weightr#   Z_inZsink)capacityr   Zprimalssourcerz   rT   Z_outc                 3   s   | ]}| | fV  qd S r    r   rZ   )nx_graphr   r   rY     r   z6min_cut_rematerialization_partition.<locals>.<genexpr>c                 3   s   | ]}| v r|fV  qd S r    r   )r   v)non_reachableur   r   rY     r   c                 S   s   i | ]\}}||qS r   r   )r   idxr4   r   r   r   
<dictcomp>  r   z7min_cut_rematerialization_partition.<locals>.<dictcomp>c                 3   s   | ]} | V  qd S r    r   rA   r   r   r   rY     r   c                    s    |  S r    r   r!   )node_idxr   r   r"     r   z5min_cut_rematerialization_partition.<locals>.<lambda>)r   c                 S   s   t | S r    r]   r[   r   r   r   r"     r   c                 S   s
   t |  S r    r]   r   r   r   r   r"     r   r^   z Theoretical Activations Stored: c                 S   s   g | ]}t |qS r   )r   r   r   r   r   r     r   z7min_cut_rematerialization_partition.<locals>.<listcomp>c                 S   s   h | ]}|j d kr|jqS r   rR   rA   r   r   r   rS     r   c                 S   s   h | ]}|j d kr|jqS r   rR   rA   r   r   r   rS     r   r   z# remat/fw/bw: /zCount of Ops Rematerialized: c                 S   s   | d S rd   r   r!   r   r   r   r"     r   Tr   )ZnetworkxImportErrorr.   rB   r0   Z	recompiler   Zcser
   r&   r$   r   rc   reversedr   rp   rJ   r   rk   r   r   primsr   subdivatan2mulr   pow	remainderfmod__and____or____xor__
__lshift__
__rshift__eqnegegtleltabsZbitwise_notceilfloorfracnegZreluroundZsilutruncloglog10log1plog2lgammaexpexpm1erferfccosacoscoshsinasinsinhtanatantanhatanhsqrtZrsqrtZ
reciprocalZsigmoidZsoftplus	thresholdZthreshold_backwardclampwhereZlerpZaddcmulZgeluZgelu_backwardr}   meanZ_grad_sum_to_sizeZsum_to_sizeZamaxtoZtype_asrU   rV   ZsqueezeZ	unsqueezeZrsubZ_to_copyaliasZconvert_element_typecloneZ	full_likevarZstdZbroadcast_in_dimselectZpermuteZ_unsafe_viewviewexpandsliceZreshapeZbroadcast_tensorsZscalar_tensorZonesZ	new_zerosr   ZarangeZtriuZvar_meanisinfr-   fullZ
as_stridedzerosZargmaxmaximumtindexr   r`   Znative_dropoutZ	rand_likeZ
randn_likemmZconvolutionZconvolution_backwardZbmmZaddmmZupsample_bilinear2dZ_softmaxZ_softmax_backward_dataZnative_layer_normZnative_layer_norm_backwardZnative_batch_normZnative_batch_norm_backwardZ_native_batch_norm_legitAOT_PARTITIONER_DEBUGr   ZDiGraphr'   Zadd_edgemathinfr;   r%   r   r{   r   Zminimum_cutupdate	enumerater   rH   rI   rP   r   r   r   r   r   ),r?   ra   r   r   rC   ZnxeZfx_gZ	cse_graphZfull_bw_graphr4   r   Zorig_fw_outputsr   r   r   rX   r   Zdefault_recomputable_opsZ
random_opsZcompute_intensive_opsZjoint_module_opsZops_ignoredr   r   Zis_non_tensor_nodeZweightZ	cut_value	partitionZ	reachableZcutsetZnbrsZ	cut_nodesZnode_inZnode_outZ	node_namerM   rN   Z	fw_moduleZ	bw_moduleZfw_module_nodesZbw_module_nodesZremat_nodescountsr   )r   r   r   r   r   r   r   r   r   r   rC   r   r   r   r   r   r   r   #min_cut_rematerialization_partition  s    


 1
$
8
!


&"
&r  fx_graphT)tracedfnamefignamec           
      C   s   |r0t | j}t| |} | jjD ]
}i |_q$tj	|\}}|sHd}t
d| |  t| |}| }	t|	d|d | |  d S )Nz.svgzWriting FX graph to file: Zwrite_.)copydeepcopyrB   r   rL   r&   r%   ospathsplitextr   r   ZFxGraphDrawerZget_main_dot_graphr   lstrip)
r  r  r  Z
clear_metar3   r4   baseextgr   r   r   r   
draw_graph  s    r"  full_graph.pngc                 C   s   t | | t| |S r    )r"  rc   )rB   Zjoint_inputs	file_namer   r   r   draw_joint_graph)  s    
r%  )r   )r   N)r  T)r#  )3Z"torch.fx.experimental.proxy_tensorr   r   Z%torch.fx.experimental.symbolic_shapesr   rk   Ztorch.fxr   rU   r  Ztorch.utils._pytreeutilsZ_pytreer)   r  r  r   r   Ztorch.fx.passesr   typingr   Zcompile_utilsr
   r    r   	functoolsZdebug_partitionerr  r   r(   r7   r=   r>   rL   rF   rP   rc   rg   ry   r   rp   r   r   	lru_cacher   r  r   r"  r%  r   r   r   r   <module>   sP   4!F	
   	