o
    H&i=,                     @   s"  d dl Z d dlmZmZ d dlmZmZmZmZ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
ejjfdejjdee dede	ejj de
ejjeejjeeef f f f
ddZdS )    N)	dataclassfield)DictListOptionalTupleTypeUnion)compatibility)map_arg)HolderModulelift_subgraph_as_module   )NodeList)getattr_recursivesetattr_recursive	Componentsplit_by_tagsF)Zis_backward_compatiblec                 C   s.   | dD ]}t| |rt| |} q d S | S )N.)splithasattrgetattr)objnamelayer r   FC:\wamp64\www\opt\env\Lib\site-packages\torch/fx/passes/split_utils.pyr      s
   
r   c                 C   sJ   d|vrt | || d S |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%   r&   dictr'   r   Noder(   r)   r   GraphModuler   r   r   r   r   "   s   
 "r   r)   tagsreturn_fqn_mappingGraphModuleClsreturnc                    s<  dt jjjdtfdd}i i i }g }i t j }i }d}	|D ]}
tt j t||
  |   ||
< q!| j	j
D ]}|jdkrO|	durLtd|}	q=|jdkri|j|j|jd	||< t|j|| _q=|jd
kroq=t|dsvJ fdd||j||j D }||j   |< tdd |D dd} j|ksJ  fdd} j	||}|j|_||<  |< q=|	du rtd||	jd D ]}|jd
kr|j|j|jd	||< qd|< qΈD ]}|jdkr| j| qi }|D ]b ttj j} j	t|dkr|d n| t|  j	 jd\ _ }|!| |j" jtt|j j#dd}t|dkrH|| jd < qt$ jD ]\}}t j%|| j||< qMq|t&|	jd |j t'dd |D }||	jd D ]}|jd
krt(||jt)| |j* q{|||}|r||fS |S )a1  
    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):
            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.
    xr;   c                 S   s   g }t | |j |S )zC
        Stores nodes in x to a list and returns the list.
        )r   append)r<   rr   r   r   flatten|   s   zsplit_by_tags.<locals>.flattenNoutputzMultiple output nodes in graph!placeholderZ	type_exprget_attrtagc                    s   g | ]}|j d vr | qS )>   rC   rA   )op).0r<   )node_to_componentr   r   
<listcomp>   s
    
z!split_by_tags.<locals>.<listcomp>c                 s   s    | ]}|j V  qd S )N)r"   )rF   cr   r   r   	<genexpr>   s    z split_by_tags.<locals>.<genexpr>r   )defaultc                    s   | j dkr|  jvr jj| j| jd j| <  j|  S | j dkr+|   kr+|  S |  jvrQ j|   jj| j	| jd}t

| j|_ j| d | <  j j|  S )NrC   rB   rA   )rE   r'   r!   rC   targettyper%   r=   rA   r   copymetar$   index)r<   rA   compZnode_remappingrG   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)   )rF   rR   r   r   r   
<dictcomp>  s    z!split_by_tags.<locals>.<dictcomp>)+r.   r/   nodeZArgumentr   r0   r   lenr=   r!   nodesrE   RuntimeErrorrA   r   rM   rN   rO   r   rT   rU   rD   maxr"   Z	node_copyrC   r&   tuplemap__getitem__r@   r   r)   updateZcall_moduler%   	enumerateZProxyr   r   r   r   rL   )r)   r8   r9   r:   r?   Ztag_to_componentZall_componentsZmain_gZmain_remappingZoutput_noderD   rW   Zupstream_componentsZmxrS   nr<   Zorig_to_split_fqn_mappingZoutsZcomp_orig_to_split_fqn_mappingZ	main_nodeioZ	main_rootZ	result_gmr   rQ   r   r   <   s   @	











"


r   )rN   dataclassesr   r   typingr   r   r   r   r   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/   r7   r3   boolr   r   r   r   r   <module>   s<     
	

"