From f2bd65ccfc72c40151f5a04831c155444c9a0e74 Mon Sep 17 00:00:00 2001 From: qazal <77887910+Qazalin@users.noreply.github.com> Date: Thu, 3 Apr 2025 12:29:02 +0800 Subject: [PATCH] delete Ops.EMPTY and Tensor._metaop (#9715) * delete Ops.EMPTY and Tensor._metaop [pr] * test_creation * arg= * abstractions2 --- docs/abstractions2.py | 4 ++-- tinygrad/ops.py | 13 +++---------- tinygrad/tensor.py | 19 ++++++++----------- 3 files changed, 13 insertions(+), 23 deletions(-) diff --git a/docs/abstractions2.py b/docs/abstractions2.py index 1998cb3383..60cef6824d 100644 --- a/docs/abstractions2.py +++ b/docs/abstractions2.py @@ -80,8 +80,8 @@ from tinygrad.engine.realize import run_schedule from tinygrad.engine.schedule import create_schedule_with_vars # allocate some values + load in values -a = UOp.metaop(Ops.EMPTY, (1,), dtypes.int32, DEVICE) -b = UOp.metaop(Ops.EMPTY, (1,), dtypes.int32, DEVICE) +a = UOp.new_buffer(DEVICE, 1, dtypes.int32) +b = UOp.new_buffer(DEVICE, 1, dtypes.int32) a.buffer.allocate().copyin(memoryview(bytearray(struct.pack("I", 2)))) b.buffer.allocate().copyin(memoryview(bytearray(struct.pack("I", 3)))) diff --git a/tinygrad/ops.py b/tinygrad/ops.py index 546ad70cd2..11f061a42e 100644 --- a/tinygrad/ops.py +++ b/tinygrad/ops.py @@ -95,9 +95,6 @@ class Ops(FastEnum): # uops that aren't rendered NAME = auto(); SINK = auto(); CONTIGUOUS = auto(); CONTIGUOUS_BACKWARD = auto(); DETACH = auto(); KERNEL = auto(); UNIQUE = auto() # noqa: E702 - # TODO: empty continues to exist because of tensor - EMPTY = auto() - # MetaOps COPY = auto(); BUFFER_VIEW = auto() # noqa: E702 @@ -474,13 +471,9 @@ class UOp(MathTrait, metaclass=UOpMetaClass): return UOp.const(dtype, unwrap(arg)).replace(src=(UOp(Ops.VIEW, dtypes.void, (UOp(Ops.DEVICE, arg=device),), ShapeTracker.from_shape(())),)).reshape((1,)*len(shape)).expand(shape) # Tensor variable binding is BIND(VAR(VIEW(DEVICE)), CONST(VIEW(DEVICE))) - if op is Ops.BIND: - var, val = arg.unbind() - return var.replace(src=(UOp(Ops.VIEW, dtypes.void, (UOp(Ops.DEVICE, arg=device),), ShapeTracker.from_shape(shape)),)).bind(val) - # otherwise it's just a RESHAPE(BUFFER) - assert op is Ops.EMPTY, f"unkown op {op}" - if not isinstance(size:=prod([x.vmax if isinstance(x, UOp) else x for x in shape]), int): raise ValueError(f"size must be int {size}") - return UOp.new_buffer(device, size, dtype).reshape(shape) + assert op is Ops.BIND, f"unkown op {op}" + var, val = arg.unbind() + return var.replace(src=(UOp(Ops.VIEW, dtypes.void, (UOp(Ops.DEVICE, arg=device),), ShapeTracker.from_shape(shape)),)).bind(val) def copy_to_device(self, device:str|tuple[str, ...], clone:bool=False): return UOp(Ops.COPY, self.dtype, (UOp(Ops.DEVICE, arg=device), self), clone) def clone(self) -> UOp: return self.copy_to_device(self.device, clone=True) @property diff --git a/tinygrad/tensor.py b/tinygrad/tensor.py index 1c6eaf6944..ac0daf2c19 100644 --- a/tinygrad/tensor.py +++ b/tinygrad/tensor.py @@ -142,7 +142,7 @@ class Tensor(SimpleMathTrait): if isinstance(data, UOp): assert dtype is None or dtype==data.dtype, "dtype doesn't match, and casting isn't supported" if data.op is Ops.BIND: data = _metaop(Ops.BIND, tuple(), dtype or data.dtype, device, data) - elif data is None: data = _metaop(Ops.EMPTY, (0,), dtype or dtypes.default_float, device) + elif data is None: data = _metaop(Ops.CONST, (0,), dtype or dtypes.default_float, device, arg=0) elif isinstance(data, get_args(ConstType)): data = _metaop(Ops.CONST, tuple(), dtype or dtypes.from_py(data), device, data) elif isinstance(data, bytes): data = _frompy(data, dtypes.uint8 if dtype is None else dtype) elif isinstance(data, (list, tuple)): @@ -406,15 +406,7 @@ class Tensor(SimpleMathTrait): # ***** creation entrypoint ***** @staticmethod - def _metaop(op, shape, device:str|tuple[str, ...]|None=None, dtype:DTypeLike|None=None, arg=None, **kwargs) -> Tensor: - dtype = to_dtype(dtype) if dtype is not None else dtypes.default_float - if isinstance(device, tuple): - return Tensor(UOp.multi(*[UOp.metaop(op, shape, dtype, Device.canonicalize(d), arg) for d in device], axis=None), - device, dtype, **kwargs) - return Tensor(UOp.metaop(op, shape, dtype, Device.canonicalize(device), arg), device, dtype, **kwargs) - - @staticmethod - def empty(*shape, **kwargs) -> Tensor: + def empty(*shape, device:str|tuple[str, ...]|None=None, dtype:DTypeLike|None=None, **kwargs) -> Tensor: """ Creates an empty tensor with the given shape. @@ -426,7 +418,12 @@ class Tensor(SimpleMathTrait): print(t.shape) ``` """ - return Tensor._metaop(Ops.EMPTY, argfix(*shape), **kwargs) + dtype, shape = to_dtype(dtype) if dtype is not None else dtypes.default_float, argfix(*shape) + if not isinstance(size:=prod([x.vmax if isinstance(x, UOp) else x for x in shape]), int): raise ValueError(f"size must be int {size}") + if isinstance(device, tuple): + return Tensor(UOp.multi(*[UOp.new_buffer(Device.canonicalize(d), size, dtype).reshape(shape) for d in device], axis=None), + device, dtype, **kwargs) + return Tensor(UOp.new_buffer(Device.canonicalize(device), size, dtype), device, dtype, **kwargs).reshape(shape) @staticmethod def from_blob(ptr:int, shape:tuple[int, ...], **kwargs) -> Tensor: