o
    Zhf                     @   s
  d dl Z d dlZd dlmZ d dl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 d dlmZ dd	gZee ZZe
d
dG dd dZdejjdedefddZe
d
d			ddedejjdeegef deeeef  dee dee fdd	ZdS )    N)OrderedDict)AnyCallableOptional)compatibility)lazy_format_graph_code)GraphModule)Node	Partitionsplit_moduleT)Zis_backward_compatiblec                   @   s(   e Zd ZdefddZdefddZdS )r
   namec                 C   sN   || _ d| | _g | _i | _i | _i | _i | _tjj	
 | _	i | _i | _d S )NZsubmod_)r   submod_name
node_namesinputsoutputsdependencies
dependentstorchfxgraphGraphenvironmenttargets)selfr    r   K/var/www/auris/lib/python3.10/site-packages/torch/fx/passes/split_module.py__init__   s   
zPartition.__init__returnc                 C   s4   d| j  d| j d| j d| j d| j d| j S )Nzname: z
,
 nodes: z,
 inputs: z,
 outputs: z,
 partitions depended on: z,
 partition dependents: )r   r   r   r   r   r   )r   r   r   r   __repr__    s   
zPartition.__repr__N)__name__
__module____qualname__strr   r   r   r   r   r   r
      s    modqualnamer   c                 C   s<   | }| dD ]}t||std| dt||}q|S )N.zNode target z not found!)splithasattrAttributeErrorgetattr)r#   r$   attr_valZatomr   r   r   _get_attr_from_qualname+   s   
r+   Fmroot_msplit_callbackqualname_mapkeep_original_orderkeep_original_node_namec           8   
      sj
  t dtddd dtdtttf dtttjjj	f ffdd	}d
dl
}i 
i i dtdtt f
fdd
fdd}tjjtjjtjjg}	t }
t }i }d}t }jjD ]ԉjd }durt|tjtjfrt|jj }|jr|vr|jj< jdv rq`| jdkrj|	v rjtjjkrtj dksJ tj d
 t!sJ }th|
|< nRjtjjkrt"dd j D sJ |# th|< d|< n,jtjjkrtj dksJ |j d
  # |$j d
  |j d
 < |dur%|
| # |D ]}|| # q'q`t"dd |% D sEJ ddd |& D }dd |
& D }
t'(t)j*rjt'd| t'd|
 t!|prt!|
}d}jjD ]aj+< jd v rqyjd!krtjj,j d
 fd"d# qy|r}||ksJ d$| d%| |}j|	vrtjj,j fd&d# tjj,j-fd'd# qyt.
/ }g }
& D ]\}	t	j0s|1| qg }|r%|2 }|1| 
| j3D ]}
| j02| 
| j0s |1| q|st|t
kr2t4d(||
fD ]R}|& D ]J\}t|d
ksIJ 
t|d
  j5< |dd D ]*}
