CoolFace
Apppublic

Darkweb007/cuda-kernels

sourceHugging Faceupdated 2mo agoView on Hugging Face
0likes
fuser.py114 linesDownload Raw Back to fusion_compiler
1"""The fusion pass.2 3Rule: two adjacent elementwise nodes A -> B (A's output feeds B) may be4fused into the same group iff:5  1. Both A and B are elementwise ops (see ops.is_elementwise).6  2. A's output has exactly one consumer in the whole graph (namely B).7 8Condition (2) is the standard real-world fusion constraint: if A's output9were used by two different downstream nodes, fusing A into just one of them10would mean recomputing A's work for the other consumer (or keeping a11separate materialized copy anyway), which is a genuine cost-model decision,12not something to do silently. So by default we keep A un-fused into B in13that case, and A ends up as its own single-node group (or fused with ITS14single-consumer... no, it has two, so it stays separate).15 16Implementation: union-find over node output names. Group membership is a17maximal weakly-connected component under the "fusable edge" relation above.18Groups are then topologically ordered (in original node order, which is19already topological since the Graph is built via sequential .add() calls).20"""21 22from __future__ import annotations23 24from dataclasses import dataclass, field25from typing import Dict, List26 27from .graph import Graph, Node28from .ops import is_elementwise29 30 31class _UnionFind:32    def __init__(self):33        self.parent: Dict[str, str] = {}34 35    def find(self, x: str) -> str:36        self.parent.setdefault(x, x)37        while self.parent[x] != x:38            self.parent[x] = self.parent[self.parent[x]]39            x = self.parent[x]40        return x41 42    def union(self, a: str, b: str) -> None:43        ra, rb = self.find(a), self.find(b)44        if ra != rb:45            self.parent[ra] = rb46 47 48@dataclass49class FusionGroup:50    nodes: List[Node] = field(default_factory=list)51 52    @property53    def inputs(self) -> List[str]:54        """External inputs to this group: names read but not produced within it."""55        produced = {n.output for n in self.nodes}56        seen = []57        for n in self.nodes:58            for i in n.inputs:59                if i not in produced and i not in seen:60                    seen.append(i)61        return seen62 63    @property64    def output(self) -> str:65        """The single external-facing output of this group. Assumes groups66        formed by `fuse()` have exactly one node whose output escapes the67        group (true by construction: we only merge single-consumer edges)."""68        internal = {i for n in self.nodes for i in n.inputs}69        externally_visible = [n.output for n in self.nodes if n.output not in internal]70        if len(externally_visible) != 1:71            raise ValueError(72                f"FusionGroup expected exactly one external output, got {externally_visible}"73            )74        return externally_visible[0]75 76    def __repr__(self) -> str:77        body = "\n    ".join(repr(n) for n in self.nodes)78        return f"FusionGroup(\n    {body}\n  )"79 80 81def fuse(graph: Graph) -> List[FusionGroup]:82    consumer_count: Dict[str, int] = {}83    for node in graph:84        for i in node.inputs:85            consumer_count[i] = consumer_count.get(i, 0) + 186 87    uf = _UnionFind()88    for node in graph:89        uf.find(node.output)  # ensure registered90 91    for node in graph:92        if not is_elementwise(node.op):93            continue94        for input_name in node.inputs:95            producer = graph.producer_of(input_name)96            if producer is None:97                continue  # graph input, nothing to fuse with98            if not is_elementwise(producer.op):99                continue100            if consumer_count.get(producer.output, 0) != 1:101                continue  # producer feeds >1 consumer, don't fuse102            uf.union(producer.output, node.output)103 104    groups_by_root: Dict[str, FusionGroup] = {}105    order: List[str] = []106    for node in graph:  # graph.nodes is already topological order107        root = uf.find(node.output)108        if root not in groups_by_root:109            groups_by_root[root] = FusionGroup()110            order.append(root)111        groups_by_root[root].nodes.append(node)112 113    return [groups_by_root[r] for r in order]114