
    Vhw5                        d Z ddlZddlZddlZddlZddlZddlmZmZ ddl	m
Z
 ddlmZmZmZmZmZ ddlZddlZddlmZ ddlmZ  ed      Zerd	d
lmZ ej6                  j8                  Zee   Zee   Ze e!e!e"e!e!ejF                  e!e!e!e!f
   Z$ ejJ                  e&      Z'ejP                  jS                  e&d      Z*de+ddfdZ,dejZ                  de eegef   e edf   f   fdZ. G d de/      Z0 G d dejb                        Z2dedefdZ3dede e e+df   e ee   df   f   fdZ4de$fdZ5 G d d      Z6 G d d      Z7dee   d e8e   d!eeege!f   ddfd"Z9y)#a  
This module provides functionality for tracking and managing regions in computational graphs.
It supports graph optimization by identifying and grouping similar regions based on their
structure and behavior. The module implements algorithms for:

1. Tracking nodes and their relationships in the computational graph
2. Identifying identical or similar regions across the graph
3. Managing graph regions for optimization purposes
4. Supporting deduplication and other graph transformation passes

The core functionality revolves around the GraphRegionTracker class which maintains
mappings between nodes and their duplicates, enabling efficient graph analysis and
optimization operations.
    N)defaultdictdeque)fields)AnyCallableOptionalTYPE_CHECKINGTypeVar)
FakeTensor)tree_flattenT   )InstructionTranslatorBasegraph_region_expansionmsgreturnc                 0    t        j                  | g|  y N)graph_expansion_logdebug)r   argss     R/home/dcms/DCMS/lib/python3.12/site-packages/torch/_dynamo/graph_region_tracker.py	debug_logr   1   s    c)D)    x.c                     ddl m}m} g } ||       }t        |      D ]'  }|j	                  t        ||j                               ) |t        |      fS )Nr   )_ident%extract_tensor_metadata_for_cache_key)torch._inductor.codecacher   r   r   appendgetattrnametuple)r   r   r   outmetadatafields         r   &_extract_tensor_metadata_for_node_hashr'   5   sS     X
C4Q7H! 2

78UZZ012 E#Jr   c                       e Zd Zy)NodeHashExceptionN)__name__
__module____qualname__ r   r   r)   r)   B   s    r   r)   c                   0     e Zd Zd fdZdedefdZ xZS )InputPicklerr   c                 x   ddl m t        j                         }|| _        t
        |   |       t        j                  j                         | _        | j                  j                  t        t        t        j                  fdt        j                  fdt        j                   fdi       d| _        y )Nr   )r   c                      t        |       ffS r   strr   r   s    r   <lambda>z'InputPickler.__init__.<locals>.<lambda>Q   s    #a&(; r   c                      t        |       ffS r   r2   r4   s    r   r5   z'InputPickler.__init__.<locals>.<lambda>R   s    &3q6))< r   c                      t        |       ffS r   r2   r4   s    r   r5   z'InputPickler.__init__.<locals>.<lambda>S   s    6CF9*= r   T)r   r   ioBytesIO_streamsuper__init__copyregdispatch_tablecopyupdater   r'   torchSymIntSymBoolSymFloatfast)selfstreamr   	__class__s     @r   r<   zInputPickler.__init__G   s    4 %4499;""B;< =		
 	r   objc                 x   	 | j                  |       | j                  j                         | j                  j                  d       | j                  j	                  d       S # t
        t        f$ r}t        |d}~ww xY w# | j                  j                  d       | j                  j	                  d       w xY w)z<
        Pickle an object and return a byte string.
        r   N)dumpr:   getvalueseektruncate	TypeErrorAttributeErrorr)   )rF   rI   es      r   dumpszInputPickler.dumpsX   s    	%IIcN<<((* LLa LL!!!$	 >* 	+#*	+ LLa LL!!!$s#   *A# #A>2A99A>>B 8B9r   N)r*   r+   r,   r<   r   bytesrR   __classcell__)rH   s   @r   r/   r/   F   s    "% % %r   r/   argc                 Z    t        | t              r| j                  j                  d      S y )Nexample_value)
isinstanceNodemetaget)rV   s    r   _extract_tensor_argr]   f   s"    #txx||O,,r   nodec                 $   t        | j                        \  }}t        | j                  j	                         d       }t        t        | j                  j                                     }t        |      \  }}||z   }|t        d |D              fS )Nc                     | d   S )Nr   r-   )r   s    r   r5   z!_normalize_args.<locals>.<lambda>q   s
    ad r   keyc              3   2   K   | ]  }t        |        y wr   )r]   ).0rV   s     r   	<genexpr>z"_normalize_args.<locals>.<genexpr>u   s     LC237Ls   )r   r   sortedkwargsitemsr#   keys)r^   	flat_args_sorted_kwargssorted_keysflat_kwargsall_argss          r   _normalize_argsrp   m   sy      		*LIq4;;,,.NCMt{{//123K!-0NK;&HL8LLMMr   c                     t        j                         t        j                         t        j                         t         j                  j                         t         j                  j                         t        j                         t        j                         t         j                  j                         t        j                         t         j                  j                  j                         f
