U
    zhC                     @   s"  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mZ d dl	m
Z
m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mZ e ZeG d
d dZG dd dejjZdd Zdd Zdd Zdd Z dd Z!eG dd dZ"e fddddddej#e
dddZ$dS )    N)	dataclass)partialwraps)CallableList)tqdm)StorageWeakRef)ContentStoreWriter   )get_outputsget_placeholdersc                   @   s:   e Zd ZU ee ed< ee ed< ejed< ejed< dS )LoadTensorMetasizestridedtypedeviceN)	__name__
__module____qualname__r   int__annotations__torchr   r    r   r   N/var/www/html/venv/lib/python3.8/site-packages/torch/_functorch/fx_minifier.pyr      s   

r   c                       s<   e Zd Zddd fdd
Z fddZ fdd	Z  ZS )
ConcretePropNFwriterskip_offloadc                   s$   t  | || _|| _t | _d S N)super__init__r   r   setseen_storages)selfmodr   r   	__class__r   r   r       s    zConcreteProp.__init__c                    s   | j d t |}|j}t|tjr| jd kr@||j	d< qt
| | jkr^d |j	d< q| js|| jtjd|| t| | |j|j|j	d< | jt
|  n
t|j	d< |S )Nr
   concrete_valueeager)pbarupdater   run_nodename
isinstancer   Tensorr   metar   Zuntyped_storager"   r   Zwrite_tensorospathjoinr   r   r   r   r   addis_tuple)r#   nrr,   r%   r   r   r+   $   s&    
   

zConcreteProp.run_nodec              
      s\   t dt| jjj| jd kd4}|| _t j| }| j	sB|
d |W  5 Q R  S Q R X d S )Nz(Saving intermediates for delta debugging)desctotaldisablezESaved!  To skip next time, run with --skip-saving-eager-intermediates)r   lenmodulegraphnodesr   r)   r   runr   set_description)r#   argsr)   r6   r%   r   r   	propagate=   s    zConcreteProp.propagate)r   r   r   r    r+   rA   __classcell__r   r   r%   r   r      s   r   c                 C   s   | j dko| jtjjjjkS )Ncall_function)optargetr   ops
debugprimsload_tensordefault)noder   r   r   is_load_tensor_nodeL   s    
rK   c                 C   s   |j dks|j dkrdS t|r$dS |jdd }t|tjrfd|_ |j|_d|_	i |_
|| dS |d krrdS |tkrd}t|jD ]}t| ||p|}q|S t|trd|_ tjjjj|_tjd|j|j|jf|_	|j|jd	|_
dS dS )
NoutputplaceholderFr'   r   TrC   r(   )r   r   )rD   rK   r/   getr-   r   r.   r,   rE   r@   kwargsappendr4   listusers_convert_node_to_placeholderr   rF   rG   rH   rI   r0   r1   r2   r   r   r   r   )r<   rJ   inpsZconcrete_valr6   Z
tuple_userr   r   r   rS   T   s>    

rS   c                 C   s8   t   d}t j|dd ddlm} || || dS )z
    Takes minified FX graph as primary input, and ports it to HLO via StableHLO
    Provides minified HLO graph as output, and archive them to local directory
    z
/hlo_filesT)Z	exists_okr   )save_torch_model_as_stablehloN)r0   getcwdmakedirsZtorch_xla.stablehlorU   )Zminified_fx_graphinputsZhlo_dirrU   r   r   r   create_minified_hlo_graph   s    rY   c                 C   s4   t dt| jj ddd |D  d| j d d S )Nz
# Working Repro with z nodes
inps = c                 S   s   g | ]}|j |j|jjfqS r   )shaper   r   type).0ir   r   r   
<listcomp>   s     zdump_state.<locals>.<listcomp>zo
inps = [torch.zeros(())] + [torch.ones(shape, dtype=dtype, device=device) for (shape, dtype, device) in inps]

)printr:   r<   r=   code)Zfx_grT   r   r   r   
dump_state   s    
rb   c                 C   s   | dkrdS | | d @ dkS )Nr   Fr
   r   )r5   r   r   r   is_power_of_two   s    rc   c                   @   s.   e Zd ZU ejed< eej ed< dd Z	dS )
ReproStater<   rT   c                 C   s$   t | j}t|t| jks td S r   )r   r<   r:   rT   AssertionError)r#   ph_nodesr   r   r   __post_init__   s    
zReproState.__post_init__N)
r   r   r   fxGraphr   r   r   r.   rg   r   r   r   r   rd      s   

