add device UOp [pr] (#8290)

This commit is contained in:
George Hotz
2024-12-17 09:11:51 -08:00
committed by GitHub
parent af87e4b53c
commit 21b085b8ed
2 changed files with 17 additions and 8 deletions
+8 -4
View File
@@ -146,6 +146,9 @@ class Ops(FastEnum):
# consts last!
VCONST = auto(); CONST = auto() # noqa: E702
# device
DEVICE = auto()
class GroupOp:
Unary = {Ops.EXP2, Ops.LOG2, Ops.SIN, Ops.SQRT, Ops.RECIP, Ops.NEG}
Binary = {Ops.ADD, Ops.MUL, Ops.IDIV, Ops.MAX, Ops.MOD, Ops.CMPLT, Ops.CMPNE, Ops.XOR, Ops.SHL, Ops.SHR, Ops.OR, Ops.AND, Ops.THREEFRY,
@@ -290,7 +293,7 @@ class UOp(MathTrait, metaclass=UOpMetaClass):
@property
def shape(self) -> Tuple[sint, ...]: return unwrap(self.st).shape
@property
def size(self) -> int: return self.arg[2] if self.op is Ops.BUFFER else unwrap(self.st).size
def size(self) -> int: return self.arg[-1] if self.op is Ops.BUFFER else unwrap(self.st).size
# *** uop evaluation ***
@@ -435,7 +438,7 @@ class UOp(MathTrait, metaclass=UOpMetaClass):
from tinygrad.shape.shapetracker import ShapeTracker
if op is Ops.CONST:
# NOTE: we embed device on CONST with a fake BUFFER uop
fake = UOp(Ops.BUFFER, dtype.ptr(), (), (-1, device, 1))
fake = UOp(Ops.BUFFER, dtype.ptr(), (UOp(Ops.DEVICE, arg=device),), (-1, 1))
# NOTE: BIND stays BIND, UOp.const unbinds here
const_uop = arg if isinstance(arg, UOp) else UOp.const(dtype, unwrap(arg))
return UOp(Ops.VIEW, dtype, (fake, const_uop), ShapeTracker.from_shape(())).reshape((1,)*len(shape)).expand(shape)
@@ -501,12 +504,13 @@ class UOp(MathTrait, metaclass=UOpMetaClass):
buffer_num = itertools.count(0)
@staticmethod
def new_buffer(device:str, size:int, dtype:DType) -> UOp: return UOp(Ops.BUFFER, dtype.ptr(), (), (next(UOp.buffer_num), device, size))
def new_buffer(device:str, size:int, dtype:DType) -> UOp:
return UOp(Ops.BUFFER, dtype.ptr(), (UOp(Ops.DEVICE, arg=device),), (next(UOp.buffer_num), size))
@property
def device(self) -> str: return unwrap(self._device)
@functools.cached_property
def _device(self) -> Optional[str]:
if self.op is Ops.BUFFER: return self.arg[1]
if self.op is Ops.DEVICE: return self.arg
# TODO: why does this fail?
#if self.op is Ops.COPY: return self.arg[0]
return dsrcs[0]._device if len(dsrcs:=[x for x in self.src if x._device is not None]) != 0 else None
+9 -4
View File
@@ -12,8 +12,9 @@ from tinygrad.device import ProfileEvent, ProfileDeviceEvent, ProfileRangeEvent,
uops_colors = {Ops.LOAD: "#ffc0c0", Ops.PRELOAD: "#ffc0c0", Ops.STORE: "#87CEEB", Ops.CONST: "#e0e0e0", Ops.VCONST: "#e0e0e0",
Ops.DEFINE_GLOBAL: "#ffe0b0", Ops.DEFINE_LOCAL: "#ffe0d0", Ops.DEFINE_ACC: "#f0ffe0", Ops.REDUCE_AXIS: "#FF6B6B",
Ops.RANGE: "#c8a0e0", Ops.ASSIGN: "#e0ffc0", Ops.BARRIER: "#ff8080", Ops.IF: "#c8b0c0", Ops.SPECIAL: "#c0c0ff",
Ops.INDEX: "#e8ffa0", Ops.WMMA: "#efefc0", Ops.VIEW: "#C8F9D4", **{x:"#ffffc0" for x in GroupOp.ALU},
Ops.BLOCK: "#C4A484", Ops.BLOCKEND: "#C4A4A4", Ops.BUFFER: "#B0BDFF",}
Ops.INDEX: "#e8ffa0", Ops.WMMA: "#efefc0", Ops.VIEW: "#C8F9D4",
**{x:"#D8F9E4" for x in GroupOp.Movement}, **{x:"#ffffc0" for x in GroupOp.ALU}, Ops.THREEFRY:"#ffff80",
Ops.BLOCK: "#C4A484", Ops.BLOCKEND: "#C4A4A4", Ops.BUFFER: "#B0BDFF", Ops.COPY: "#a040a0"}
# ** API spec
@@ -61,13 +62,17 @@ def get_metadata(keys:List[Any], contexts:List[List[TrackedGraphRewrite]]) -> Li
def uop_to_json(x:UOp) -> Dict[int, Tuple[str, str, List[int], str, str]]:
assert isinstance(x, UOp)
graph: Dict[int, Tuple[str, str, List[int], str, str]] = {}
excluded = set()
for u in x.toposort:
if u.op is Ops.CONST: continue
if u.op in {Ops.CONST, Ops.DEVICE}:
excluded.add(u)
continue
argst = ("\n".join([f"{v.shape} / {v.strides}"+(f" / {v.offset}" if v.offset else "") for v in u.arg.views])) if u.op is Ops.VIEW else str(u.arg)
label = f"{str(u.op).split('.')[1]}{(' '+word_wrap(argst.replace(':', ''))) if u.arg is not None else ''}\n{str(u.dtype)}"
for idx,x in enumerate(u.src):
if x.op is Ops.CONST: label += f"\nCONST{idx} {x.arg:g}"
graph[id(u)] = (label, str(u.dtype), [id(x) for x in u.src if x.op is not Ops.CONST], str(u.arg), uops_colors.get(u.op, "#ffffff"))
if x.op is Ops.DEVICE: label += f"\nDEVICE{idx} {x.arg}"
graph[id(u)] = (label, str(u.dtype), [id(x) for x in u.src if x not in excluded], str(u.arg), uops_colors.get(u.op, "#ffffff"))
return graph
def _replace_uop(base:UOp, replaces:Dict[UOp, UOp]) -> UOp:
if (found:=replaces.get(base)) is not None: return found