a
    h,                     @   s  d dl 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mZ ddlmZ g d	Ze
d
ddd Ze
d
ddd Ze
d
deG dd dZe
d
dd
d
ejjfejjee eeeejj eejjeejjeeef f f dddZdS )    N)	dataclassfield)OptionalUnion)compatibility)map_arg)HolderModulelift_subgraph_as_module   )NodeList)getattr_recursivesetattr_recursive	Componentsplit_by_tagsF)Zis_backward_compatiblec                 C   s0   | dD ] }t| |r$t| |} q
 d S q
| S )N.)splithasattrgetattr)objnamelayer r   I/var/www/auris/lib/python3.9/site-packages/torch/fx/passes/split_utils.pyr      s
    
r   c                 C   sH   d|vrt | || n.|d}tt| |d d|dd  | d S )Nr   r   r
   )setattrr   r   r   join)r   attrvaluer   r   r   r   r      s    
r   c                   @   s   e Zd ZU dZejjed< eed< e	ed< e
edZeed< e
edZeed< e
edZeed< e
edZeejjejjf ed	< e
edZee	 ed
< dZeejj ed< dS )r   zX
    A component serves as a container for a subgraph we want to create afterwards.
    graphorderr   )default_factoryinput_placeholdersorig_inputsorig_outputsgetattr_mapsconstructor_argsNgm)__name__
__module____qualname____doc__torchfxGraph__annotations__intstrr   listr    r!   r"   dictr#   Noder$   r%   r   GraphModuler   r   r   r   r   $   s   
"r   )r%   tagsreturn_fqn_mappingreturn_tupleGraphModuleClsreturnc                    s  t jjjtddd}i i i }g }i t j }i }	d}
|D ].}tt j t||  |   ||< q@| j	j
D ],}|jdkr|
durtd|}
qx|jdkr|j|j|jd|	|< t|j|	| _qx|jd	krqxt|d
sJ d|  fdd||j||j D }||j   |< tdd |D dd} j|ksnJ d j d j d|  fdd} j	||}|j|_||<  |< qx|
du rtd||
jd D ]2}|jd	kr|j|j|jd|	|< nd|< qȈD ]"}|jdkr | j| q i }|D ] ttj j}|rV j	| n" j	t|dkrr|d n| t |  j	 jd\ _!}|"| |j# jtt|	j j$dd}t|dkr|s||	 jd < n,t% jD ] \}}t j&|| j|	|< qq,|t'|
jd |	j t(dd |D }| j	j)|_)||
jd D ](}|jd	krPt*||jt+| |j, qP|||}|r||fS |S )a9  
    Splits a GraphModule using tags on its graph nodes. We honor the order of
    tags. For example, we have tags = ["a", "b", "c"], the function will create
    the initial submodules in the order of "a", "b", "c".

    To set a tag:
    gm.graph.nodes[idx].tag = "mytag"

    This will result in all nodes with the same tag being extracted and placed in their
    own submodule. For placeholder, output and get_attr node, the tag is ignored. placeholder
    and output nodes are created when needed while get_attr nodes get copied to submodules
    where they are used.

    Given the following module def:

    class SimpleModule(torch.nn.Module):
        def __init__(self) -> None:
            super().__init__()
            self.linear1 = torch.nn.Linear(...)
            self.linear2 = torch.nn.Linear(...)
            self.linear3 = torch.nn.Linear(...)

        def forward(self, in1, in2):
            r1 = self.linear1(in1)
            r2 = self.linear2(in2)
            r3 = torch.cat([r1, r2])
            return self.linear3(r3)

    Marking the node corresponding to in1 with the tag sc.REQUEST_ONLY.lower() results in the following split:

    ro:
    def forward(self, in1):
        self = self.root
        linear1 = self.linear1(in1)
        return linear1

    main:
    def forward(self, in2, linear1):
        self = self.root
        linear2 = self.linear2(in2)
        cat_1 = torch.cat([linear1, linear2])
        linear3 = self.linear3(cat_1)
        return linear3

    main:
    def forward(self, in1, in2):
        self = self.root
        ro_0 = self.ro_0(in1)
        main_1 = self.main_1(in2, ro_0)
        return main_1

    Returns:
        split_gm: torch fx graph after split
        orig_to_split_fqn_mapping: a map between the original fqn and the fqn
            after split for call_module and get_attr.
    )xr8   c                 S   s   g }t | |j |S )zC
        Stores nodes in x to a list and returns the list.
        )r   append)r9   rr   r   r   flatten   s    zsplit_by_tags.<locals>.flattenNoutputzMultiple output nodes in graph!placeholderZ	type_exprget_attrtagzNode does not have tag: c                    s   g | ]}|j d vr | qS )>   r@   r>   )op).0r9   )node_to_componentr   r   
<listcomp>   s   
z!split_by_tags.<locals>.<listcomp>c                 s   s   | ]}|j V  qd S )N)r   )rC   cr   r   r   	<genexpr>       z split_by_tags.<locals>.<genexpr>r   )defaultz
Component z8 order must be >= max of its upstream components, order=z	 and max=c                    s   | j dkrL|  jvrB jj| j| jd j| < t| j j|  _ j|  S | j dkrj|   krj|  S |  jvr j	|   jj
| j| jd}t| j|_ j	| d | <  j j|  S )Nr@   r?   r>   )rB   r#   r   r@   targettypecopymetar!   r:   r>   r   r    index)r9   r>   compZnode_remappingrD   Zused_in_mainr   r   
remap_func   s     



z!split_by_tags.<locals>.remap_funczGraph had no output node!r
   )ZsubgraphZ	comp_name)argskwargsc                 S   s   i | ]}|j |jqS r   )r   r%   )rC   rP   r   r   r   
<dictcomp>&  rH   z!split_by_tags.<locals>.<dictcomp>)-r*   r+   nodeZArgumentr   r,   r   lenr:   r   nodesrB   RuntimeErrorr>   r   rK   rL   rM   r   Zformat_noderR   rS   rA   maxr   Z	node_copyr@   r"   tuplemap__getitem__r=   r	   r%   updateZcall_moduler!   	enumerateZProxyr   r   Z_codegenr   r   rJ   )r%   r4   r5   r6   r7   r<   Ztag_to_componentZall_componentsZmain_gZmain_remappingZoutput_noderA   rU   Zupstream_componentsZmxrQ   nr9   Zorig_to_split_fqn_mappingZoutsZcomp_orig_to_split_fqn_mappingZ	main_nodeioZ	main_rootZ	result_gmr   rO   r   r   >   s    A	









"



r   )rL   Zdataclassesr   r   typingr   r   Ztorch.fxr*   Ztorch.fx._compatibilityr   Ztorch.fx.graphr   Ztorch.fx.passes.utilsr   r	   Ztools_commonr   __all__r   r   r   r+   r3   r0   r/   boolrK   rZ   r1   r   r   r   r   r   <module>   s6   
	

"