o
    ei>                     @   s   d dl Z d dlmZ d dlmZmZ d dlZd dlm	Z	 d dl
mZ g dZG dd dejjZ		dd
ejjdededeejjejjf fddZdejjdedefddZ		ddeejjejjf deeejjgef  dedefddZdS )    N)Callable)OptionalUnion)map_arg)split_module)FoldedGraphModuleget_unique_attr_name_in_modulesplit_const_subgraphsc                       sf   e Zd ZdZ			ddejjdejjde	ejj de	e
 de
f
 fd	d
Z fddZdd Z  ZS )r   a  
    FoldedGraphModule is a GraphModule which also contains another
    `const_subgraph_module` representing a subgraph which has all const attr
    inputs and which can be run once before running the main standard
    `graph`. The `const_output_names` are the ordered list names of attrs which
    represent what each respective output from the const_subgraph should be set
    on which attrs.
    Ncudarootgraphconst_subgraphfx_const_folded_attrs_namedevice_for_folded_attrsc                    s@   t  || |d u rd ntj||| _d| _|| _|| _d S )NF)	super__init__torchfxGraphModuleconst_subgraph_modulehas_folding_been_runr   r   )selfr   r   r   r   r   	__class__ j/var/www/addictedbytheproject.nl/epg/venv/lib/python3.10/site-packages/torch/fx/experimental/const_fold.pyr      s   
zFoldedGraphModule.__init__c                    s   | j s|   t j| S N)r   run_foldingr   __call__)r   argskwargsr   r   r   r   .   s   zFoldedGraphModule.__call__c                    s~   j d u s
jd u rd S jrtdd_  }fdd t|tr2tj fdd|D n |}t	j| d S )NzFolding has already been runTc                    sN   t jjt| ts|   n
t | gj j	dt| t jr#| j
dS ddS )N)deviceF)requires_grad)r   nn	Parameter
isinstanceintdetachcloneTensortor   r"   )i)r   r   r   _create_paramE   s   z4FoldedGraphModule.run_folding.<locals>._create_paramc                    s   g | ]} |qS r   r   ).0r+   )r,   r   r   
<listcomp>N   s    z1FoldedGraphModule.run_folding.<locals>.<listcomp>)
r   r   r   AssertionErrorr%   tupler   r#   ParameterListsetattr)r   folded_attrsparamsr   )r,   r   r   r   3   s   


zFoldedGraphModule.run_folding)NNr
   )__name__
__module____qualname____doc__r   r#   Moduler   Graphr   strr   r   r   __classcell__r   r   r   r   r      s$    
r   Tgminline_mod_namerun_dcereturnc              	      s  t |  | }t|tjjstdt| d}| jj	D ]}|j
dkr.|j|kr.|} nq|du r:td| |j}|j}i d}fdd}	|jj	D ]}
|
j
dkrj|
j|v r_||
j n|| |
< |d	7 }qN|
j
d
kr|
jd }t||	}g }t|ttfrddl  fdd|jD }|| |D ](}|jd	 }t|tstdt| |||  | j| || |< qqN| j| | j|
|	}W d   n1 sw   Y  ||
< qN| j| |r| j  S )a  
    Given `gm` and some graph module which is called with target name `inline_mod_name`,
    this helper will inline all of the nodes from that called graph module into `gm`.

    Returns a mapping from subgraph nodes to the newly created/mapped nodes in gm.
    zExpected GraphModule, got Ncall_modulez$Could not find call_module node for r   c                    s    |  }| j  |_ |S r   )metacopy)nodenew_node)replacement_mappingr   r   replacement_fnr   s   z&_inline_module.<locals>.replacement_fnplaceholder   outputc                    s6   g | ]}|j d kr|j ju rt|jd tr|qS )call_functionrI   )optargetgetitemr%   r   r&   )r-   user)operatorr   r   r.      s    
z"_inline_module.<locals>.<listcomp>zExpected int index, got )dictnamed_modulesr%   r   r   r   r/   typer   nodesrL   rM   r   r    namer   listr0   rP   usersreplace_all_uses_withr&   
erase_nodeinserting_before	node_copyeliminate_dead_code)r=   r>   r?   
inline_modcall_mod_node_to_replacerD   call_mod_argscall_mod_kwargsph_countrG   inline_nodeoutputsoutput_replacementsgetitem_usersrO   idxrE   r   )rP   rF   r   _inline_moduleU   sd   