rd   F)save_diroffload_to_diskr   skip_sanitymax_granularity)fail_frb   c                   s  t |ttfstj}	t|	j}
|dk	rBt|sBtd| dd	fdd	fddd}|rrt	|}t
||d	j|  |s|	|std
td|
 dtjd ttdfddtdfdd}|dfdd|dfdd
tdddtdfddfdd }|d!||d"fd#d$d%d&  |d'tjd( fd)d*|d+ fd,d-t|	|}
fd.d/}|t|j|j td0ttt|jj }|dk	rt||}|||d1d2}|dk	r|}q|d0 }d3}|d4kr`|||d3d2}|dk	rT|}d1}q`|d0 }q&|rjq
|d4}|dk	r|}qqq|j|jstd5td6	 d7tjd t|j}d8tjkrt||j |||j td9tjd ||jfS ):aF  
    Minimizes a FX graph with given inputs, such that the resulting FX graph still returns True for module_fails.

    Does 2 main strategies:
    1. Truncates suffix: Removes some suffix from the graph and sets a new output.
    2. Delta Debugging: Tries replacing half of the graph with inputs. If fails,
        tries replacing quarter of the graph, etc.

    >>> # xdoctest: +SKIP(failing)
    >>> failing_function = fx.symbolic_trace(f)
    >>> minimize(failing_function, [torch.randn(5)], lambda fx_g, inps: fx_g(*inps))

    note: module_fails returns True if it fails.
    Nzmax_granularity z not power of twor   c                    s   t  t| jS r   )rh   GraphModulecopydeepcopyr<   )Zfx_graph)rn   r   r   deepcopy_fx_graph   s    z#minifier.<locals>.deepcopy_fx_graphc                    s2   t | } d7 t | }|j  ||S )Nr
   )rp   rq   rh   ro   r<   Zlint)r<   rT   r$   )rn   module_failsnum_queriesr   r   graph_fails   s
    

zminifier.<locals>.graph_failsr   z#Input graph did not fail the testerzStarted off with  nodesfile)strategyr,   c                    s&   t dtd fdd}|S )Nr
   )	old_statec           
   
      sx  t tjd t d d| dt| jj dt| j d	tjd  | jt| j|}|d k	r`t|jj}t| jj}t|j}t| j}tt|j}tt| j}d}	||k rd}	t d	| d
| dtjd ||krd}	t d	| d
| dtjd ||k r,d}	t d	| d
| dtjd |	s:t	d|j|js\t dtjd d S |S t d tjd d S )Nrw   z
Strategy: z (G: z) (z nodes, z inputs)FTzSUCCESS: Went from z to rv   z inputsz outputsz$Success raised but no progress made?z=WARNING: Something went wrong, not applying this minificationzFAIL: )
r`   sysstderrr:   r<   r=   rT   rQ   r   RuntimeError)
rz   granularity	new_stateZ	new_nodesZ	old_nodesnew_inpsZold_inpsZnew_outsZold_outsZprogress_made)rr   ru   r,   ry   r   r   new_func   s^    *  




z6minifier.<locals>._register_strategy.<locals>.new_func)r
   )r   rd   )ry   r,   r   )rr   ru   )r,   ry   r   _register_strategy   s    3z$minifier.<locals>._register_strategyr,   c                    s   t  | dS )Nr   )r   r   )r   r   r   register_strategy  s    z#minifier.<locals>.register_strategyzTruncate suffixc           	         s   t  }t }i  t| jD ]\}}|| fdd}|jdkr|| dkr||d  dkr||kr||f}t|jt| jk r||rt	||  S |
| || | |< qd S )Nc                    s    |  S r   r   xenvr   r   <lambda>$      z1minifier.<locals>.remove_suffix.<locals>.<lambda>)rM   rL   r      )r!   rh   ri   	enumerater=   	node_copyrD   rL   r:   rd   r3   
erase_node)		cur_graphcur_inpsr~   Ztested	new_graphidxrJ   new_nodeZoutput_noderu   r   r   remove_suffix  s,    

 


zminifier.<locals>.remove_suffixzRemove outputsc                    s   t d|d }t| jD ] \}}||_|jdkr|} q:qt|jd tjrPd S t	|jd dd d}t
|dkrvd S tdt
||D ]<}|d | ||| d   f|_ | |rt| |  S qd S )Nr
   r   rL   r   c                 S   s   t | tjr| jS tdS )Ng    eA)r-   rh   Noder   r   r   r   r   r   r   D  r   z2minifier.<locals>.remove_outputs.<locals>.<lambda>)key)maxr   r=   r   rD   r-   r@   rh   r   sortedr:   rangerd   )r   r   r~   r   rJ   rL   Zoutput_argsr   r   r   remove_outputs7  s&    
  
