diff --git a/test/external/external_test_llvm.py b/test/external/external_test_llvm.py deleted file mode 100644 index e332d27a52..0000000000 --- a/test/external/external_test_llvm.py +++ /dev/null @@ -1,48 +0,0 @@ -#!/usr/bin/env python -import unittest -import numpy as np -from tinygrad.ops import LazyOp, BinaryOps, ReduceOps -from tinygrad.runtime.ops_llvm import LLVMBuffer - -class TestLLVM(unittest.TestCase): - def test_add(self): - a = LLVMBuffer.fromCPU(np.ones((4,4))) - b = LLVMBuffer.fromCPU(np.ones((4,4))) - ast = LazyOp(BinaryOps.ADD, (a,b)) - ret = LLVMBuffer((4,4)).exec_ast(ast) - print(ret.toCPU()) - - def test_sum(self): - a = LLVMBuffer.fromCPU(np.ones((4,4))) - ast = LazyOp(ReduceOps.SUM, (a,), (1,1)) - ret = LLVMBuffer((1,1)).exec_ast(ast) - print(ret.toCPU()) - - def test_sum_add(self): - a = LLVMBuffer.fromCPU(np.ones((4,4))) - b = LLVMBuffer.fromCPU(np.ones((1,1))) - ast = LazyOp(ReduceOps.SUM, (a,), (1,1)) - ast = LazyOp(BinaryOps.ADD, (ast,b)) - ret = LLVMBuffer((1,1)).exec_ast(ast) - print(ret.toCPU()) - - def test_add_sum(self): - a = LLVMBuffer.fromCPU(np.ones((4,4))) - b = LLVMBuffer.fromCPU(np.ones((4,4))) - ast = LazyOp(BinaryOps.ADD, (a,b)) - ast = LazyOp(ReduceOps.SUM, (ast,), (1,1)) - ret = LLVMBuffer((1,1)).exec_ast(ast) - print(ret.toCPU()) - - def test_add_sum_add(self): - a = LLVMBuffer.fromCPU(np.ones((4,4))) - b = LLVMBuffer.fromCPU(np.ones((4,4))) - c = LLVMBuffer.fromCPU(np.ones((1,1))) - ast = LazyOp(BinaryOps.ADD, (a,b)) - ast = LazyOp(ReduceOps.SUM, (ast,), (1,1)) - ast = LazyOp(BinaryOps.ADD, (ast,c)) - ret = LLVMBuffer((1,1)).exec_ast(ast) - print(ret.toCPU()) - -if __name__ == "__main__": - unittest.main() diff --git a/test/models/test_real_world.py b/test/models/test_real_world.py index 121e09b3ee..3e60404ac4 100644 --- a/test/models/test_real_world.py +++ b/test/models/test_real_world.py @@ -67,12 +67,14 @@ def derandomize_model(model): class TestRealWorld(unittest.TestCase): def setUp(self): + self.old_type = Tensor.default_type np.random.seed(2002) if getenv("KOPT"): self.oldfunc = getattr(__import__("tinygrad.codegen.search", fromlist=["kernel_optimize_search"]), "kernel_optimize_search") setattr(__import__("tinygrad.codegen.search", fromlist=["kernel_optimize_search"]), "kernel_optimize_search", kopt_search_hook) def tearDown(self): + Tensor.default_type = self.old_type if getenv("KOPT"): setattr(__import__("tinygrad.codegen.search", fromlist=["kernel_optimize_search"]), "kernel_optimize_search", self.oldfunc) @@ -86,7 +88,6 @@ class TestRealWorld(unittest.TestCase): @unittest.skipUnless(Device.DEFAULT in JIT_SUPPORTED_DEVICE and Device.DEFAULT not in ["LLVM"], "needs JIT, too long on CI LLVM") def test_llama(self): - old_type = Tensor.default_type Tensor.default_type = dtypes.float16 args_tiny = {"dim": 1024, "multiple_of": 256, "n_heads": 8, "n_layers": 8, "norm_eps": 1e-05, "vocab_size": 1000} @@ -97,11 +98,8 @@ class TestRealWorld(unittest.TestCase): # NOTE: only test one pass, not testing the dynamic shape autoregressive part helper_test("test_llama", lambda: (Tensor([[1,]]),), test, 0.22 if CI else 13.5, 126 if CI else 486) - Tensor.default_type = old_type - @unittest.skipUnless(Device.DEFAULT in JIT_SUPPORTED_DEVICE and Device.DEFAULT not in ["LLVM"], "needs JIT, too long on CI LLVM") def test_gpt2(self): - old_type = Tensor.default_type Tensor.default_type = dtypes.float16 args_tiny = {"dim": 1024, "n_heads": 8, "n_layers": 8, "norm_eps": 1e-5, "vocab_size": 1000} @@ -111,8 +109,6 @@ class TestRealWorld(unittest.TestCase): def test(t): return model(t, 0).realize() helper_test("test_gpt2", lambda: (Tensor([[1,]]),), test, 0.21 if CI else 0.9, 129 if CI else 369) - Tensor.default_type = old_type - @unittest.skipIf(getenv("KOPT"), "cifar hangs with KOPT") @unittest.skipUnless(Device.DEFAULT in JIT_SUPPORTED_DEVICE and Device.DEFAULT not in ["LLVM"], "needs JIT, too long on CI LLVM") def test_train_cifar(self): diff --git a/tinygrad/codegen/kernel.py b/tinygrad/codegen/kernel.py index f550f9886f..a94d4f133c 100644 --- a/tinygrad/codegen/kernel.py +++ b/tinygrad/codegen/kernel.py @@ -53,7 +53,6 @@ class Kernel: self.opts = opts if opts else (cast(Compiled, Device[Device.DEFAULT]).linearizer_opts if isinstance(Device[Device.DEFAULT], Compiled) else LinearizerOptions()) self.ast = ast self.var_vals = var_vals - self.key = (ast, tuple(var_vals.keys())) if var_vals else ast # fetch lazyop info self.info: FlopCounter = get_lazyop_info(cast(LazyOp, self.ast)) diff --git a/tinygrad/codegen/search.py b/tinygrad/codegen/search.py index 18836dca0a..c727275e02 100644 --- a/tinygrad/codegen/search.py +++ b/tinygrad/codegen/search.py @@ -50,10 +50,10 @@ def kernel_optimize_search(k:Linearizer, create_k:Callable[[], Linearizer], to_p # optimization global_db = None -def kernel_optimize(k:Linearizer, create_k:Callable[[], Linearizer], to_prg, bufs): +def kernel_optimize(k:Linearizer, create_k:Callable[[], Linearizer], to_prg, bufs, key): global global_db - skey = str(k.key) + skey = str(key) if getenv("KOPT") == 2 and global_db is None: import shelve diff --git a/tinygrad/ops.py b/tinygrad/ops.py index 372dba7fc7..f0726b24dd 100644 --- a/tinygrad/ops.py +++ b/tinygrad/ops.py @@ -67,14 +67,9 @@ class LazyOp: @property def st(self): raise NotImplementedError @property - def children(self): raise NotImplementedError - @property - def shape(self): raise NotImplementedError - @property def realized(self): raise NotImplementedError @property - def optype(self): raise NotImplementedError - def realize(self): raise NotImplementedError + def children(self): raise NotImplementedError # movement ops def reshape(self, _): raise NotImplementedError @@ -117,7 +112,7 @@ class Interpreted: if ast.op in BufferOps and ast.op not in self.fxn_for_op: if ast.op == BufferOps.MEM: assert inputs[ast.arg.idx-1].dtype == ast.arg.dtype, "dtype mismatch" - buf = self.to_underlying(inputs[ast.arg.idx-1]) + buf = self.to_underlying(inputs[ast.arg.idx-1].realized) elif ast.op == BufferOps.CONST: buf = self.to_underlying(self.buffer.fromCPU(np.array(ast.arg.val, dtype=ast.arg.dtype.np))) for mop,arg in ast.arg.st.to_movement_ops(): buf = self.fxn_for_op[mop](buf, arg) @@ -226,7 +221,7 @@ class Compiled: if output.realized: for i,a in enumerate(inputs): # TODO: if this is contiguous it's fine - if a == output.realized: + if a.realized == output.realized: if any(not x.arg.st.contiguous for x in ast.get_lazyops() if x.op == BufferOps.MEM and x.arg.idx == i+1): output.realized = None break @@ -238,23 +233,26 @@ class Compiled: from tinygrad.jit import CacheCollector CacheCollector._mark_output_buffer(output.output_buffer) - from tinygrad.codegen.linearizer import Linearizer - k = Linearizer(ast, self.linearizer_opts, var_vals) + # all the rawbuffers + rawbuffers = [output.realized] + [x.realized for x in inputs] + key = (ast, tuple(var_vals.keys())) if var_vals else ast # TODO: remove var_vals so the key can just be the AST # compilation time def get_program(): + from tinygrad.codegen.linearizer import Linearizer + k = Linearizer(ast, self.linearizer_opts, var_vals) from tinygrad.codegen.search import kernel_optimize - if getenv("KOPT"): kernel_optimize(k, lambda: Linearizer(ast, self.linearizer_opts, var_vals), self.to_program, [output.realized]+inputs) + if getenv("KOPT"): kernel_optimize(k, lambda: Linearizer(ast, self.linearizer_opts, var_vals), self.to_program, rawbuffers, key) elif not getenv("NOOPT"): k.hand_coded_optimizations() return self.to_program(k) - if hasattr(k, 'key') and getenv("ENABLE_METHOD_CACHE", 1): - if k.key not in self.method_cache: self.method_cache[k.key] = get_program() - prg = self.method_cache[k.key] + if getenv("ENABLE_METHOD_CACHE", 1): + if key not in self.method_cache: self.method_cache[key] = get_program() + prg = self.method_cache[key] else: prg = get_program() if prg.name == getenv("PRINT_PRG", ''): print(prg.prg) - prg.exec([output.realized]+inputs, var_vals=var_vals) + prg.exec(rawbuffers, var_vals=var_vals) return output.realized diff --git a/tinygrad/realize.py b/tinygrad/realize.py index 5656f43941..0dcad8a3d6 100644 --- a/tinygrad/realize.py +++ b/tinygrad/realize.py @@ -23,7 +23,7 @@ def run_schedule(schedule:List[Tuple[LazyOp, LazyBuffer, Tuple[LazyBuffer, ...]] for i,s in enumerate(op.src): assert isinstance(s, LazyOp) and s.op == BufferOps.MEM and s.arg.idx == i+1 and s.arg.st.contiguous, f"bad LoadOps src {i}: {s}" LOAD_OPS_DISPATCHER[cast(LoadOps, op.op)](out, *buffers) else: - out.realized = Device[out.device].exec_ast(op, output=out, inputs=[x.realized for x in buffers], var_vals=out.var_vals, **out._device_extra_args()) + out.realized = Device[out.device].exec_ast(op, output=out, inputs=buffers, var_vals=out.var_vals, **out._device_extra_args()) del out.op for v in out.views: del v.op assert out.realized and isinstance(out.realized, Device[out.device].buffer), f"device mismatch on realized got {type(out.realized)} expected {out.device}"