t| 		jj6jjt7d)d j D i j8d*}j9 |_|	j5< qZq<q6|D ]p}
| 	i }	j:D ]`} |  }!|!jd+krt|!jtsJ t;|!j}"t|"tj<j=rǈ	j>|!j}#|"	j?|!j< n	jj@| |  j8d,}#d|| < n	jj@| |  j8d,}#d|| < |  j9 |#_|#	j5|  < q|	_:qjjD ]tAd-r
jB 		j5tjj,j fd.d#}$tjj,j-fd/d#}%jd0vr4j}&n$t;j}'jCd1d2}&|'	j?|&< |durX	jD d1|& }(j||(< t|$t7s`J t|%tshJ rnj+nd})	jj6j|&|$|%j8|)d3}j9 |_|	j5< q |fD ]M}tE|D ]E| }t|d
ksJ |dd D ].}
t| 	| }*|*dusJ d4	jj6|*j|*j	j5 fi |*j8d*}|*j9 |_qqqi i  tjjF i }+|sjjD ]| |+\ }+qnjjD ]j+< q |s|n|},t }-d5d6 jjD |,D ]}
| 	t7	fd7d	jGD }.t|.}/|/dkrC	jH|.d
  n|/dkrO	jH|. n	jHd8 |rfd9d6	j:D }0D ]|-v rnqe| |+\ }1|-# qe|0D ]|-v rq| |+\ }+|-# qtjj		j?	j|+	jD< I	jDt7 fd:d	j:D }2t	jG}3|3dkrtjjJK|2}4tL	jGD ]\}5}6|4|5 j |6< qːq|3dkr|2 tMtN	jG< q|r  s jjD ]| |+\ }+qjjD ]jd!krHtjj,j d
  fd;d# qtjj	|+}7t dtd<|7dd |7S )=a  
    Creates subgraphs out of main graph

    Args:
        m (GraphModule): Graph module to split
        root_m (torch.nn.Module): root nn module. Not currently used. Included
            because the root nn module is usually transformed via
            torch.fx._symbolic_trace.symbolic_trace (see example below)
        split_callback (Callable[[Node], int]): Callable function
            that maps a given Node instance to a numeric partition identifier.
            split_module will use this function as the policy for which operations
            appear in which partitions in the output Module.
        qualname_map: Optional[Dict[str, str]]: optional output parameter that returns a
            mapping from new target names in the module after split to old target
            names in the original module.
        keep_original_order: Optional[bool]: keep the original order of the GraphModule
            or use the Topological order of the new constructed GraphModule


    Returns:
        GraphModule: the module after split.

    Example:

        This is a sample setup:

            import torch
            from torch.fx.symbolic_trace import symbolic_trace
            from torch.fx.graph_module import GraphModule
            from torch.fx.node import Node
            from torch.fx.passes.split_module import split_module

            class MyModule(torch.nn.Module):
                def __init__(self) -> None:
                    super().__init__()
                    self.param = torch.nn.Parameter(torch.rand(3, 4))
                    self.linear = torch.nn.Linear(4, 5)

                def forward(self, x, y):
                    z = self.linear(x + self.param).clamp(min=0.0, max=1.0)
                    w = self.linear(y).clamp(min=0.0, max=1.0)
                    return z + w

            # symbolically trace model
            my_module = MyModule()
            my_module_traced = symbolic_trace(my_module)

            # random mod partitioning
            partition_counter = 0
            NPARTITIONS = 3

            def mod_partition(node: Node):
                global partition_counter
                partition = partition_counter % NPARTITIONS
                partition_counter = (partition_counter + 1) % NPARTITIONS
                return partition

            # split module in module with submodules
            module_with_submodules = split_module(
                my_module_traced, my_module, mod_partition
            )

        Output looks like this. Original graph is broken into partitions

            > print(module_with_submodules)
            GraphModule(
                (submod_0): GraphModule(
                    (linear): Linear(in_features=4, out_features=5, bias=True)
                )
                (submod_1): GraphModule(
                    (linear): Linear(in_features=4, out_features=5, bias=True)
                )
                (submod_2): GraphModule()
            )

            def forward(self, x, y):
                param = self.param
                submod_0 = self.submod_0(x, param, y);  x = param = y = None
                getitem = submod_0[0]
                getitem_1 = submod_0[1];  submod_0 = None
                submod_1 = self.submod_1(getitem, getitem_1);  getitem = getitem_1 = None
                getitem_2 = submod_1[0]
                getitem_3 = submod_1[1];  submod_1 = None
                submod_2 = self.submod_2(getitem_2, getitem_3);  getitem_2 = getitem_3 = None
                return submod_2

        Output of split module is the same as output of input traced module.
        This is an example within a test setting:

            > orig_out = my_module_traced(x, y)
            > submodules_out = module_with_submodules(x, y)
            > self.assertEqual(orig_out, submodules_out)
            True
    z%szpre split_moduleT)Zcolorednodebase_mod_envbase_mod_attrsc                    s   | j dkrKt| jdkr| jd ntjj}r1|tjju rdn|f} jd| j|| jd|| j< n j	| j
| j|d|| j< | j || j _||fS | j dkru | j
|| j< | j || j _t| j
tsjJ t| j
}||| j
< ||fS )Nplaceholderr   r   )args	type_expr)r7   default_valueget_attr)oplenr6   inspect	Signatureemptycreate_noder   typer5   targetmetacopyr9   
isinstancer"   r+   )r2   r3   r4   r8   r6   r*   )base_mod_graphr1   r,   r   r   construct_graph   s4   


z%split_module.<locals>.construct_graphr   Ndef_nodeuse_nodec                    sF  ddl m} t| dd }t|dd }td| j||d ur|jnd| ||kr|d ur@ | }|j| j |d ur@|j| |d ur | }|j	| j | j
d }d urt||tdD ]/}| }	|j	|	j | jdkrt|	dd }
|
d ur |
 }|j|	j |j| qa|d ur|j| d S d S d S d S )	Nr   )free_symbols_fx_partitionz*record_cross_partition_use %s (%s) %s (%s)-example_value)keyr5   )Z%torch.fx.experimental.symbolic_shapesrI   r)   logdebugr   r   
