Files
nimlgenandGitHub 58edff61d9
Autogen / In-tree Autogen (comgr 2) (push) Successful in 59s
Unit Tests / Fuzzing (push) Successful in 3m12s
Unit Tests / Python Backend (push) Successful in 3m30s
Unit Tests / Test LLM (push) Successful in 3m32s
Unit Tests / Torch Backend Tests (push) Successful in 3m45s
Deploy Docs / deploy (push) Successful in 3m55s
Unit Tests / hcq2 (push) Failing after 4m15s
Unit Tests / Linters (push) Successful in 4m19s
Unit Tests / Models (push) Successful in 4m54s
Unit Tests / Linux (DSP) (push) Successful in 5m17s
Unit Tests / CL IMAGE Tests (push) Successful in 5m24s
Unit Tests / Linux (DEV=CPU:X86) (push) Successful in 5m34s
Unit Tests / Docs (push) Successful in 5m43s
Unit Tests / AMD ASM IDE (push) Successful in 5m47s
Unit Tests / SPEC=2 (2) (push) Successful in 6m5s
Unit Tests / Compile-only (DEV=NULL:NAK:sm_120) (push) Successful in 1m50s
Unit Tests / Linux (DEV=CPU:LLVM) (push) Successful in 6m8s
Unit Tests / Linux (DEV=CPU:LVP) (push) Successful in 6m11s
Unit Tests / Compile-only (DEV=NULL:IR3:a630) (push) Successful in 2m22s
Unit Tests / Torch Backend Training (push) Successful in 6m24s
Unit Tests / Linux (DEV=WEBGPU) (push) Successful in 6m29s
Unit Tests / SPEC=2 (1) (push) Successful in 6m33s
Unit Tests / Unit Tests (push) Successful in 6m39s
Unit Tests / Linux (amdllvm gfx1201) (push) Successful in 5m43s
Unit Tests / Null Tests (push) Successful in 6m42s
Unit Tests / Linux (DEV=CL) (push) Successful in 6m44s
Unit Tests / Linux (amdllvm gfx1100) (push) Successful in 6m44s
Unit Tests / Linux (DEV=CPU:CLANG) (push) Successful in 6m52s
Unit Tests / openpilot Compile Tests (push) Successful in 7m4s
Unit Tests / Linux (amd gfx1100) (push) Successful in 7m14s
Unit Tests / Linux (ptx) (push) Successful in 3m34s
Unit Tests / Linux (amd gfx1201) (push) Successful in 7m19s
Unit Tests / Linux (amdllvm gfx950) (push) Successful in 3m54s
Unit Tests / Linux (am) (push) Successful in 7m32s
Unit Tests / Optimization Tests (push) Successful in 7m53s
Unit Tests / Linux (nv) (push) Successful in 4m50s
Unit Tests / Linux (amd gfx950) (push) Successful in 5m21s
Unit Tests / Compile-only (DEV=NULL:QCOMCL:a630) (push) Successful in 4m31s
Unit Tests / ONNX (CPU) Tests (push) Successful in 9m57s
Autogen / In-tree Autogen (push) Successful in 11m57s
Autogen / In-tree Autogen (macos) (push) Canceled after 0s
Benchmarks / Mac pytest (push) Canceled after 0s
Benchmarks / LLM (DEV=AMD) (push) Canceled after 0s
Benchmarks / LLM (DEV=METAL) (push) Canceled after 0s
Benchmarks / LLM (DEV=NV) (push) Canceled after 0s
Benchmarks / HLB-CIFAR10 (DEV=AMD) (push) Canceled after 0s
Benchmarks / HLB-CIFAR10 (DEV=METAL) (push) Canceled after 0s
Benchmarks / HLB-CIFAR10 (DEV=NV) (push) Canceled after 0s
Benchmarks / MLPerf (AMD) (push) Canceled after 0s
Benchmarks / MLPerf (NV) (push) Canceled after 0s
Benchmarks / Stable Diffusion (DEV=AMD) (push) Canceled after 0s
Benchmarks / Stable Diffusion (DEV=METAL) (push) Canceled after 0s
Benchmarks / Stable Diffusion (DEV=NV) (push) Canceled after 0s
Benchmarks / Tests (DEV=AMD) (push) Canceled after 0s
Benchmarks / Tests (DEV=METAL) (push) Canceled after 0s
Benchmarks / Tests (DEV=NV) (push) Canceled after 0s
Benchmarks / UsbGPU Benchmark (push) Canceled after 0s
Benchmarks / comma Benchmark (0.11.2) (push) Canceled after 0s
Benchmarks / comma Benchmark (0.11.0) (push) Canceled after 0s
Benchmarks / DSP Benchmark (push) Canceled after 0s
Benchmarks / UsbGPU Benchmark (comma) (push) Canceled after 0s
Benchmarks / PCI Driver Benchmark (DEV=AMD) (push) Canceled after 0s
Benchmarks / PCI Driver Benchmark (DEV=NV) (push) Canceled after 0s
Benchmarks / LLVM Speed (push) Canceled after 0s
Platform Tests / MacOS (unit) (push) Canceled after 0s
Platform Tests / MacOS (unit, mock) (push) Canceled after 0s
Platform Tests / MacOS (DEV=METAL) (1) (push) Canceled after 0s
Platform Tests / MacOS (DEV=METAL) (2) (push) Canceled after 0s
Platform Tests / MacOS (DEV=CPU:CLANG) (push) Canceled after 0s
Platform Tests / MacOS (DEV=CPU:LLVM) (push) Canceled after 0s
Platform Tests / MacOS (DEV=CPU:LVP) (push) Canceled after 0s
Platform Tests / MacOS (DEV=WEBGPU) (push) Canceled after 0s
Platform Tests / Windows (DEV=CPU:CLANG) (push) Canceled after 0s
Platform Tests / Windows (DEV=CPU:LLVM) (push) Canceled after 0s
Platform Tests / Windows (DEV=CPU:X86) (push) Canceled after 0s
Platform Tests / Windows (DEV=WEBGPU) (push) Canceled after 0s
hcq2: one submitter (#17556)
* hcq2: c submitter

* x

* x

* x

* simpler

* simpler

* x

* x

* Dx

* revrt

* Dx

* x

* fst

* fix
2026-08-17 16:08:19 +03:00

150 lines
6.6 KiB
Python

import os, time, struct, functools, unittest
from dataclasses import replace
from typing import Any, Callable
import numpy as np
from tinygrad import Tensor, dtypes, Device
from tinygrad.uop.ops import UOp, Ops, KernelInfo
from tinygrad.tensor import _to_np_dtype
from tinygrad.codegen import to_program
from tinygrad.dtype import DType, truncate
from tinygrad.nn.state import get_parameters
from tinygrad.helpers import T, Target, DEV, DEBUG, Context, GlobalCounters
from tinygrad.renderer import Renderer
from tinygrad.codegen import full_rewrite_to_sink, line_rewrite, pm_linearize_cleanups
from tinygrad.codegen.late.linearizer import linearize
from tinygrad.engine.realize import compile_linear
# decorator to skip slow tests by default, run with RUN_SLOW=1 to include them
slow = unittest.skipUnless(os.getenv("RUN_SLOW"), "slow test, set RUN_SLOW=1 to run")
from tinygrad.runtime.ops_python import PythonRenderer
def full_rewrite(sink:UOp, ren:Renderer|None=None) -> UOp:
if ren is None: ren = Renderer(Target())
if sink.arg is None: sink = sink.replace(arg=KernelInfo())
return full_rewrite_to_sink(sink, ren, optimize=sink.tag is None)
def get_uops(sink:UOp, ren:Renderer|None=None) -> list[UOp]:
"""Extract linearized UOps from a sink. Test helper that only does linearization (no render)."""
full_sink = full_rewrite(sink, ren)
return line_rewrite(linearize(full_sink), pm_linearize_cleanups)
def replace_opts(ast:UOp, opts:list) -> UOp: return ast.replace(arg=replace(ast.arg, opts_to_apply=tuple(opts)))
def derandomize_model(model):
for p in get_parameters(model):
p.replace(Tensor.empty(p.shape, device=p.device, dtype=p.dtype))
p.realize()
class KernelCountException(Exception):
def __init__(self, expected:int, got:int):
self.expected, self.got = expected, got
super().__init__(f"expected {expected}, got {got}")
def check_schedule(t:Tensor|list[Tensor]|UOp, allowed:int, to_prerealize:list[Tensor]|None=None, filter_sink=True):
if to_prerealize:
with Context(DEBUG=0, TRACK_MATCH_STATS=0): Tensor.realize(*to_prerealize)
if isinstance(t, Tensor): linear, var_vals = t.linear_with_vars()
elif isinstance(t, list) and isinstance(t[0], Tensor): linear, var_vals = Tensor.linear_with_vars(*t)
else:
assert isinstance(t, UOp), f"can't schedule {t}"
linear, var_vals = Tensor(t).linear_with_vars()
# test compiling the linear
compile_linear(linear)
kernel_cnt = sum((len(call.device) if isinstance(call.device, tuple) else 1)
for call in linear.src if call.src[0].op is Ops.SINK or not filter_sink)
if kernel_cnt != allowed:
print(f"SCHEDULE ISSUE, expecting {allowed} got {kernel_cnt}")
if DEBUG >= 3:
for i,call in enumerate(linear.src):
print("kernel", i+1)
print(call.src[0])
raise KernelCountException(allowed, kernel_cnt)
return linear, var_vals
def assert_kernel_count(expected:int):
got = GlobalCounters.kernel_count
if got != expected: raise KernelCountException(expected, got)
def call_is_graph(call:UOp) -> bool:
ast = call.src[0]
return ast.op is Ops.CUSTOM_FUNCTION and ast.arg == "graph"
def call_is_hcq(call:UOp) -> bool:
ast = call.src[0]
return ast.op is Ops.CUSTOM_FUNCTION and ast.arg == "hcq"
def jit_cache_count(linear:UOp) -> int:
n = 0
for call in linear.src:
ast = call.src[0]
if ast.op is Ops.CUSTOM_FUNCTION and ast.arg == "graph": n += jit_cache_count(ast.src[0])
else: n += 1
return n
def assert_jit_cache_len(fxn, expected_len):
linear = fxn.captured.linear if fxn.captured is not None else None
if linear is None or not linear.src:
if expected_len != 0: raise KernelCountException(expected_len, 0)
return
if expected_len and all(call_is_hcq(call) for call in linear.src): # HCQ2: one batch submitter, or fence + reset + merged calls + finalizer
from tinygrad.runtime.support.hcq2 import HCQ_RUNTIME_DEV
expected_len = 1 if HCQ_RUNTIME_DEV.value == "CPU" else 4
if call_is_graph(linear.src[0]):
if len(linear.src) != 1: raise KernelCountException(1, len(linear.src))
inner = linear.src[0].src[0].src[0] # LINEAR UOp inside CUSTOM_FUNCTION
if len(inner.src) != expected_len: raise KernelCountException(expected_len, len(inner.src))
else:
if len(linear.src) != expected_len: raise KernelCountException(expected_len, len(linear.src))
def min_normal(dt:DType) -> float: return 2.0 ** (2 - (1 << (dtypes.finfo(dt)[0] - 1)))
def rand_for_dtype(dt:DType, size:int, allow_subnormal=True):
if dtypes.is_unsigned(dt):
return np.random.randint(0, 100, size=size, dtype=_to_np_dtype(dt))
elif dtypes.is_int(dt):
return np.random.randint(-100, 100, size=size, dtype=_to_np_dtype(dt))
elif dt == dtypes.bool:
return np.random.choice([True, False], size=size)
ret = np.random.uniform(-10, 10, size=size).astype(_to_np_dtype(dt))
if dt == dtypes.bfloat16 or dt in dtypes.fp8s: ret = np.array([truncate[dt](x) for x in ret], dtype=ret.dtype)
if not allow_subnormal: ret = np.where(np.abs(ret) < min_normal(dt), 0, ret)
return ret
def timeit(fxn:Callable[..., T], *args, **kwargs) -> tuple[T, float]:
st = time.perf_counter_ns()
ret = fxn(*args, **kwargs)
return ret, (time.perf_counter_ns()-st)*1e-6
def eval_uop(uop:UOp, inputs:list[tuple[DType, list[Any]]]|None=None, vals:tuple[int, ...]=()):
dev = Device['PYTHON']
allocator = dev.allocator
bufs = []
for buf_dt, data in inputs or []:
bufs.append(buf:=allocator.alloc(len(data) * buf_dt.itemsize))
allocator._copyin(buf, memoryview(struct.pack(str(len(data)) + (buf_dt.fmt or ""), *data)))
g = UOp.param(0, uop.dtype, (1,))
prg = to_program(UOp.store(g.index(UOp.const(0)), uop).sink(arg=KernelInfo()), PythonRenderer(Target("PYTHON")))
prog = dev.runtime(prg.to_elf())
prog(out_buf:=allocator.alloc(uop.dtype.itemsize), *bufs, vals=vals)
return out_buf.cast(uop.dtype.fmt or "").tolist()[0]
def to_uops_list(u:list[UOp], ren=None) -> list[UOp]:
sink = UOp.group(*u)
for r in sink.ranges: sink = sink.end(r)
ret = get_uops(sink.sink(arg=KernelInfo(opts_to_apply=())), ren)
assert ret[-1].op is Ops.SINK
return ret
def not_support_multi_device():
# CL and CUDA don't support multi device if in CI
return (Device.DEFAULT == "CL" and Device[Device.DEFAULT].count() < 2) or (Device.DEFAULT == "CUDA" and DEV.interface.startswith("MOCK"))
def needs_second_gpu(fn):
@functools.wraps(fn)
def wrapper(self, *args, **kwargs):
# check if there's a second GPU, if not, skip multi tests
try: Tensor.zeros(10, device=f"{Device.DEFAULT}:1").contiguous().realize()
except Exception as e: self.skipTest(f"second device not available: {e}")
return fn(self, *args, **kwargs)
return wrapper