L i8?ddlZddlmZddlmZmZmZmZmZm Z ddl Z ddl m Z ddl mZddlmZddlmZdd lmZerdd lmZgd Ze d GddeZe d eGddZdede j4j6ddfdZe d dede eefde eefdeefdZe d  d dede eeefde eeedfdeeedeegefdedeedeegefde deefdZ! d dede eeefde eeedfdeeedeegefdedeedeegefde deefdZ"y)!N) dataclass)AnyCallable NamedTupleOptional TYPE_CHECKINGUnion) compatibility)symbolic_trace)Graph) GraphModule)Node) InternalMatch)Matchreplace_patternreplace_pattern_with_filtersReplacedPatternsT)is_backward_compatiblec,eZdZUeed<eeefed<y)ranchor nodes_mapN)__name__ __module__ __qualname__r__annotations__dict`/mnt/ssd/data/python-lab/Trading/venv/lib/python3.12/site-packages/torch/fx/subgraph_rewriter.pyrrs LD$JrrFc<eZdZUeed<eeefed<eeed<y)rrr replacementsN)rrrrrrlistrrr rr!s" LD$Jt*rrgm replacementreturnc|jt|tr|jj dt j jdtdttfd}|jjD]}|jdk(s|jdk(s"|||j}|||j}|K|ntj|}t|t j jr|j!|j|t#||j|t%d|jd|jd |jj y) Nr$targetr&c|jd\}}} |j|}t||d}|S#t$rYywxYw)N.) rpartition get_submoduleAttributeErrorgetattr)r$r( module_path_ attr_namemodattrs r try_get_attrz)_replace_attributes..try_get_attr2sW$*$5$5c$:! Q  #%#3#3K#@CsIt,   s7 AA call_moduleget_attrzAttempted to create a "z-" node during subgraph rewriting with target zL, but the referenced attribute does not exist in the replacement GraphModule)delete_all_unused_submodules isinstancergraphlinttorchnnModulestrrrnodesopr(copydeepcopy add_submodulesetattr RuntimeError)r$r%r4nodegm_attrreplacement_attrnew_attrs r _replace_attributesrJ,s;##%+{+ #(3- 77m #tww*'<"2t{{3G+KE  ""-==)9:.@$$T[[(;B X6 #-GG##';;-0;;/@HHMMOrpatternct|||}|Dcgc]#}t|j|j%c}Scc}w)a Matches all possible non-overlapping sets of operators and their data dependencies (``pattern``) in the Graph of a GraphModule (``gm``), then replaces each of these matched subgraphs with another subgraph (``replacement``). Args: ``gm``: The GraphModule that wraps the Graph to operate on ``pattern``: The subgraph to match in ``gm`` for replacement ``replacement``: The subgraph to replace ``pattern`` with Returns: List[Match]: A list of ``Match`` objects representing the places in the original graph that ``pattern`` was matched to. The list is empty if there are no matches. ``Match`` is defined as: .. code-block:: python class Match(NamedTuple): # Node from which the match was found anchor: Node # Maps nodes in the pattern subgraph to nodes in the larger graph nodes_map: Dict[Node, Node] Examples: .. code-block:: python import torch from torch.fx import symbolic_trace, subgraph_rewriter class M(torch.nn.Module): def __init__(self) -> None: super().__init__() def forward(self, x, w1, w2): m1 = torch.cat([w1, w2]).sum() m2 = torch.cat([w1, w2]).sum() return x + torch.max(m1) + torch.max(m2) def pattern(w1, w2): return torch.cat([w1, w2]) def replacement(w1, w2): return torch.stack([w1, w2]) traced_module = symbolic_trace(M()) subgraph_rewriter.replace_pattern(traced_module, pattern, replacement) The above code will first match ``pattern`` in the ``forward`` method of ``traced_module``. Pattern-matching is done based on use-def relationships, not node names. For example, if you had ``p = torch.cat([a, b])`` in ``pattern``, you could match ``m = torch.cat([a, b])`` in the original ``forward`` function, despite the variable names being different (``p`` vs ``m``). The ``return`` statement in ``pattern`` is matched based on its value only; it may or may not match to the ``return`` statement in the larger graph. In other words, the pattern doesn't have to extend to the end of the larger graph. When the pattern is matched, it will be removed from the larger function and replaced by ``replacement``. If there are multiple matches for ``pattern`` in the larger function, each non-overlapping match will be replaced. In the case of a match overlap, the first found match in the set of overlapping matches will be replaced. ("First" here being defined as the first in a topological ordering of the Nodes' use-def relationships. In most cases, the first Node is the parameter that appears directly after ``self``, while the last Node is whatever the function returns.) One important thing to note is that the parameters of the ``pattern`` Callable must be used in the Callable itself, and the parameters of the ``replacement`` Callable must match the pattern. The first rule is why, in the above code block, the ``forward`` function has parameters ``x, w1, w2``, but the ``pattern`` function only has parameters ``w1, w2``. ``pattern`` doesn't use ``x``, so it shouldn't specify ``x`` as a parameter. As an example of the second rule, consider replacing .. code-block:: python def pattern(x, y): return torch.neg(x) + torch.relu(y) with .. code-block:: python def replacement(x, y): return torch.relu(x) In this case, ``replacement`` needs the same number of parameters as ``pattern`` (both ``x`` and ``y``), even though the parameter ``y`` isn't used in ``replacement``. After calling ``subgraph_rewriter.replace_pattern``, the generated Python code looks like this: .. code-block:: python def forward(self, x, w1, w2): stack_1 = torch.stack([w1, w2]) sum_1 = stack_1.sum() stack_2 = torch.stack([w1, w2]) sum_2 = stack_2.sum() max_1 = torch.max(sum_1) add_1 = x + max_1 max_2 = torch.max(sum_2) add_2 = add_1 + max_2 return add_2 )rr)_replace_patternrrr)r$rKr%match_and_replacementsms r rr^s@v.b';G?U :;QXX5  s(= match_filtersrignore_literalsreplacement_callbacknode_name_matchc $t|||||||S)a See replace_pattern for documentation. This function is an overload with an additional match_filter argument. Args: ``match_filters``: A list of functions that take in (match: InternalMatch, original_graph: Graph, pattern_graph: Graph) and return a boolean indicating whether the match satisfies the condition. See matcher_utils.py for definition of InternalMatch. ``replacement_callback``: A function that takes in a match and returns a Graph to be used as the replacement. This allows you to construct a replacement graph based on the match. ``replacement_callback``: Node name to match. If not empty, it will try to match the node name. )rM)r$rKr%rPrQrRrSs r rrs&:   rc "#ddlm}m}|g}|j"t |t r |j#n(t |t r|#nt|j#|#ddd|} | j"|} | D cgc] t "#fd|Dr } } t |t r |j} n?t |t r|} n,t|rt|j} n |Jdd} i} g}| D]r}| ||"#}n | Jd| }|jDcgc]}|jd k(s|}}t|jt|k(sJi}t||jD]\}}t |t r| j#||||<|||k7s4|jj%|}| ||j|<t'|j(j+t'|j(j-j%|}| ||j(|<|||<t/}|j0D]}|j3|j4d}t|dk(rd}nz#_replace_pattern..4s"  NM : szGMust provide either a replacement GraphModule or a replacement callback placeholderr zThe insert point can't be Noneoutput)rrr")*#torch.fx.passes.utils.matcher_utilsrrVr9r8rr r matchallcallabler?r@lenplaceholder_nodesziprgetindexr#rkeysvaluessetreturning_nodesupdateusersnextiterreversedinserting_before graph_copyreplace_all_uses_with erase_nodeappendranchors recompiler;r<r=rJ)$r$rKr%rPrQrRrSrrVmatcher_matchesrOcommon_replacement_graphmatch_changed_noderNrcreplacement_graphnreplacement_placeholdersval_maprngngn_indmap_key user_nodesfirst_user_nodefirst_next_node next_node insert_pointcopied_returning_nodesvreplacement_nodes copied_noderFr]r^s$ ` @@r rMrMs(S HHN';' GU # &w/55 #'' G%,MM%2%H  -   H+{+#.#4#4 K '#. + #1+#>#D#D #/ U /$( ,.b   + 4~}! ,7 Y 7!9 (..$ !$$-2GA$  $ 5**+s3K/LLLL$&2E4K4KL !FB"d#044R< $"44::2>F6H6LE++F3"5??#7#7#9:U__3356<%>!7& "  ,d 3&<%> "~~') 1E4K4K+KA) ) 5(()S1G-HHHH"5#8#8:PQ 1OB  $ $[ 1%0 r " 1]001 (Dww-'DGGx,?__T*##B' ( %% }}Q'//.  yb LLLN+uxx/B , !!MF$ r  ) s*S3SS3S 3SS S )NNFN)#rA dataclassesrtypingrrrrrr r;_compatibilityr _symbolic_tracer r9r graph_modulerrFr-passes.utils.matcher_with_name_node_map_utilsr__all__rrr<r=rJr#rboolr>rrMrrr rs !LL )+%L d+ J , e,  -/K/ehhoo/$/dd+}} 8[( )}x,-} %[ },}Be,>B ! $$ 8UK/ 0$x T9:$ Xu5t; <= $$#/5%0%78$$ $-$T>B ! o"o" 8UK/ 0o"x T9:o" Xu5t; <= o"o"#/5%0%78o"o" o"r