mirror of
https://github.com/tinygrad/tinygrad.git
synced 2026-08-16 13:18:26 +00:00
Compare commits
5
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4218cc9257 | ||
|
|
17419edc4a | ||
|
|
88e88d63d6 | ||
|
|
b21afb4883 | ||
|
|
dac3743d75 |
@@ -88,12 +88,14 @@ class GradAccClipAdamW(Optimizer):
|
||||
return out.shard_like(t) if offloaded else out
|
||||
if t.dtype in dtypes.fp8s:
|
||||
from examples.mlperf.models.flat_llama import FP8_MAX
|
||||
amax = new_w.float().abs().max(axis=tuple(range(1, new_w.ndim))).detach() # per-layer amax for (n_layers, out, in)
|
||||
scale = FP8_MAX / (amax + 1e-8)
|
||||
fp8_w = (new_w * scale.reshape(-1, *([1]*(new_w.ndim-1)))).clamp(-FP8_MAX, FP8_MAX).cast(t.dtype)
|
||||
if hasattr(t, '_inv_scale'):
|
||||
inv = ((amax + 1e-8) / FP8_MAX).cast(t._inv_scale.dtype)
|
||||
t._inv_scale.assign(inv.shard_like(t._inv_scale) if offloaded else inv)
|
||||
return fp8_w.shard_like(t) if offloaded else fp8_w
|
||||
# delayed scaling: reuse previous step's inv_scale
|
||||
scale = t._inv_scale.reciprocal().reshape(-1, *([1]*(new_w.ndim-1)))
|
||||
scaled = (new_w * scale).clamp(-FP8_MAX, FP8_MAX)
|
||||
ret = scaled.cast(t.dtype)
|
||||
# update inv_scale for next step from quantized result
|
||||
new_amax = (ret.float().abs().max(axis=tuple(range(1, ret.ndim))) * t._inv_scale).detach()
|
||||
inv = ((new_amax + 1e-8) / FP8_MAX).cast(t._inv_scale.dtype)
|
||||
t._inv_scale.assign(inv.shard_like(t._inv_scale) if offloaded else inv)
|
||||
return ret.shard_like(t) if offloaded else ret
|
||||
out = new_w.cast(t.dtype)
|
||||
return out.shard_like(t) if offloaded else out
|
||||
|
||||
Binary file not shown.
+2
-2
@@ -80,6 +80,7 @@ A \op{Buffer}'s \textbf{addrspace} is \texttt{GLOBAL}, \texttt{LOCAL}, or \textt
|
||||
\op{Stack} & $(T_0, T_1, \ldots)$ & --- & Join along a newly created leading axis. All shapes must match. \\
|
||||
\op{Replicated} & $(T,)$ & axes & Mark $T$ as replicated along axes. Collapse axes to $1$. \\
|
||||
\op{Slice} & $(T, \mathrm{offset})$ & size, dtype & Zero-copy \textit{size} elems of dtype; offset is elems of $T$ dtype. \\
|
||||
\op{Bitcast} & $(T,)$ & dtype & Reinterpret storage as target dtype; preserve total bytes. \\
|
||||
\bottomrule
|
||||
\end{tabular}
|
||||
|
||||
@@ -165,8 +166,7 @@ Unary & $(T,)$
|
||||
& $\mathrm{trunc}(x)$: round toward zero. \\
|
||||
& & \op{Cast}
|
||||
& Convert to target dtype (specified in arg). \\
|
||||
& & \op{Bitcast}
|
||||
& Reinterpret bits as target dtype. Must be same size. \\[4pt]
|
||||
\\[4pt]
|
||||
Binary & $(A, B)$
|
||||
& \op{Add}, \op{Mul}, \op{Max}, \op{Mod}, \op{Idiv}
|
||||
& $a+b$, $a \cdot b$, $\max(a,b)$, $a \bmod b$, $\lfloor a/b \rfloor$ \\
|
||||
|
||||
@@ -347,11 +347,12 @@ def late_buffer_view(t:UOp, b:UOp):
|
||||
assert x.op not in GroupOp.Elementwise, "can't buffer view elementwise"
|
||||
x = x.src[0]
|
||||
x = next(u for u in x.src if u.op is Ops.INDEX)
|
||||
assert x.op is Ops.INDEX, "must be INDEX"
|
||||
|
||||
if len(shape) == 0: offset = x.src[1].arg
|
||||
else: offset = max(sum(idx.vmin for idx in x.src[1:]), 0)
|
||||
|
||||
return b.replace(src=(UOp(Ops.SLICE, t.dtype, (x.base, UOp.const(dtypes.weakint, offset)), size), b.src[1]))
|
||||
return b.replace(src=(UOp(Ops.SLICE, t.dtype, (x.src[0], UOp.const(dtypes.weakint, offset)), size),))
|
||||
|
||||
to_bufferview = PatternMatcher([
|
||||
(UPat(Ops.STAGE, src=(UPat((Ops.BITCAST, Ops.CONTIGUOUS), name="t"), UPat()), name="b"), late_buffer_view),
|
||||
@@ -413,7 +414,11 @@ def bufferize_to_store(ctx:itertools.count, x:UOp, idx:UOp, allow_locals=True):
|
||||
# NOTE: the DEFINE_LOCAL needs to be disambiguated here
|
||||
if sdtype.addrspace == AddrSpace.GLOBAL:
|
||||
buf = UOp(Ops.BUFFER, x.dtype, (UOp(Ops.LUNIQUE, arg=next(ctx)), UOp(Ops.DEVICE, arg=x.arg.device)), size)
|
||||
do_store = buf.index(idx, dtype=sdtype).store(x.src[0]).end(*rngs)
|
||||
if x.src[0].op is Ops.SLICE:
|
||||
# no INDEX on SLICE, this could be cleaner
|
||||
do_store = buf.store(x.src[0]).end(*rngs)
|
||||
else:
|
||||
do_store = buf.index(idx, dtype=sdtype).store(x.src[0]).end(*rngs)
|
||||
return buf.after(do_store)
|
||||
|
||||
if allow_locals:
|
||||
|
||||
+1
-2
@@ -680,8 +680,7 @@ class UOp(OpMixin, metaclass=UOpMetaClass):
|
||||
def marg(self):
|
||||
match self.op:
|
||||
case Ops.RESHAPE | Ops.EXPAND: return tuple(ssimplify(self.src[1].sgep(i)) for i in range(self.src[1].dtype.count))
|
||||
case Ops.PAD: return tuple((self.src[1].sgep(i), self.src[2].sgep(i)) for i in range(self.src[1].dtype.count))
|
||||
case Ops.SHRINK: return tuple((self.src[1].sgep(i), self.src[2].sgep(i)) for i in range(self.src[1].dtype.count))
|
||||
case Ops.PAD | Ops.SHRINK: return tuple((self.src[1].sgep(i), self.src[2].sgep(i)) for i in range(self.src[1].dtype.count))
|
||||
case Ops.PERMUTE | Ops.FLIP: return self.arg
|
||||
case _: raise RuntimeError(f"{self.op} is not a MovementOp")
|
||||
|
||||
|
||||
@@ -224,12 +224,10 @@ spec_program = PatternMatcher([
|
||||
# these are intermediate ops. everything should be deleted from here
|
||||
spec_full = PatternMatcher([
|
||||
# SLICE on BUFFER is allowed if BUFFER is
|
||||
(UPat(Ops.SLICE, src=(UPat((Ops.BUFFER, Ops.PARAM)), UPat(Ops.CONST, dtype=dtypes.weakint)), allow_any_len=True, name="bv"),
|
||||
(UPat(Ops.SLICE, src=(UPat(GroupOp.Movement.union({Ops.BUFFER, Ops.PARAM, Ops.STAGE, Ops.AFTER})),
|
||||
UPat(Ops.CONST, dtype=dtypes.weakint)), allow_any_len=True, name="bv"),
|
||||
lambda bv: isinstance(bv.arg, int)),
|
||||
|
||||
# TODO: SLICE shouldn't go on INDEX. why is this allowed? remove these both
|
||||
(UPat(Ops.SLICE, src=(UPat((Ops.INDEX,)), UPat(Ops.CONST, dtype=dtypes.weakint)), allow_any_len=True, name="bv"),
|
||||
lambda bv: isinstance(bv.arg, int)),
|
||||
(UPat(Ops.CALL, src=(UPat((Ops.SLICE,)),), allow_any_len=True), lambda: True),
|
||||
|
||||
# codegen may end ranges after gpudims has replaced RANGE with SPECIAL.
|
||||
|
||||
+11
-11
@@ -70,16 +70,6 @@ const drawGraph = (data) => {
|
||||
const callCount = g.graph().callCount;
|
||||
const nodes = d3.select("#nodes").selectAll("g").data(g.nodes().map(id => g.node(id)), d => d).join("g").attr("class", d => d.className ?? "node")
|
||||
.attr("transform", d => `translate(${d.x},${d.y})`).on("click", (e,d) => {
|
||||
if (d.callNode || d.collapsible) {
|
||||
const t = d3.zoomTransform(document.getElementById("graph-svg"));
|
||||
const [x, y] = t.apply([d.x, d.y]);
|
||||
anchor = {id:d.id, x, y, k:t.k};
|
||||
if (d.callNode) {
|
||||
if (state.callSrcMask.has(d.id)) state.callSrcMask.delete(d.id); else state.callSrcMask.add(d.id);
|
||||
if (state.callSrcMask.size >= callCount) { showCallSrc.toggle.checked = !showCallSrc.toggle.checked; state.callSrcMask.clear(); }
|
||||
} else if (state.expandedNodes.has(d.id)) state.expandedNodes.delete(d.id); else state.expandedNodes.add(d.id);
|
||||
return setState({});
|
||||
}
|
||||
const parents = g.predecessors(d.id);
|
||||
const children = g.successors(d.id);
|
||||
if (parents == null && children == null) return;
|
||||
@@ -124,7 +114,17 @@ const drawGraph = (data) => {
|
||||
addTags(nodes.selectAll("g.tag").data(d => d.tag != null ? [d] : []).join("g").attr("class", "tag")
|
||||
.attr("transform", d => `translate(${-d.width/2+8}, ${-d.height/2+8})`).datum(e => ({ text:e.tag })));
|
||||
addTags(nodes.selectAll("g.type").data(d => d.collapsible ? [d] : []).join("g").attr("class", d => `tag ${d.collapsed ? 'collapsed' : 'expanded'}`)
|
||||
.attr("transform", d => `translate(${-d.width/2}, ${0})`).datum(d => ({ text:d.collapsed ? "+" : "−", fill:d.callNode ? null : d.color })));
|
||||
.attr("transform", d => `translate(${-d.width/2}, ${0})`).datum(d => ({ ...d, text:d.collapsed ? "+" : "−", fill:d.callNode ? null : d.color })).on("click", (e,d) => {
|
||||
e.stopPropagation();
|
||||
const t = d3.zoomTransform(document.getElementById("graph-svg"));
|
||||
const [x, y] = t.apply([d.x, d.y]);
|
||||
anchor = {id:d.id, x, y, k:t.k};
|
||||
if (d.callNode) {
|
||||
if (state.callSrcMask.has(d.id)) state.callSrcMask.delete(d.id); else state.callSrcMask.add(d.id);
|
||||
if (state.callSrcMask.size >= callCount) { showCallSrc.toggle.checked = !showCallSrc.toggle.checked; state.callSrcMask.clear(); }
|
||||
} else { if (state.expandedNodes.has(d.id)) state.expandedNodes.delete(d.id); else state.expandedNodes.add(d.id); }
|
||||
return setState({});
|
||||
}));
|
||||
addTags(nodes.selectAll("g.ref").data(d => d.ref != null ? [d] : []).join("g").attr("class", "tag ref")
|
||||
.attr("transform", d => `translate(${d.width/2-2}, ${-d.height/2+2})`).on("click", (e,d) => { e.stopPropagation(); switchCtx(d.ref); }).datum(d => ({ref:d.ref})),
|
||||
"M-1.7 1.7 L1.7 -1.7 M-0.55 -1.7 H1.7 V0.55");
|
||||
|
||||
Reference in New Issue
Block a user