You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
110 lines
6.2 KiB
110 lines
6.2 KiB
#!/usr/bin/env python
|
|
import unittest, os, subprocess, sys
|
|
from tinygrad import Tensor
|
|
from tinygrad.device import Device, Compiler
|
|
from tinygrad.helpers import diskcache_get, diskcache_put, getenv, Context, WIN, CI
|
|
|
|
class TestDevice(unittest.TestCase):
|
|
def test_canonicalize(self):
|
|
self.assertEqual(Device.canonicalize(None), Device.DEFAULT)
|
|
self.assertEqual(Device.canonicalize("CPU"), "CPU")
|
|
self.assertEqual(Device.canonicalize("cpu"), "CPU")
|
|
self.assertEqual(Device.canonicalize("CL"), "CL")
|
|
self.assertEqual(Device.canonicalize("CL:0"), "CL")
|
|
self.assertEqual(Device.canonicalize("cl:0"), "CL")
|
|
self.assertEqual(Device.canonicalize("CL:1"), "CL:1")
|
|
self.assertEqual(Device.canonicalize("cl:1"), "CL:1")
|
|
self.assertEqual(Device.canonicalize("CL:2"), "CL:2")
|
|
self.assertEqual(Device.canonicalize("disk:/dev/shm/test"), "DISK:/dev/shm/test")
|
|
self.assertEqual(Device.canonicalize("disk:000.txt"), "DISK:000.txt")
|
|
|
|
def test_getitem_not_exist(self):
|
|
with self.assertRaises(ModuleNotFoundError):
|
|
Device["TYPO"]
|
|
|
|
def test_lowercase_canonicalizes(self):
|
|
device = Device.DEFAULT
|
|
Device.DEFAULT = device.lower()
|
|
self.assertEqual(Device.canonicalize(None), device)
|
|
Device.DEFAULT = device
|
|
|
|
@unittest.skipIf(WIN and CI, "skipping windows test") # TODO: subproccess causes memory violation?
|
|
def test_env_overwrite_default_compiler(self):
|
|
expect_failure = "\ntry: assert Device[Device.DEFAULT].compiler is None;\nexcept RuntimeError: pass"
|
|
|
|
if Device.DEFAULT == "CPU":
|
|
from tinygrad.runtime.support.compiler_cpu import CPULLVMCompiler, ClangJITCompiler
|
|
try: _, _ = CPULLVMCompiler(), ClangJITCompiler()
|
|
except Exception as e: self.skipTest(f"skipping compiler test: not all compilers: {e}")
|
|
|
|
imports = "from tinygrad import Device; from tinygrad.runtime.support.compiler_cpu import CPULLVMCompiler, ClangJITCompiler"
|
|
subprocess.run([f'python3 -c "{imports}; assert isinstance(Device[Device.DEFAULT].compiler, CPULLVMCompiler)"'],
|
|
shell=True, check=True, env={**os.environ, "DEV": "CPU", "CPU_LLVM": "1"})
|
|
subprocess.run([f'python3 -c "{imports}; assert isinstance(Device[Device.DEFAULT].compiler, ClangJITCompiler)"'],
|
|
shell=True, check=True, env={**os.environ, "DEV": "CPU", "CPU_LLVM": "0"})
|
|
subprocess.run([f'python3 -c "{imports}; {expect_failure}"'],
|
|
shell=True, check=True, env={**os.environ, "DEV": "CPU", "CPU_CLANGJIT": "0", "CPU_LLVM": "0"})
|
|
subprocess.run([f'python3 -c "{imports}; assert isinstance(Device[Device.DEFAULT].compiler, CPULLVMCompiler)"'],
|
|
shell=True, check=True, env={**os.environ, "DEV": "CPU", "CPU_CLANGJIT": "0"})
|
|
subprocess.run([f'python3 -c "{imports}; {expect_failure}"'],
|
|
shell=True, check=True, env={**os.environ, "DEV": "CPU", "CPU_CLANGJIT": "1", "CPU_LLVM": "1"})
|
|
elif Device.DEFAULT == "AMD":
|
|
from tinygrad.runtime.support.compiler_amd import HIPCompiler, AMDLLVMCompiler
|
|
try: _, _ = HIPCompiler(Device[Device.DEFAULT].arch), AMDLLVMCompiler(Device[Device.DEFAULT].arch)
|
|
except Exception as e: self.skipTest(f"skipping compiler test: not all compilers: {e}")
|
|
|
|
imports = "from tinygrad import Device; from tinygrad.runtime.support.compiler_amd import HIPCompiler, AMDLLVMCompiler"
|
|
subprocess.run([f'python3 -c "{imports}; assert isinstance(Device[Device.DEFAULT].compiler, AMDLLVMCompiler)"'],
|
|
shell=True, check=True, env={**os.environ, "DEV": "AMD", "AMD_LLVM": "1"})
|
|
subprocess.run([f'python3 -c "{imports}; assert isinstance(Device[Device.DEFAULT].compiler, HIPCompiler)"'],
|
|
shell=True, check=True, env={**os.environ, "DEV": "AMD", "AMD_LLVM": "0"})
|
|
subprocess.run([f'python3 -c "{imports}; assert isinstance(Device[Device.DEFAULT].compiler, HIPCompiler)"'],
|
|
shell=True, check=True, env={**os.environ, "DEV": "AMD", "AMD_HIP": "1"})
|
|
subprocess.run([f'python3 -c "{imports}; {expect_failure}"'],
|
|
shell=True, check=True, env={**os.environ, "DEV": "AMD", "AMD_HIP": "1", "AMD_LLVM": "1"})
|
|
else: self.skipTest("only run on CPU/AMD")
|
|
|
|
def test_compiler_envvar(self):
|
|
d = Device[Device.DEFAULT]
|
|
dname = Device.DEFAULT.split(':')[0].upper()
|
|
assert d._get_compiler_envvar(type("Compiler", (), {})) == f"{dname}_COMPILER"
|
|
assert d._get_compiler_envvar(type("LLVMCompiler", (), {})) == f"{dname}_LLVM"
|
|
assert d._get_compiler_envvar(type("RandomCompiler", (), {})) == f"{dname}_RANDOM"
|
|
assert d._get_compiler_envvar(type(f"{dname}Compiler", (), {})) == f"{dname}_{dname}COMPILER" # do not repeat device name alone
|
|
assert d._get_compiler_envvar(type(f"{dname}LLVMCompiler", (), {})) == f"{dname}_LLVM" # do not repeat device name
|
|
|
|
class MockCompiler(Compiler):
|
|
def __init__(self, key): super().__init__(key)
|
|
def compile(self, src) -> bytes: return src.encode()
|
|
|
|
class TestCompiler(unittest.TestCase):
|
|
def test_compile_cached(self):
|
|
diskcache_put("key", "123", None) # clear cache
|
|
getenv.cache_clear()
|
|
with Context(DISABLE_COMPILER_CACHE=0):
|
|
self.assertEqual(MockCompiler("key").compile_cached("123"), str.encode("123"))
|
|
self.assertEqual(diskcache_get("key", "123"), str.encode("123"))
|
|
|
|
def test_compile_cached_disabled(self):
|
|
diskcache_put("disabled_key", "123", None) # clear cache
|
|
getenv.cache_clear()
|
|
with Context(DISABLE_COMPILER_CACHE=1):
|
|
self.assertEqual(MockCompiler("disabled_key").compile_cached("123"), str.encode("123"))
|
|
self.assertIsNone(diskcache_get("disabled_key", "123"))
|
|
|
|
def test_device_compile(self):
|
|
getenv.cache_clear()
|
|
with Context(DISABLE_COMPILER_CACHE=1):
|
|
a = Tensor([0.,1.], device=Device.DEFAULT).realize()
|
|
(a + 1).realize()
|
|
|
|
class TestRunAsModule(unittest.TestCase):
|
|
def test_module_runs(self):
|
|
p = subprocess.run([sys.executable, "-m", "tinygrad.device"],stdout=subprocess.PIPE, stderr=subprocess.PIPE,
|
|
env={**os.environ, "DEBUG": "1"}, timeout=30,)
|
|
out = (p.stdout + p.stderr).decode()
|
|
self.assertEqual(p.returncode, 0, msg=out)
|
|
self.assertIn("CPU", out) # for sanity check
|
|
|
|
if __name__ == "__main__":
|
|
unittest.main()
|
|
|