metakernel / CARD.md
phanerozoic's picture
Card: standardized form with hero
db7534e verified
|
Raw
History Blame
7.54 kB
metadata
library_name: kernels
license: apache-2.0

metakernel

The measuring instrument for the kernel-design loop, packaged as a kernel and loadable through kernels: trustworthy timing, adversarial correctness comparison, and measured facts about the device. The reference standard is the suite of measurement invariants any correctly functioning device must satisfy, certified on multiple architectures.

An agent iterating on CUDA candidates is good at writing code and bad at trusting its own measurements. It needs three things it cannot reliably improvise: timing that rejects thermal throttling, comparison that distinguishes real bugs from legitimate reduction-order noise, and device numbers that were measured rather than copied from a spec sheet. metakernel ships those as loadable ops that run anywhere get_kernel runs, including headless CI where Nsight and CUPTI are unavailable, which is exactly where agent loops live.

A roofline plot draws itself from a live device probe: the bandwidth diagonal, five measured compute roofs, and a real GEMM plotting onto it

The dossier drawing its own roofline, every line measured live by probe kernels: the 790 GB/s DRAM diagonal, compute roofs from fp64's 1.2 TF to int8's 715 TOP/s, the dependent-load latency ladder from 30 shared-memory cycles to 666 at DRAM, and a real fp16 GEMM plotting itself at its measured 116 TF with throttled samples rejected from the median.

Usage

from kernels import get_kernel
mk = get_kernel("phanerozoic/metakernel", version=1, trust_remote_code=True)

dossier = mk.probe_device()                          # measured device facts
report  = mk.bench(lambda: cand.op(x), iters=200,    # throttle-rejected medians
                   bytes=B, flops=F, dossier=dossier)
verdict = mk.compare(ref_op, cand_op, gen=make_inputs)   # pass/fail with ULP evidence
table   = mk.sweep(factory, {"BLOCK": [64, 128, 256]})   # config search

Every op returns plain dicts and tensors with fixed schemas, never prose, so an agent parses results instead of scraping stdout. version selects the release branch; trust_remote_code is required by kernels for publishers without the trusted-publisher mark.

API

Symbol Purpose
probe_device(quick=False) empirical dossier: DRAM/L2/shared/transfer bandwidth, pointer-chase latencies, FMA and per-dtype MMA rates, atomic contention curve, launch overhead, grid-barrier cost, occupancy tables, clock under load
bench(fn, iters, bytes, flops, dossier, dtype, graph, clock_stride) cudaEvent bracketing; median with CI; rejection of samples whose SM clock sagged; achieved GB/s and TFLOP/s; roofline placement; CUDA-graph capture for microsecond kernels
compare(ref, cand, gen, order_shuffle, atol, rtol, zero_atol) max/mean ULP, log2 ULP histogram, first divergent index, NaN/Inf census; with an order shuffle every element is judged against its own pointwise reduction-order band; carries worst_elements for debugging
order_shuffles.last_dim() / .matmul_k() built-in shuffles for the common contractual-noise axes
fuzz_shapes(op, ref, make, dtypes, isolate) the ugly envelope: 0-d to 3-d and zero-size shapes, non-tile-multiple sizes, transposed and strided views, misaligned slices, 2^31 logical-element expansion; per-case repro recipes; isolate=True survives context-killing candidates
sweep(factory, param_grid, check, budget_s, race) launch-config search with a correctness gate per row so a fast wrong config cannot win; successive halving with pruned points visible
alloc_stamps / read_stamps / stamped_demo clock64 phase stamps around agent-marked kernel phases
dossier_drift(current, pinned, rel_tol) / pinned_dossiers() drift of fresh measurements against the release-pinned dossier per architecture
mma_tile_check(trials) random integer tiles through the wmma fragment path, compared exactly against the reference GEMM
measure_clock() / ulp_diff(a, b) the throttle primitive; elementwise ULP distance
ops.mk_* the raw probe kernels

Method

Each dossier entry is produced by a dedicated probe kernel: streaming triads and read/write/gather kernels for bandwidth, Sattolo-cycle pointer chases for latency, register-resident FMA chains and register-fragment mma_sync loops for compute, an atomic hammer swept over distinct-address counts, empty-launch trains, and a cooperative-groups kernel for grid-barrier cost. Every number carries the SM clock it was measured under; bench probes the clock and rejects samples from sagged windows, reporting the count. The comparison ops treat the reference as a distribution: an order shuffle over contractual-noise dimensions bounds the legitimate numerical band, applied pointwise so a uniformly wrong candidate cannot hide behind one order-sensitive element.

Measured

Release-pinned dossier for RTX 6000 Ada (sm89, 142 SMs, 96 MB L2, ECC on):

entry value
clock under sustained FMA load 2.71 GHz max, 0.3% sag over 24 windows
device-memory bandwidth triad 638-705 GB/s; read-only 771; write-only 767; random 16 B gather 218
L2 / shared-memory bandwidth 9,325 GB/s / 21,250 GB/s aggregate
host transfers H2D 24.0 pinned; D2H 26.2; D2D 331 GB/s
dependent-load latency smem 30.0 cy; L1 45.8; L2 292; DRAM 649
FMA pipes f32 90.9 TFLOP/s; f64 1.28 TFLOP/s
MMA sustained (accumulator-verified) fp16 376, bf16 366, tf32 177, int8 770 TOP/s, 2:4-sparse fp16 713; fp8 194 as a flagged lower bound
atomics fp32 curve 0.72 Gop/s at 1 address to 484 at one per thread
launch overhead / grid barrier 5.6 us queued, 14.1 round trip / 0.54 us per grid.sync

A second pinned dossier covers GeForce RTX 3070 Ti Laptop (sm86). MMA flops derive from accumulator read-back with every fragment element observed; mma_tile_check reproduces the reference GEMM exactly through the same fragment path.

Certification

The test suite asserts invariants that must hold on any correctly functioning device: L2 exceeds DRAM bandwidth and random gather costs more than streaming; latencies order smem < L1 < L2 < DRAM; tensor-core rates beat the FMA pipe and hold the silicon's structural ratios; a large cuBLAS GEMM lands within [0.30, 1.05] of the dossier fp16 rate; compare passes reordered reductions and fails corrupted candidates through both routes; fuzz_shapes catches a contiguity-cheating op and reports the 2^31 case as run or skipped, never silently; the chase probe repeats within 20%.

Requirements and limits

  • No hardware counters: everything is inferred from timing, clocks, and the occupancy API, so entries carry a confidence field and timing-differential inference can misattribute.
  • Single device, single tenant: contention surfaces as rejected samples, not errors. launch_overhead includes torch dispatch.
  • MMA numbers are dense-tile register rates with no memory traffic, an upper bound. In-process fuzz_shapes cannot survive a context-killing candidate; isolate=True can, at a torch startup per child.
  • Published variants are Linux x86_64; on Windows load_local.py JIT-builds the same source.

References

Williams, Waterman, Patterson, "Roofline: An Insightful Visual Performance Model" (2009); Sattolo's algorithm for single-cycle pointer chases; the occupancy API and cudaEvent timing model.

License

Apache-2.0.