rg   
mod_tracedrU   c                 C   s   t dd|}|d  rd| }t| |r>t d|}|du r&|d }n|dd\}}| dt|d  }t| |s|S )	zP
    Make sure the name is unique (in a module) and can represents an attr.
    z[^0-9a-zA-Z_]+_r   z(.*)_(\d+)$N_1rI      )resubisdigithasattrmatchgroupr&   )rh   rU   rp   basenumr   r   r   r      s   



r   cpumoduleskip_folding_node_fnr   c              	      s  ddl }t| tjjstj| }n| }dtjjdtf fdd t d}|jj	D ]S}|j
dv r2q*|j
d	kr@t|js@q*|rG||rGq*| rLq*t|jd
d|jrXq*|j
dkrq||j }rqt|tjjrq |rqq*| |j
d	kr}d}q*|st||jS dtjjffdd}t|| |}	d\}
}|	jt|	|d}}|r|jj	ng D ]}|j
dkrt|	|jt||j q|jj	D ]}|j
dkrt|	|jt||j qd}|	jj	D ]}|j
dkr|j|
kr|j} nq|du rtdtj|	|j}d}|jj	D ]t}|j
dkrt|jd t}q|j
dkrq|t|kr3td| dt| d|| }|d7 }|j
d	krItd|j
 |j| |j|j}W d   n	1 sbw   Y  |j ! |_ |"| |j#| qdt$ vrtdt%|d}t|	||rtj&' ntj&(  |	jj	D ]9}|j
dkr|j|
kr|j| |j|}W d   n	1 sw   Y  |j ! |_ |"|  nqt)|	|rt*|	| |	j+  t|	|	j|j||S )aJ  
    Looks through `module` for any nodes that have all constant attribute inputs
    and separates them out into their own constant subgraph, and returns a
    FoldedGraphModule which runs that constant subgraph on the first run to set
    attributes on the module prior to running the non-constant portion of the
    graph.
    r   Nru   r@   c                    st   t | tjjstd| jjD ](}|jdkr| r dS |jdkr7| 	|j
 }r7t |tjjr7 |  S qdS )z`
        Return True if a GraphModule type subgraph contains any impure op, else False.
        zDcaller should only pass GraphModule to subgraph_has_impure_ops checkrK   TrA   F)r%   r   r   r   r/   r   rT   rL   	is_impureget_submodulerM   )ru   rD   	submodule)_subgraph_has_impure_opsr   r   rz      s   
z7split_const_subgraphs.<locals>._subgraph_has_impure_opsF>   rJ   rH   get_attr
fill_valuerA   TrD   c                    s   |  v rdS dS )Nr   rI   r   )rD   )const_nodesr   r   mod_partition  s   z,split_const_subgraphs.<locals>.mod_partition)submod_0submod_1z,Could not find call_module node for const_gmrJ   rH   zPlaceholder index z out of range for args (len=)rI   zExpected get_attr, got multiple_outputsz multiple_outputs not set in loop_FX_CONST_FOLDED_ATTRS),sympyr%   r   r   r   symbolic_traceboolsetr   rT   rL   all_input_nodesissubsetrw   r    getExprrx   rM   addr   Noder   r   getattrr2   r   r/   r0   lenrZ   r{   rB   rC   rX   rY   localsr   r#   r1   r$   ro   rg   r\   )ru   rv   r   r   rh   found_const_foldingrD   
target_modr~   splitconst_mod_namenon_const_mod_nameconst_gmnon_const_gmcall_const_gm_argsroot_const_gmph_idxr   in_noderE   r   r3   r   )rz   r}   r   r	      s   











r	   )T)Nrt   )rl   collections.abcr   typingr   r   torch.fxr   torch.fx.noder   torch.fx.passes.split_moduler   __all__r   r   r   r;   r   rQ   r   rg   r   r#   r9   r	   r   r   r   r   <module>   s<   D
Z