forked from tinygrad/tinygrad
add device UOp [pr] (#8290)
This commit is contained in:
+8
-4
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user