S r   )rA   is_grad_enabledis_inference_mode_enabledget_num_threads_C2_get_cublas_allow_fp16_reduced_precision_reduction2_get_cublas_allow_bf16_reduced_precision_reductionget_default_dtype$are_deterministic_algorithms_enabled_get_cublas_allow_tf32-is_deterministic_algorithms_warn_only_enabled	_autograd_saved_tensors_hooks_is_enabledr-   r   r   get_global_state_keyr~   x   s    '')CCECCE!224'');;=::< r   c                   z    e Zd ZdeddfdZededd fd       Zdee   fdZdee   fdZ	deddfd	Z
d
eddfdZy)BackwardBfsArgIteroriginr   Nc                 0    || _         t               | _        y r   )_curr   _queue)rF   r   s     r   r<   zBackwardBfsArgIter.__init__   s    $*	-2Wr   c                 >    t        |       }|j                  |        |S r   )r   add_children)r   its     r   createzBackwardBfsArgIter.create   s    '
	r   c                     | j                   }| j                  s	d | _         |S | j                  j                         | _         |S r   )r   r   popleft)rF   rets     r   nextzBackwardBfsArgIter.next   s;    ii{{DI 
 ++-DI
r   c                     | j                   S r   )r   rF   s    r   peekzBackwardBfsArgIter.peek   s    yyr   r^   c                    t        |j                        \  }}|D ]$  }t        |t              s| j	                  |       & t        |j
                        \  }}|D ]$  }t        |t              s| j	                  |       & y r   )r   r   rY   rZ   _appendrg   )rF   r^   rj   rk   rV   rn   kwargs          r   r   zBackwardBfsArgIter.add_children   sr    #DII.	1 	"C#t$S!	" &dkk2Q  	$E%&U#	$r   rV   c                 b    | j                   || _         y | j                  j                  |       y r   )r   r   r    )rF   rV   s     r   r   zBackwardBfsArgIter._append   s%    99DIKKs#r   )r*   r+   r,   rZ   r<   staticmethodr   r   r   r   r   r   r-   r   r   r   r      s~    5t 5 5 t  4  
htn htn 
$ 
$$ 
$$4 $D $r   r   c            
           e Zd ZdZddZdededee   dedef
d	Z	d
edede
fdZdddeddfdZdej                  j                  deee      fdZdefdZy)GraphRegionTrackera  
    GraphRegionTracker tracks each node added to the output graph and generates a key based on the source location,
    instruction pointer, input shapes, and global state at the time the node is inserted into the graph. Nodes with
    the same key are grouped together in a list of identical nodes (the value of node_to_duplicates).

    hash_to_duplicates: Dict[str, IdenticalNodes] - A dictionary mapping the key to a list of identical nodes
    node_to_duplicates: Dict[Node, IdenticalNodes] - A dictionary mapping a node to the list of identical nodes it belongs to
    input_pickler: InputPickler - An instance of InputPickler used to generate a node hash
    r   Nc                 X    t        t              | _        i | _        t	               | _        y r   )r   listhash_to_duplicatesnode_to_duplicatesr/   input_picklerr   s    r   r<   zGraphRegionTracker.__init__   s!    =H=N>@)^r   filenamelinenoinstruction_pointerr^   c                     ddl m} t               |||t        |      f} || j                  j                  |            S )Nr   )sha256_hash)r   r   r~   rp   r   rR   )rF   r   r   r   r^   r   rb   s          r   
_hash_nodezGraphRegionTracker._hash_node   sE     	: !"D!
 4--33C899r   n0n1c                     || j                   v xr4 || j                   v xr$ | j                   |   | j                   |   u xr ||uS r   )r   )rF   r   r   s      r   _is_identicalz GraphRegionTracker._is_identical   sY    $))) d---''+t/F/Fr/JJ "		
r   txr   c                 2   	 | j                   | j                  |j                  j                  |j                  |j
                  |         }|j                  |       || j                  |<   y# t        $ r!}t        j                  d||       Y d}~yd}~ww xY w)z
        The main entry point for tracking a node. This function will hash the node argument and group
        nodes with the same hash together. It updates the hash_to_duplicates and node_to_duplicates dictionaries
        to track the new node.
        z(Unable to hash node %s with exception %sN)r   r   f_codeco_filenamer   r   r    r   r)   logr   )rF   r   r^   
