mirror of
https://github.com/tinygrad/tinygrad.git
synced 2026-08-14 06:58:28 +00:00
Compare commits
8
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f34efbe9f3 | ||
|
|
0f40b9c3b5 | ||
|
|
06bd987dcb | ||
|
|
1cbe0ba1f2 | ||
|
|
548154c8f2 | ||
|
|
2d1d91dd99 | ||
|
|
1da09eb82d | ||
|
|
5825ffbbcf |
@@ -4,6 +4,7 @@ import itertools
|
||||
from tinygrad.helpers import DISABLE_FAST_IDIV, TRANSCENDENTAL, SPEC, DEBUG, VIZ, IMAGE, NOOPT, EMULATED_DTYPES, NOLOCALS, USE_TC
|
||||
from tinygrad.helpers import ALLOW_TF32, TracingKey, Context, panic
|
||||
from tinygrad.uop.ops import PatternMatcher, graph_rewrite, UOp, pm_lower_index_dtype, Ops, UPat, track_rewrites, KernelInfo, ProgramInfo, GroupOp
|
||||
from tinygrad.uop.ops import shape_to_shape_arg
|
||||
from tinygrad.uop.render import pyrender
|
||||
from tinygrad.uop.spec import type_verify, spec_tensor, spec_program
|
||||
from tinygrad.renderer import Renderer, Estimates
|
||||
@@ -57,6 +58,16 @@ pm_no_weakints = PatternMatcher([
|
||||
(UPat(GroupOp.All, dtype=dtypes.weakint, name="x"), lambda x: x.replace(dtype=dtypes.int))
|
||||
])
|
||||
|
||||
pm_fix_image_shrink = PatternMatcher([
|
||||
# proper image index
|
||||
(UPat(Ops.SHRINK, src=(UPat(Ops.RESHAPE, src=(UPat(Ops.PARAM, name="img"), UPat())), UPat(name="idx"), UPat()), name="out"),
|
||||
lambda img,out,idx: img.reshape(-1, 4).index(idx.src[0]//4) if len(img.shape) == 3 and out.shape == (4,) else None),
|
||||
# demote this to non image
|
||||
(UPat(Ops.INDEX, src=(UPat(Ops.RESHAPE, src=(UPat(Ops.PARAM, name="img"), UPat())), UPat(name="idx")), name="out"),
|
||||
lambda img,out,idx: img.replace(src=(shape_to_shape_arg((img.max_numel(),)),),
|
||||
dtype=dtypes.half if img.dtype.itemsize == 2 else dtypes.float).index(idx) if out.shape == () else None)
|
||||
])+pm_mops
|
||||
|
||||
def full_rewrite_to_sink(ast:UOp, ren:Renderer, optimize:bool=True) -> UOp:
|
||||
if VIZ: graph_rewrite(ast, PatternMatcher([]), name="View Base AST")
|
||||
if DEBUG >= 5: print(pyrender(ast))
|
||||
@@ -104,8 +115,8 @@ def full_rewrite_to_sink(ast:UOp, ren:Renderer, optimize:bool=True) -> UOp:
|
||||
sink = graph_rewrite(sink, pm_add_loads+pm_remove_invalid, name="** add loads (code)")
|
||||
|
||||
# create image buffers
|
||||
if IMAGE and ren.target.device in {"QCOM", "CL", "PYTHON", "NULL"}:
|
||||
sink = graph_rewrite(sink, pm_make_images, name="create image buffers", bottom_up=True, ctx=ren.target.arch)
|
||||
#if IMAGE and ren.target.device in {"QCOM", "CL", "PYTHON", "NULL"}:
|
||||
# sink = graph_rewrite(sink, pm_make_images, name="create image buffers", bottom_up=True, ctx=ren.target.arch)
|
||||
|
||||
# devectorize
|
||||
sink = graph_rewrite(sink, sym+devectorize_alu+devectorize_buf_and_index+load_store_folding+correct_load_store+load_store_indexing,
|
||||
@@ -127,6 +138,10 @@ def full_rewrite_to_sink(ast:UOp, ren:Renderer, optimize:bool=True) -> UOp:
|
||||
# do memory coalesing (late)
|
||||
sink = memory_coalesing(sink, ren)
|
||||
|
||||
# image fixup
|
||||
#if IMAGE and ren.target.device in {"QCOM", "CL", "PYTHON", "NULL"}:
|
||||
# sink = graph_rewrite(sink, pm_fix_image_shrink, name="fix image shrink")
|
||||
|
||||
# instruction selection decompositions
|
||||
pm_decomp = pm_decomp+\
|
||||
get_late_rewrite_patterns(supported_ops, bool(DISABLE_FAST_IDIV))+\
|
||||
|
||||
@@ -3,17 +3,20 @@ import itertools
|
||||
from collections import defaultdict
|
||||
from tinygrad.dtype import dtypes, AddrSpace, Invalid, ImageDType
|
||||
from tinygrad.uop.ops import UOp, Ops
|
||||
from tinygrad.helpers import getenv
|
||||
from tinygrad.helpers import getenv, IMAGE
|
||||
from tinygrad.renderer import Renderer
|
||||
|
||||
# image now lives here
|
||||
|
||||
def memory_coalesing(sink:UOp, ctx:Renderer) -> UOp:
|
||||
if getenv("DMC"): return sink
|
||||
using_image = IMAGE and ctx.target.device in {"QCOM", "CL", "PYTHON", "NULL"}
|
||||
|
||||
# collect
|
||||
memory: defaultdict[tuple[Ops, UOp, Any, Any], dict[int, list[UOp]]] = defaultdict(dict)
|
||||
for u in sink.toposort():
|
||||
# TODO: this should handle images too, it's just memory coalesing
|
||||
if u.op in {Ops.LOAD, Ops.STORE} and not isinstance(u.src[0].src[0].dtype, ImageDType):
|
||||
if u.op in {Ops.LOAD, Ops.STORE}:
|
||||
assert len(u.src) == (2 if u.op is Ops.STORE else 1), "memory coalesing does not support gated loads/stores"
|
||||
if u.src[0].op is not Ops.INDEX: continue
|
||||
buf, idx_u = u.src[0].src
|
||||
@@ -44,7 +47,7 @@ def memory_coalesing(sink:UOp, ctx:Renderer) -> UOp:
|
||||
lengths = [4]
|
||||
elif ctx is not None and ctx.supports_float4:
|
||||
# TODO: a better way to get this than ctx
|
||||
lengths = [8,4,2] if buf.dtype.base == dtypes.half and getenv("ALLOW_HALF8") else [4,2]
|
||||
lengths = [8,4,2] if buf.dtype.base == dtypes.half and getenv("ALLOW_HALF8") and not using_image else [4,2]
|
||||
lengths.append(1) # worst case, it's not folded
|
||||
# do the grouping
|
||||
grouped_offsets = [[x for _,x in group] for _,group in itertools.groupby(enumerate(sorted(offsets.keys())), lambda x: x[1]-x[0])]
|
||||
@@ -53,6 +56,9 @@ def memory_coalesing(sink:UOp, ctx:Renderer) -> UOp:
|
||||
offset = (base+full_grp[0]) if isinstance(base, UOp) else UOp.const(dtypes.int, full_grp[0])
|
||||
length = [l for l in lengths if l <= len(full_grp) and (not must_divide or offset.divides(l) is not None)][0]
|
||||
grp = full_grp[:length]
|
||||
if len(grp) == 4 and using_image:
|
||||
print("IMAGE OPTION")
|
||||
pass
|
||||
idx = buf._mop(Ops.SHRINK, arg=[(offset, len(grp))]) if len(grp) > 1 else buf.index(offset)
|
||||
if op == Ops.STORE:
|
||||
datas = []
|
||||
|
||||
@@ -172,7 +172,7 @@ def split_load_store(ctx:Renderer|None, ls:UOp, idx:UOp):
|
||||
lengths = []
|
||||
must_divide = True
|
||||
# TODO: this belongs in coalese
|
||||
if isinstance(buf.dtype, ImageDType): lengths = [4]
|
||||
#if isinstance(buf.dtype, ImageDType): lengths = [4]
|
||||
lengths.append(1) # worst case, it's not folded
|
||||
|
||||
# filter fold lengths that don't divide
|
||||
|
||||
Reference in New Issue
Block a user