setdefaultr   r   rB   getsortedr"   r:   r   )rG   rH   rI   ZdefinedusedZdef_partitionZuse_partitionZdef_valsZs_nodeZ	s_definedZs_def_partition)
partitionssymbol_to_noder   r   record_cross_partition_use   sF   	z0split_module.<locals>.record_cross_partition_usec                    sV   t | }td| j|  |}|d u rt|  |< }|j| j || _d S )Nz*instantiate_node_partition_mapping %s (%s))	r"   rN   rO   r   rQ   r
   r   appendrJ   )r2   partition_name	partition)rU   r.   r   r   "instantiate_node_partition_mapping   s   

z8split_module.<locals>.instantiate_node_partition_mappingrL   )r5   r9   outputZcall_function   c                 s   s    | ]	}t |t V  qd S N)rD   r	   .0argr   r   r   	<genexpr>@  s    zsplit_module.<locals>.<genexpr>c                 s   s    | ]}|d uV  qd S r^   r   )r`   vr   r   r   rb   P      zautocast must exitc                 S      i | ]	\}}|t |qS r   rR   r`   krc   r   r   r   
<dictcomp>R      z split_module.<locals>.<dictcomp>c                 S   re   r   rf   rg   r   r   r   ri   S  rj   zautocast_regions: %szgrad_regions: %s)r5   r9   r\   c                    s
    | d S r^   r   n)rW   r   r   <lambda>f     
 zsplit_module.<locals>.<lambda>zRautocast or set_grad_enabled require monotonically increasing partitions:highest: z, this node's: c                    
   |  S r^   r   rG   r2   rW   r   r   rn   v  ro   c                    rp   r^   r   rq   rr   r   r   rn   y  ro   z cycle exists between partitions!c                 s   s    | ]}|V  qd S r^   r   r_   r   r   r   rb     s    )r:   rA   r6   kwargsr7   r9   )r7   rJ   c                        |  S r^   r   rl   r   r   r   rn         c                    rt   r^   r   rl   ru   r   r   rn     rv   )call_moduler9   r%   _)r:   rA   r6   rs   r7   r   zMissing exit nodec                 S   s   g | ]	}|j d kr|qS )r5   )r:   )r`   r2   r   r   r   
<listcomp>  rj   z split_module.<locals>.<listcomp>c                 3   s    | ]
}j  |  V  qd S r^   ru   r`   r   )
orig_nodesrZ   r   r   rb   "  s    
r   c                    s   g | ]
}|vr | qS r   r   )r`   rM   )orig_mod_envoriginal_orderr   r   ry   2  s
    c                 3   s    | ]} | V  qd S r^   r   rz   r3   r   r   rb   P  rd   c                    s
    | j  S r^   )r   rl   r~   r   r   rn   j  ro   zpost split_module)OrN   rO   r   r	   dictr"   r   r   Zgraph_moduler   sympyr   ampZ_enter_autocastZ_exit_autocastZ_CZ_set_grad_enabledr   setr   nodesrB   rQ   rD   ZSymIntZSymFloatr2   exprSymbolr:   rA   r;   r6   boolalladdremovevaluesitems_LOGGERisEnabledForloggingDEBUGr   Zmap_argrs   listkeysr   rX   popr   RuntimeErrorr   r?   tupler@   rC   r   r+   nnModuler9   r   r5   r'   rJ   replacer   reversedr   r   r\   rw   proxyZProxy	enumeratenextiter)8r,   r-   r.   r/   r0   r1   rF   r   r[   ZGLOBAL_STATE_NODESZgrad_regionsZautocast_regionsZautocast_exitsZactive_gradZactive_autocastsvals0aZassert_monotonically_increasingZhighest_partitionpidZoriginal_partition_orderZroot_partitionsrY   Zsorted_partitionsZroot_partitionZ	dependentZregions_mappingZregionsrnew_nodeZ
new_inputsinpZ	orig_nodeZ	orig_attrr5   Zgathered_argsZgathered_kwargsrA   Ztarget_attrr$   r   Z	exit_noder4   Zconstruct_order_partitionsZalready_constructed_attr_nodesZoutput_valsZnum_output_valsZorig_mod_attr_nodesZ_based_mod_attrsZ
output_valZnum_outputsZoutput_val_proxyiZoutput_nameretr   )r3   rE   r   r1   r,   r2   r|   r{   r}   rZ   rU   rW   r.   rV   r   r   5   s0  h
"0
		



 













	







)NFF)r<   r   collectionsr   typingr   r   r   r   Ztorch.fx._compatibilityr   Ztorch.fx._utilsr   Ztorch.fx.graph_moduler   Ztorch.fx.noder	   __all__	getLoggerr   rN   r   r
   r   r   r"   r+   intr   r   r   r   r   r   r   <module>   s>   
