From 00822603ecd9ee18f7844bbd0d8b3ed476ebeba8 Mon Sep 17 00:00:00 2001 From: qazal <77887910+Qazalin@users.noreply.github.com> Date: Sun, 1 Jun 2025 23:27:04 +0300 Subject: [PATCH] allow stacking of VIEW UOps [pr] (#10532) * allow stacking of VIEW UOps [pr] * merge_views is first * simpler * loc for pr, this needs a helper * keep * diff [pr] * formatting --- tinygrad/engine/grouper.py | 10 +++++----- tinygrad/uop/ops.py | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/tinygrad/engine/grouper.py b/tinygrad/engine/grouper.py index a3e3d22816..15d7015a32 100644 --- a/tinygrad/engine/grouper.py +++ b/tinygrad/engine/grouper.py @@ -266,7 +266,7 @@ merge_views = PatternMatcher([ # merge adjacent views (UPat(Ops.VIEW, src=(UPat(Ops.VIEW, name="v1"),), name="v2"), lambda v1,v2: v1.replace(arg=v1.arg+v2.arg)), # replace MovementOps with VIEW - (UPat(GroupOp.Movement, src=(UPat.var("x"),), name="mop"), lambda mop,x: x.view(mop.st)), + (UPat(GroupOp.Movement, src=(UPat.var("x"),), name="mop"), lambda mop,x: x.base.view(mop.st)), # remove NOOP views (UPat.var("x").view(name="view"), lambda x,view: x if x.st is not None and view.st.contiguous and view.shape == x.shape else None), (UPat(GroupOp.All-{Ops.DEFINE_GLOBAL}).view(name="view"), @@ -301,7 +301,7 @@ def reduce_push_add_ones(src:UOp, r:UOp, view:UOp): view_left = merge_views+PatternMatcher([ # view before elementwise and buffer ops (UPat(Ops.VIEW, src=(UPat({*GroupOp.ALU, Ops.CAST, Ops.BITCAST, Ops.BIND, Ops.LOAD, Ops.STORE, Ops.VALID}, name="e"),), name="view"), - lambda e,view: e.replace(src=tuple(s.view(s.st+view.st) if s.op is Ops.VIEW else s.view(view.st) for s in e.src))), + lambda e,view: e.replace(src=tuple(s.view(view.st) for s in e.src))), # if there's ones added after reduce, put this before the reduce (UPat(Ops.VIEW, src=(UPat(Ops.REDUCE_AXIS, src=(UPat.var("src"),), name="r"),), name="view"), reduce_push_add_ones), ]) @@ -319,7 +319,7 @@ def swizzle_reduceop(r:UOp, src:UOp, view:UOp, fuse=False): # create a new reduceop for the swizzled input new_input_st = tmp + ShapeTracker(tuple(nv)) new_axis = tuple(range(len(st.shape), len(st.shape) + len(r.axis_arg))) - swizzled_src = apply_swizzle(src.view(src.arg+new_input_st if src.op is Ops.VIEW else new_input_st)) + swizzled_src = apply_swizzle(src.view(new_input_st)) if fuse: red = UOp(Ops.REDUCE_AXIS, r.dtype, (swizzled_src.fuse(),), (r.arg[0], new_axis, True)) else: red = UOp(Ops.REDUCE_AXIS, r.dtype, (swizzled_src,), (r.arg[0], new_axis)) return red.view(ShapeTracker.from_shape(st.shape)) @@ -337,7 +337,7 @@ def elementwise_view_right(root:UOp): assert all_same([x.base.size for x in swizzles]), f"swizzle inputs must have the same size {swizzles}" # place view after applying the elementwise op new_st = ShapeTracker.from_shape(swizzles[0].base.shape) - new_src = [x.base if x.base.shape==new_st.shape else apply_swizzle(x.view(x.arg+new_st) if x.op is Ops.VIEW else x.view(new_st)) for x in root.src] + new_src = [x.base if x.base.shape==new_st.shape else apply_swizzle(x.view(new_st)) for x in root.src] # reshape to match downstream shapes return root.replace(src=tuple(new_src)).reshape(root.shape) @@ -435,7 +435,7 @@ pm_fuse = PatternMatcher([ # FUSE elementwise. (UPat(Ops.VIEW, src=(UPat({*GroupOp.ALU, Ops.CAST}, name="alu"),), name="view").fuse(), - lambda alu, view: alu.replace(src=tuple(x.view(x.arg+view.arg if x.op is Ops.VIEW else view.arg).fuse() for x in alu.src))), + lambda alu, view: alu.replace(src=tuple(apply_swizzle(x.view(view.arg)).fuse() for x in alu.src))), # push FUSE through to srcs (UPat(Ops.FUSE, name="x"), lambda x: x.src[0].replace(src=tuple(y.fuse() for y in x.src[0].src))), diff --git a/tinygrad/uop/ops.py b/tinygrad/uop/ops.py index c2060bc374..2934c74388 100644 --- a/tinygrad/uop/ops.py +++ b/tinygrad/uop/ops.py @@ -498,7 +498,7 @@ class UOp(MathTrait, metaclass=UOpMetaClass): if (self.op is Ops.VIEW and len(self.src) != 0) or self.op in GroupOp.Movement: return self.src[0].base if self.op is Ops.MULTI: return self.src[0].base # MULTI is really a VIEW return self - def view(self, new_st:ShapeTracker) -> UOp: return UOp(Ops.VIEW, self.dtype, (self.base,), new_st) + def view(self, new_st:ShapeTracker) -> UOp: return UOp(Ops.VIEW, self.dtype, (self,), new_st) def _mop(self, op:Ops, arg): ret = UOp(op, self.dtype, (self,), arg)