z minifier.<locals>.remove_outputs)	cur_statec                 S   s   | j }| j}t|}t|t|ks(tg }tt|D ]4}t|| jdkr^|||  q8|||  q8t|t|k rt	||S d S )Nr   )
r<   rT   r   r:   re   r   rR   r   rP   rd   )r   r   r   rf   r   r   r   r   r   remove_unused_inputs_uncheckedO  s    
z0minifier.<locals>.remove_unused_inputs_uncheckedc                    s&   | }|d k	r" |j |jr"|S d S r   )r<   rT   )r   r   )ru   r   r   r   remove_unused_inputs_checked_  s    z.minifier.<locals>.remove_unused_inputs_checkedc                    s    t | |S r   )rd   r   r   r~   )r   r   r   _remove_unused_wrappere  s    z(minifier.<locals>._remove_unused_wrapperzRemove unused inputszEliminate dead codec                    s    |   r | |rt| |S d S r   )eliminate_dead_coderd   r   r   r   r   r   l  s    
z%minifier.<locals>.eliminate_dead_codec                    s   t  }i  d}| jD ]n}|jdkrB|| fdd}| |< q|st|r||j}| |< |t	j
jjj|j|j qd}q| jD ](}| kr|| fdd}| |< q|S )NFrM   c                    s    |  S r   r   r   r   r   r   r   |  r   z=minifier.<locals>._consolidate_placeholders.<locals>.<lambda>Tc                    s    |  S r   r   r   r   r   r   r     r   )rh   ri   r=   rD   r   rK   rM   r,   rP   r   rF   rG   rH   rI   r@   rO   )r   rT   r   Zseen_non_placeholderrJ   r   r   r   r   _consolidate_placeholdersr  s&    




z+minifier.<locals>._consolidate_placeholderszDelta Debugging)r   c                    s   t | j}td||D ]}d}| }|d d  }t||| }t||D ]"}	t|j|	 }
t||
|rJd}qJ|stq|   ||}t||}|d krt||}|j|j	rt|j|j	  S qd S )Nr   FT)
r:   r=   r   minrQ   rS   r   rd   r<   rT   )r   r   r~   	num_nodesZstart_rangeZis_removingr   r   Z	end_ranger   r   r   )r   rr   ru   r   r   r   delta_debugging  s(    


z!minifier.<locals>.delta_debuggingzConsolidate Inputsc                    s6   t |} | |} t ||kr2| |r2t| |S d S r   )r:   rd   )r   r   r~   Zold_len)r   ru   r   r   consolidate_inputs  s
    

z$minifier.<locals>.consolidate_inputsc                    s   t d| tjd g }t| jj}tt| j}||d krH|g7 }|rZ| g7 }|g7 }|D ]}|| |}|d k	rj|  S qjd S )NzTrying granularity rw   r   )r`   r{   r|   r:   r<   r=   r   )failing_stater~   use_non_granularZ
strategiesr   Znum_outputsry   r   )r   r   r   r   r   remove_unused_inputsr   r   try_granularity  s$    


z!minifier.<locals>.try_granularityr   T)r   Fr
   z9Uh oh, something went wrong :( Final graph is not failingzMade z queriesZXLA_HLO_DEBUGz#Wrote minimal repro out to repro.py)r-   tuplerQ   re   r<   r:   r=   rc   r}   r	   r   rA   r`   r{   r|   r   strrd   rh   ri   ro   rT   r   mathfloorlog2r   r0   environrY   )rn   rT   rs   rb   rj   rk   r   rl   rm   Zfailing_graphZcur_sizer   r   r   r   r   r~   r   Zhas_progressZ
failing_fxr   )r   r   r   rr   r   r   rn   ru   rs   rt   r   r   r   r   r   r   minifier   s    
7
 



  


r   )%rp   r   r0   r{   dataclassesr   	functoolsr   r   typingr   r   r   Ztorch.fxrh   Z	torch.hubr   Z torch.multiprocessing.reductionsr   Ztorch.utils._content_storer	   Zcompile_utilsr   r   objectr4   r   ZInterpreterr   rK   rS   rY   rb   rc   rd   ro   r   r   r   r   r   <module>   sD   /0