scope variable names inside CALLs (#17424)

This commit is contained in:
2026-08-05 20:59:09 -04:00
committed by GitHub
parent d726e5f7f3
commit be25207a7a
3 changed files with 19 additions and 3 deletions
+12
View File
@@ -212,6 +212,18 @@ class TestCallSchedule(unittest.TestCase):
out = f(a, v.bind(5))
np.testing.assert_allclose(out.numpy(), [5., 10., 15.])
def test_precompile_scoped_bind_arg(self):
@function(precompile=True)
def f(x:Tensor, scale:UOp) -> Tensor: return x * scale
a = Tensor.ones(3)
x = f(a, UOp.variable("scale_a", 1, 100).bind(2))
y = f(a, UOp.variable("scale_b", 1, 100).bind(3))
fx = next(u for u in x.uop.toposort() if u.op is Ops.FUNCTION)
fy = next(u for u in y.uop.toposort() if u.op is Ops.FUNCTION)
self.assertEqual(fx.src[0].key, fy.src[0].key)
np.testing.assert_equal(x.numpy(), [2, 2, 2])
np.testing.assert_equal(y.numpy(), [3, 3, 3])
def test_precompile_schedule_cache_hit(self):
"""two instances of the same @function should produce identical function body keys (schedule cache hit)"""
@function(precompile=True)
+6 -2
View File
@@ -98,10 +98,14 @@ pm_post_sched_cache = PatternMatcher([
create_new_buffer(ctx, b) if isinstance(b.arg, ParamArg) and b.addrspace is AddrSpace.GLOBAL else None),
])
def resolve_linear_call(linear_call:UOp):
linear = graph_rewrite(linear_call.src[0], pm_post_sched_cache, ctx=({}, linear_call.src[1:]), walk=True, name="params to buffers")
binds = {f"p{i}":x.src[0] for i,x in enumerate(linear_call.src[1:]) if x.op is Ops.BIND}
return linear.substitute({v:binds[v.expr] for v in linear.variables() if v.expr in binds}, enter_calls=True, name="resolve scalar params")
pm_resolve_linear_call = PatternMatcher([
# call LINEAR is resolved here
(UPat(Ops.CALL, src=(UPat(Ops.LINEAR),), name="linear_call", allow_any_len=True), lambda linear_call:
graph_rewrite(linear_call.src[0], pm_post_sched_cache, ctx=({}, linear_call.src[1:]), walk=True, name="params to buffers")),
(UPat(Ops.CALL, src=(UPat(Ops.LINEAR),), name="linear_call", allow_any_len=True), resolve_linear_call),
])+pm_flatten_linear
schedule_cache: dict[bytes, UOp] = {}
+1 -1
View File
@@ -1166,8 +1166,8 @@ class UOp(RandMixin, metaclass=UOpMetaClass):
src: tuple[UOp, ...] = (UOp(Ops.NOOP) if shape is None else shape_to_shape_arg(shape),)
return UOp(Ops.PARAM, src=src, arg=ParamArg(slot, dtype, vmin_vmax, multiple_of, name, addrspace, axis, device, volatile))
def param_like(self, slot:int):
if self.op is Ops.BIND: return self.src[0].replace(arg=replace(self.src[0].arg, slot=slot, name=f"p{slot}"))
addrspace = self.addrspace if self.addrspace is not None else AddrSpace.GLOBAL
if self.op is Ops.BIND: return self.src[0].replace(arg=replace(self.src[0].arg, slot=slot, addrspace=addrspace))
return UOp.param(slot, self.dtype, self.shard_shape if self.axis is not None else self._shape, self.device, addrspace=addrspace, axis=self.axis)
@staticmethod