duplicatesrQ   s        r   
track_nodezGraphRegionTracker.track_node   s    		K00II))299b6L6LdJ
 d#,6D##D)  	KII@$JJ	Ks   A)A, ,	B5BBgraphc                    t        |j                        D ci c]  \  }}||
 c}}g }| j                  j                         D ]r  }t	        |      dkD  sg }t
        j                  }|D ](  }|v st        ||         }|j                  |g       * t	        |      dkD  s`|j                  ||f       t |j                  d        |D 	cg c]  \  }}	|	 }
}}	t               }|
D ]5  }t        ||| j                         |D ]  }|j                  fd        7 |
D cg c]  }t	        |d         dkD  s| c}S c c}}w c c}	}w c c}w )a  
        This function is responsible for extracting the largest regions of identical nodes from the given graph.
        **Note**: This function assumes the nodes that have been tracked with track_node are in the provided graph argument.

        The algorithm proceeds as follows:
        The nodes tracked via track_node above are organized into region groups. The initial region groups look like this:
        [[IdenticalNode1], [IdenticalNode2], [IdenticalNode3]] and each sublist is called a region. For each region group
        (starting at the topologically latest region group), the inner regions are gradually expanded one node at time from
        the flattened args and kwargs of the node in each region provided that for all regions in the group, the nodes being
        added are also identical (ie have the same key computed by track_node). This is checked by verifying that the two
        nodes have the same identical node list in node_to_duplicates.
        r   c                     | d    S )Nr   r-   )rgs    r   r5   z:GraphRegionTracker.get_identical_regions.<locals>.<lambda>  s    RUF r   ra   c                     |    S r   r-   )ntopological_rankings    r   r5   z:GraphRegionTracker.get_identical_regions.<locals>.<lambda>  s    *=a*@ r   r   )	enumeratenodesr   valueslenmathinfminr    sortsetfully_expand_region_groupr   )rF   r   ir^   region_groups_with_rankgroupregion_groupmin_rankr   rk   region_groups
seen_nodesregionr   s                @r   get_identical_regionsz(GraphRegionTracker.get_identical_regions   sy    7@6LM71dtQwM"$ ,,335 	ME5zA~!88! 4D22#&x1DT1J#K$++TF3	4 |$q(+22L(3KL	M 	 $$):$;)@AAAA
 !$
) 	BL%lJ@R@RS& B @AB	B .;
)c,q/>RUV>VL
 	
G N. B
s   E	E+EEc                 <    d| j                    d| j                   dS )Nz&GraphRegionTracker(hash_to_duplicates=z, node_to_duplicates=))r   r   r   s    r   __str__zGraphRegionTracker.__str__"  s.    78O8O7PPefjf}f}e~~  A  	Ar   rS   )r*   r+   r,   __doc__r<   r3   intr   rZ   r   boolr   r   rA   fxGraphr   Regionr   r   r-   r   r   r   r      s    ,
::%(:?G}:TX:	:
 
$ 
4 
K8 K K K"2
588>> 2
d4<>P 2
hA Ar   r   regionsr   is_identical_fnc           	         t        d       t        d|        t        d | D              sJ g }| D ]*  }|\  }|j                  t        j	                  |             , g }|D ]'  }|j                         }|sJ |j                  |       ) |d   j                         }	|	J |	rd}
|j                          |j                  |	       t        |      }|dd  D ]  }|j                         }t        d       t        d||	       t        d	||v        t        d
|       |r_t        d |||	             |
||vxr  ||vxr |j                  dk7  xr	  |||	      z  }
|j                  |       |j                  |       nd}
t        d        |
rt        | ||      D ]}  \  }}}|j                  |       t        d|       t        d|j                  t        |j                  j                                      |j                  |       |j                  |        |d   j                         }	|	r| D ]  }|j!                           t        d|        t        d       y )Nz2--------------------------------------------------zexpanding new region group: %sc              3   8   K   | ]  }t        |      d k(    yw)r   N)r   )rd   r   s     r   re   z,fully_expand_region_group.<locals>.<genexpr>/  s     6Fs6{a6s   r   Tr   z--------------------z$considering adding: %s, cur_node: %szpreviously claimed nodes: %sz%szis_identical: %splaceholderFzadding %s's childrenz%s %szend expand new region group: %s)r   allr    r   r   r   r   clearr   opaddzipr   r   rg   rh   reverse)r   r   r   region_itersr   r   nodes_to_add	region_itr^   current_nodeadd_nodenodes_to_add_sets               r   r   r   &  s   
 BC.8 6g6666L ?	.55f=>?  "L " %	~~tt$%
  ?'')L### L)|,%ab) 	.I>>#D,-<dLQ4dj6HIdJ',odL.QR
* <$44<=0< (l;	 ##D) $$T* ,-)	., +.wl+S %'	4d#0$7'499d4;;3D3D3F.GH&&t,t$% $A++-G L   /9BCr   ):r   r=   r8   loggingr   picklecollectionsr   r   dataclassesr   typingr   r   r   r	   r
   torch._loggingrA   torch.fxtorch._subclasses.fake_tensorr   torch.utils._pytreer   r   symbolic_convertr   r   rZ   r   r   IdenticalNodesr#   r   r   dtypeGlobalStateKey	getLoggerr*   r   _logginggetArtifactLoggerr   r3   r   Tensorr'   	Exceptionr)   Picklerr/   r]   rp   r~   r   r   r   r   r-   r   r   <module>r      s    	    *  B B   4 , CL ; xx}}	ddtT3dEKKtTSWWXg!nn66& 
*3 *$ *
 ||
 
8QCFU38_,-
 		 	%6>> %@S S N
N
5c?E(3-"4556Nn ,&$ &$RlA lA^FD&\FDD	FD tTlD01FD 
	FDr   