Personalize this lesson
Adapt explanations and teaching visuals to your background and preferred voice.
Suppose an AI coding agent generates a CUDA extension that clears its visible smoke test and reports an eye-popping 1.4x speedup on an H100 GPU. The pull request looks clean, the pull request comments celebrate the win, and the kernel merges into main. Two days later in staging, inference worker threads hang indefinitely, customer prompts with 1009 tokens trigger silent NaN outputs, and uncoalesced memory reads drop real memory bandwidth across the cluster from 3.35 TB/s down to 120 GB/s.
During post-mortem debugging, engineers discover the root cause: the model generated a single specialized branch for the exact public test shape [2, 4096]. Every non-standard row length triggered an out-of-bounds shared memory read, and a missing barrier created a race condition that passed the unit test only because thread warps ran in lockstep on an idle GPU.
Generated GPU code isn't an implementation; it's an untrusted proposal. A language model predicts token sequences based on open-source patterns rather than executing hardware instructions or reasoning about memory controllers, thread divergence, and cache lines. Promoting generated code into a production library requires undeniable empirical evidence: the candidate must preserve mathematical semantics across its full domain, execute safely without memory corruption, beat a comparable baseline fairly, and roll back instantly when production workloads disagree with lab benchmarks.
The GPU Runtime Execution Lab made host submission, device streams, static storage, fallback paths, and timing scopes explicit. Generated-kernel engineering takes ownership one layer lower: prove that the candidate symbol behind that dispatch computes the correct operator safely before the runtime ever replays or promotes it.
One realistic operator carries this process throughout the chapter: weighted root mean square normalization (RMSNorm), weighted_rmsnorm(x, weight, eps). It rescales each row across its last dimension and applies a learned feature weight. For an example row [3.0, 4.0], the mean square is . Divide each entry by , then multiply by its corresponding weight. The positive scalar ensures an all-zero row never divides by zero.
For row index , feature index , and row width :
The reference implementation is pure PyTorch. A candidate may use CUDA, Triton, or compiler code. The promotion gates stay identical. The executable examples below run on CPU: they test evaluator logic, proving how to audit a candidate before giving it device access.
AI kernel generation dynamics and common failure modes
LLMs generate CUDA and Triton by pattern-matching code patterns from open-source repositories like FlashAttention and PyTorch. They can reproduce idiomatic launch grids, shared memory declarations, and warp-reduction syntax effortlessly. Yet that high syntactic fluency hides lethal semantic blind spots: models struggle with spatial coordinate transforms, thread-block boundary conditions, and hardware memory hierarchies.
Three failure modes recur across generated GPU kernels:
- Subtle race conditions and missing barriers: In reduction operators like RMSNorm, threads compute partial sums and exchange them through shared memory (
smem). LLMs regularly omit__syncthreads()in CUDA or block-level barriers in Triton between write and read stages, assuming warp-synchronous execution or implicit ordering. On a small test tensor where warps run in lockstep across a single Streaming Multiprocessor (SM), the test passes reliably. In production, with 132 SMs executing asynchronous warps under dynamic clock frequency scaling, the kernel suffers Read-After-Write (RAW) data hazards, corrupting outputs non-deterministically. - Out-of-bounds shared memory indexing: Block tile sizes (such as 128 or 256 threads) rarely divide real-world tensor dimensions cleanly. When a sequence length or hidden dimension is prime (such as ), edge tiles must mask out inactive threads. LLMs often guard global memory reads with
if (idx < H), but forget to mask the shared memory store or fail to clear reduction padding. Uninitialized shared memory floats get summed into the reduction tree, quietly poisoning the denominator. - Uncoalesced memory access passing small tests by luck: Models frequently confuse column-major and row-major layout indexing, swapping
threadIdx.xandthreadIdx.yor indexing across rows instead of along contiguous row elements. On a tiny smoke test (such as floats), the entire tensor fits inside a single 128-byte cache line; the test reports a false speedup because there's no memory latency penalty. Under production batching (such as batch 64, sequence length 4096, hidden dim 8192), non-consecutive addresses force the memory controller to issue 32 distinct 32-byte sector transactions instead of one coalesced 128-byte transaction. Effective memory bandwidth plummets from 3.35 TB/s down to 120 GB/s.
Treating generated code as untrusted build input protects your cluster from these hidden defects.
Write the operator contract before the prompt
Prompt engineering can't repair an underspecified operation. A code generator needs both the exact mathematical formula and the library contract surrounding it. PyTorch custom operators declare mutation, aliasing, and schemas via torch.library.custom_op, while torch.library.opcheck verifies registration, fake-tensor integration, and compilation mechanics rather than numerical correctness.[1] Treat those as distinct obligations.
Here is the contract for the running operator:
| Contract axis | weighted_rmsnorm requirement | Rejection example |
|---|---|---|
| Shape | x has shape [..., H], H > 0; empty outer dimensions are valid; weight has shape [H]; output shape matches x | Candidate assumes batch is 2 or H is 4096 |
| Dtype | x and weight share float16, bfloat16, or float32; low-precision reduction accumulates in float32 | Candidate sums squares in float16 |
| Stride | Any non-overlapping strided x and weight accepted; unsupported fast-path layouts route to reference | Candidate reads tensors as contiguous without checking |
| Device | Both tensors on same CUDA device; CPU path routes to reference implementation | Candidate copies through host or mismatched device |
| Aliasing | Functional operation returns fresh output and leaves inputs unchanged | Candidate overwrites x through borrowed pointer |
| Autograd | Fast path is inference-only; active autograd routes to differentiable reference | Candidate silently detaches tensors needing gradients |
| Scalar | eps is a numeric scalar staying finite and strictly positive in FP32 | A tiny positive value rounds to zero in reduction dtype |
| Numerics | Match reference within dtype-specific tolerances; NaNs match positions and signed infinities match | Candidate passes only finite, unit-scale random values |
| Errors | Wrapper rejects invalid shape, dtype, device, or eps under versioned error contract | Candidate silently casts or truncates values |
The dispatch predicate is an active gate in the contract. Suppose the first generated kernel supports CUDA, contiguous x and weight, H divisible by 128, and all three dtypes. The wrapper must verify those conditions, check the target GPU architecture, and confirm that backward autograd isn't needed; any other valid call routes to the reference. Invalid public inputs must still raise the declared library error. A fast-path restriction is acceptable; an unannounced semantic limitation isn't.
A contiguous last dimension alone doesn't justify flattening rows: sliced outer dimensions leave gaps between them. Either compute row addresses from strides or require the entire input tensor to be contiguous. Active autograd requires both torch.is_grad_enabled() and at least one input tensor with requires_grad=True.
Use a prompt specification that exposes obligations without leaking private evaluation fixtures:
1Implement weighted_rmsnorm(x, weight, eps) for the declared CUDA fast path.
2
3Semantics:
4 xf, wf = float32(x), float32(weight)
5 y = (xf * rsqrt(mean(xf ** 2, dim=-1, keepdim=True) + float32(eps))) * wf
6 cast y back to x.dtype
7
8Contract:
9 x: [..., H], weight: [H], same supported floating dtype and CUDA device
10 return fresh output; never mutate or alias x or weight
11 wrapper dispatches unsupported shapes or strides to reference
12 wrapper uses differentiable reference when active autograd needs a backward path
13
14Deliver:
15 source, build command, dispatch predicate, claimed hardware target,
16 correctness command, sanitizer command, benchmark command, and known limits
17
18Forbidden:
19 input-value lookup tables, incorrect shape branches, host callbacks,
20 network access, and changes outside isolated build directoryExact evaluation shapes and adversarial values stay outside the model context. Structural rules remain visible so the generator implements the intended program rather than guessing benchmark inputs.
What must a reviewer be able to state before generation begins?
Answer
A reviewer must state the accepted shapes, dtypes, strides, devices, aliasing, error behavior, numerical policy, and fallback predicate without reading the candidate. If an axis is unclear, the contract isn't frozen.
Isolate generated code and the toolchain
Generated kernel source is untrusted code. Compiling it invokes preprocessors, linkers, build scripts, dynamic linkers, and shell hooks. Run the compiler and generated binaries in a disposable sandbox with a pinned toolchain image, no credentials, no network access, tight CPU and memory limits, a wall-clock timeout, and a single writable build directory. Expose only public smoke fixtures there. An external orchestrator calls the model provider without exposing API keys to the build worker. Allow-list compiler commands and artifact types. Keep the evaluator, hidden fixtures, promotion registry, and production codebase completely outside the sandbox.
Device execution requires a second security boundary. Running untrusted binaries on a shared GPU worker risks memory snooping, kernel hangs, and driver crashes that destabilize co-located workloads. Execute tests on an isolated, short-lived GPU worker with no production traffic. Expose only evaluator-allocated input and output buffers, kill the worker process on timeout or illegal memory access, and reset or quarantine the device before reuse. A host container doesn't prevent arbitrary device code from executing illegal instructions or exhausting GPU resources. The compiler sandbox limits host-side build capabilities; the disposable GPU worker isolates hardware faults.
These boundaries mirror secure code-generation agent architectures: model output receives only the capabilities required for its task, avoiding ambient authority over the repository or secrets. Record every tool call, compiler invocation, exit code, and artifact hash. Reject attempts to modify the harness, reference, timing harness, or test suites.
Catch a candidate that only handles the visible shape
A minimal evaluator demonstrates incomplete domain coverage immediately. The CPU example below inspects a deliberately flawed candidate that computes the operator for the public contiguous 2 x 4 float32 shape, but returns zeros for any other input.
1import torch
2
3def reference(x: torch.Tensor, weight: torch.Tensor, eps: float) -> torch.Tensor:
4 mean_square = x.float().square().mean(dim=-1, keepdim=True)
5 normalized = x.float() * torch.rsqrt(mean_square + eps)
6 return (normalized * weight.float()).to(x.dtype)
7
8def bad_candidate(x: torch.Tensor, weight: torch.Tensor, eps: float) -> torch.Tensor:
9 public_shape = tuple(x.shape) == (2, 4)
10 if public_shape and x.is_contiguous() and x.dtype == torch.float32:
11 mean_square = x.square().mean(dim=-1, keepdim=True)
12 return x * torch.rsqrt(mean_square + eps) * weight
13 return torch.zeros_like(x)
14
15def check(name: str, x: torch.Tensor, weight: torch.Tensor) -> bool:
16 expected = reference(x, weight, 1e-5)
17 actual = bad_candidate(x, weight, 1e-5)
18 try:
19 torch.testing.assert_close(actual, expected, rtol=1e-5, atol=1e-6)
20 passed = True
21 except AssertionError:
22 passed = False
23 disp = "PASS" if passed else "FAIL"
24 print(f"{name}: {disp}")
25 return passed
26
27base = torch.tensor(
28 [[0.5, -1.0, 2.0, -0.25], [3.0, 0.25, -2.0, 1.0]],
29 dtype=torch.float32,
30)
31weight4 = torch.tensor([1.0, 0.5, -0.75, 2.0])
32cases = [
33 ("visible-contiguous-2x4", base, weight4),
34 ("post-freeze-scale-large", base * 3.0, weight4),
35 ("post-freeze-scale-small", base * 0.01, weight4),
36 ("post-freeze-negated", -base, weight4),
37 ("hidden-shape-3x5", torch.arange(15.0).reshape(3, 5) + 0.5, torch.ones(5)),
38 ("hidden-noncontiguous-2x4", torch.arange(8.0).reshape(4, 2).t() + 0.5, weight4),
39]
40
41assert cases[-1][1].stride() == (1, 2)
42passed = [check(name, x, weight) for name, x, weight in cases]
43assert passed == [True, True, True, True, False, False]
44disp = "PROMOTE" if all(passed) else "REJECT"
45print("candidate disposition:", disp)1visible-contiguous-2x4: PASS
2post-freeze-scale-large: PASS
3post-freeze-scale-small: PASS
4post-freeze-negated: PASS
5hidden-shape-3x5: FAIL
6hidden-noncontiguous-2x4: FAIL
7candidate disposition: REJECTScaling and negation preserve tensor shape, so the candidate's hardcoded branch still passes them. The new shape and transposed view expose the missing domain. Shape specialization is acceptable when a wrapper routes unsupported calls to a verified fallback. Returning zeros for unhandled inputs violates the operator contract.
The autonomous evaluation harness: six sequential gates
An autonomous evaluation harness subjects candidate GPU code to a battery of deterministic gates. Skipping early gates to run benchmarks wastes GPU compute on broken code. The pipeline enforces six sequential checks:

1. Reference oracle
The reference oracle defines functional ground truth. Written in pure PyTorch, it enforces the formal operator schema, checks input metadata, and produces the baseline output tensor. It operates with full precision accumulation (FP32) to prevent precision loss.
2. Compilation check and static inspection
Compiling with nvcc -O3 and target architecture flags (such as -arch=sm_90a for NVIDIA H100) produces diagnostic logs from ptxas, the PTX optimizing assembler.[2] Static inspection extracts three critical metrics:
- Register allocation and spills: Inspect the
ptxasoutput string (e.g.,ptxas info : Used 64 registers, 0 bytes cmem, 1024 bytes spill stores, 1024 bytes spill loads). If a thread requires more registers than the hardware allows per warp,ptxasspills variables into local memory (backed by high-latency DRAM), cratering execution speed. - Shared memory allocation: High shared memory usage per thread block reduces active warp occupancy per SM. For instance, requesting 64 KB of shared memory on an SM with a 99 KB capacity limits concurrency to one block per SM.
- Symbol verification: Tools like
cuobjdumpandnvdisasmconfirm that the compiled.cubincontains the declared symbol rather than falling back to host PyTorch routines or embedding precomputed constant tables.[3]
3. Multi-scale numerical verification
A candidate that passes on powers of two can fail on boundary conditions. Test families must probe diverse dimensions and memory alignments:
- Powers of two: Shapes like test aligned, coalesced memory access paths.
- Prime row lengths: Odd and prime dimensions like test edge-tile boundary masks and thread reduction cleanup loops.
- Non-contiguous views and ragged strides: Transposed matrices (
x.t()), strided slices, and non-zero storage offsets test pointer arithmetic. - Adversarial floating-point inputs: Zeros, subnormals, numbers near overflow ( squaring to infinity in FP32), and exact NaN or infinity placements verify compliance with IEEE 754 standards.
Componentwise numerical acceptance requires a declared formula:
PyTorch's torch.testing.assert_close implements this rule and checks that NaNs match at identical positions.[4] Choose tolerances based on operator mathematics and reduction length. Reporting maximum absolute error, maximum relative error, and failing element counts prevents an aggregate pass from hiding localized divergence.
The script below audits input preservation, memory aliasing, and non-finite policies:
1import math
2import torch
3
4def reference(x, weight, eps):
5 if x.layout != torch.strided or weight.layout != torch.strided:
6 raise ValueError("Need ordinary strided tensors.")
7 if x.ndim < 1 or x.shape[-1] <= 0 or weight.shape != (x.shape[-1],):
8 raise ValueError("Need x[..., H], H > 0, and weight[H].")
9 if x.dtype not in (torch.float16, torch.bfloat16, torch.float32) or weight.dtype != x.dtype:
10 raise ValueError("Need the same supported floating dtype.")
11 if x.device != weight.device or x.device.type not in ("cpu", "cuda"):
12 raise ValueError("Need one supported device.")
13 if type(eps) not in (float, int):
14 raise ValueError("eps must be an ordinary numeric scalar.")
15 try:
16 eps_value = float(eps)
17 except OverflowError as exc:
18 raise ValueError("eps is too large.") from exc
19 if not math.isfinite(eps_value) or eps_value <= 0:
20 raise ValueError("eps must be finite and positive.")
21 eps32 = float(torch.tensor(eps_value, dtype=torch.float32))
22 if not math.isfinite(eps32) or eps32 <= 0:
23 raise ValueError("eps must stay finite and positive in FP32.")
24 with torch.autocast(device_type=x.device.type, enabled=False):
25 xf, wf = x.float(), weight.float()
26 scale = torch.rsqrt(xf.square().mean(dim=-1, keepdim=True) + eps32)
27 return ((xf * scale) * wf).to(x.dtype)
28
29def value_bytes(tensor):
30 flat = torch.empty(tensor.numel(), dtype=tensor.dtype, device=tensor.device)
31 flat.copy_(tensor.detach().reshape(-1))
32 return flat.view(torch.uint8)
33
34def audit(candidate, x, weight, eps=1e-5):
35 expected = reference(x, weight, eps)
36 snapshots = [value_bytes(t) for t in (x, weight)]
37 def metadata(t):
38 return (t.shape, t.stride(), t.storage_offset(), t.dtype, t.device,
39 t.untyped_storage().data_ptr())
40 before_metadata = [metadata(t) for t in (x, weight)]
41 actual = candidate(x, weight, eps)
42 try:
43 assert isinstance(actual, torch.Tensor)
44 torch.testing.assert_close(actual, expected, rtol=1e-5, atol=1e-6, equal_nan=True)
45 for current, before, original_meta in zip((x, weight), snapshots, before_metadata, strict=True):
46 assert metadata(current) == original_meta, "input metadata changed"
47 assert torch.equal(value_bytes(current), before), "input mutated"
48 if actual.numel() and current.numel():
49 assert actual.untyped_storage().data_ptr() != current.untyped_storage().data_ptr(), "output aliases input"
50 except AssertionError:
51 return False
52 return True
53
54def mutate_after_computing(x, weight, eps):
55 y = reference(x, weight, eps)
56 x.add_(1)
57 return y
58
59def scrub_nans(x, weight, eps):
60 return reference(x, weight, eps).nan_to_num()
61
62base = torch.tensor([[3., 4.], [0., 0.]])
63weight = torch.tensor([1., 2.])
64special = torch.tensor([[float("nan"), 1.], [float("inf"), 2.]])
65cases = [
66 ("reference ordinary", reference, base.clone(), weight),
67 ("reference empty outer dimension", reference, torch.empty(0, 2), weight),
68 ("reference non-finite policy", reference, special, weight),
69 ("correct values but mutated input", mutate_after_computing, base.clone(), weight),
70 ("aliased zero output", lambda x, w, e: x, torch.zeros(1, 2), weight),
71 ("wrong output dtype", lambda x, w, e: reference(x, w, e).double(), base, weight),
72 ("silently replaced NaNs", scrub_nans, special, weight),
73]
74results = [audit(fn, x, w) for _, fn, x, w in cases]
75assert results == [True, True, True, False, False, False, False]
76for (name, *_), passed in zip(cases, results, strict=True):
77 disp = "PASS" if passed else "FAIL"
78 print(f"{name}: {disp}")1reference ordinary: PASS
2reference empty outer dimension: PASS
3reference non-finite policy: PASS
4correct values but mutated input: FAIL
5aliased zero output: FAIL
6wrong output dtype: FAIL
7silently replaced NaNs: FAILChecking dense tensor values, input mutation, and pointer aliasing catches bugs before device timing runs.
4. Compute Sanitizer gating
Numerical tests don't reveal undefined behavior that survived by luck. NVIDIA Compute Sanitizer isolates execution hazards into four dedicated tools:[5]
memcheck: Detects out-of-bounds memory accesses, misaligned addresses, and device heap errors.racecheck: Intercepts shared memory hazards, including Read-After-Write (RAW), Write-After-Read (WAR), and Write-After-Write (WAW) data races.initcheck: Flags reads from uninitialized global or shared device memory.synccheck: Identifies divergent synchronization barriers, such as threads within a block reaching different__syncthreads()calls, which deadlocks hardware warps.
Invoke the sanitizer with an explicit non-zero exit code:
1compute-sanitizer --tool memcheck --error-exitcode 1 ./test_runner
2compute-sanitizer --tool racecheck --error-exitcode 1 ./test_runnerAny report of a hazard or misaligned access halts evaluation immediately.
5. Clean CUDA event benchmarking
Accurate GPU timing requires strict methodology. Python host timers (time.time()) measure kernel launch enqueue time rather than device completion.[6] High-integrity benchmarking enforces five rules:[7]
- CUDA events on the work stream: Place
cudaEventRecordbefore and after the kernel on the active stream, synchronizing on the end event before reading elapsed time. - Warmup passes: Run 20 to 50 warmup iterations to bring the GPU core and memory clocks out of idle power states (P-states).
- Interleaved A-B-B-A execution: Alternate between baseline () and candidate () executions to cancel out thermal throttling and dynamic frequency variations over time.
- Rotated buffer cache busting: If a benchmark runs the same 16 MB tensor in a tight loop on an H100 GPU (which has 50 MB of L2 cache), the tensor stays resident in L2 cache. The benchmark reports an unrealistic 12 TB/s cache speed instead of measuring HBM memory bandwidth. Cycle through a ring of separate memory buffers to force real global memory traffic.
- Statistical reporting: Record full timing distributions (median, P90, P99) instead of cherry-picking the minimum latency.
6. Roofline sanity check
Compare measured kernel throughput against the theoretical hardware ceiling using the Roofline model.[8]
For weighted RMSNorm, calculate the arithmetic intensity ():
- Operations: Sum of squares ( multiplies, adds), mean (1 divide), rsqrt (1 op), normalization ( multiplies), and weighting ( multiplies). Total: roughly floating-point operations.
- Memory traffic: Read input ( elements), read weight ( elements), and write output ( elements). For FP16 ( bytes/element), total memory traffic is bytes.
- Arithmetic intensity: .
Because an H100 SXM5 GPU features an arithmetic intensity ridge point around 150 FLOPs/Byte, RMSNorm is deeply memory bandwidth bound. Achieved bandwidth can't exceed the physical HBM3 limit of 3.35 TB/s:
If a benchmark reports an effective bandwidth of 5.2 TB/s on an H100, the kernel isn't fast; it's skipping computation, returning early, or dropping memory writes.
The refinement feedback loop: hardware-guided iteration
Autonomous generation agents (such as KernelAgent) don't rely on blind one-shot generation; they analyze diagnostic traces to iteratively optimize kernel code.[9] The harness closes the loop by feeding structured telemetry back to the model:

The feedback payload provides three categories of actionable signals:
- Compiler diagnostics: Capture
ptxaswarnings, register spill counts, and shared memory footprints. If local memory spills occur, the model responds by reducing unroll factors, hoisting variables, or tiling registers. - Sanitizer traces: When
racecheckormemcheckfails, extract the instruction pointer, memory address, thread coordinates (threadIdx=(x,y,z)), and block coordinates (blockIdx=(x,y,z)). The agent receives the exact instruction line where a barrier is missing or an address is miscalculated. - Warp stall counters: Telemetry from NVIDIA Nsight Compute (NCU) reveals runtime bottlenecks via hardware performance counters:[8]
smsp__warp_issue_stalled_long_scoreboard_pct: Warps waiting for global DRAM loads. Feedback prompts the model to vectorize memory loads usingfloat4or implement asynchronous copies (cp.async).smsp__warp_issue_stalled_short_scoreboard_pct: Warps stalled on shared memory or MIO operations, signaling shared memory bank conflicts. The model pads shared memory buffers (such as__shared__ float smem[128 + 1]).smsp__warp_issue_stalled_barrier_pct: Warps stalled waiting at__syncthreads(), pointing to thread divergence or poor load balancing. The model switches to warp shuffle intrinsics (__shfl_down_sync) across 32-thread warps.
To prevent prompt poisoning and benchmark memorization, enforce three strict boundaries: sanitize logs to remove raw tensors from hidden fixtures, cap the refinement loop to a maximum of 5 iterations, and hold out an untouched validation suite that runs only once after candidate generation freezes.
The promotion evidence ladder: from lab to production infrastructure
Passing laboratory unit tests is necessary, but it doesn't prove that a kernel will run reliably under messy production traffic. The promotion evidence ladder establishes four progressive validation tiers:

Tier 1: Lab verification
The candidate clears the automated harness: the operator contract passes, ptxas shows zero local memory spills, multi-scale tests verify prime lengths and adversarial floats, Compute Sanitizer reports zero hazards, and benchmark throughput aligns with the Roofline model.
Tier 2: Shadow execution
Deploy the compiled candidate to a production inference node in shadow mode. The inference runtime duplicates real customer requests: the trusted reference kernel computes the user-facing response, while the candidate kernel runs concurrently on an asynchronous stream with zero impact on user latency.
An asynchronous worker compares candidate outputs against reference tensors. Shadow execution audits three critical metrics under production traffic:
- Numerical consistency: Verify that real input distributions (such as varying context lengths and sparsity) don't trigger unexpected precision divergence or NaNs.
- Host and device memory leaks: Monitor virtual memory metrics (VMM) and CUDA caching allocators over millions of invocations.
- JIT compilation cardinality: Ensure the runtime doesn't compile a new binary for every novel sequence length, which exhausts host RAM and GPU memory.
Tier 3: Canary routing
Route a small fraction of live traffic (e.g., 1% ramping to 5%) directly to the candidate kernel behind a dynamic feature flag. Execution is restricted to tested GPU architectures via dispatch predicates.
During canary routing, automated tripwires monitor three failure indicators:
- Tail latency regressions: A sudden spike in P99 or P99.9 latency indicates warp serialization or cache thrashing.
- Driver and hardware errors: Any GPU XID error, CUDA illegal address trap, or hardware engine reset trips the circuit breaker immediately.
- Downstream logit drift: Sample output token distributions to ensure downstream generation remains identical.
If any tripwire triggers, the feature flag flips within milliseconds, routing all traffic back to the trusted reference without dropping requests.
Tier 4: Production gate
Full promotion commits the candidate to the core operator registry. The kernel includes an automated circuit breaker, a permanent reference fallback path, and a cryptographically signed promotion receipt.
Read benchmark scores within their boundary
Research benchmarks measure model capabilities across standardized harnesses, but they don't certify production readiness:
| Benchmark | Useful signal | Boundary |
|---|---|---|
| KernelBench | Correct-and-faster rate across 250 PyTorch workloads under fixed thresholds[10] | Uses fixed public shapes; doesn't test general layout or prime dimension coverage |
| KernelBench-Verified | H200 evaluation with a TF32-enabled baseline, four distributions, and memory tracking[11] | Best-of-five selection; excludes degenerate tasks; focuses on single-turn generation |
| KernelBench-X | 176 tasks across 15 categories, precision variants, and cross-GPU hardware efficiency[12] | Hardware-specific wins don't guarantee portability to untracked architectures |
| SOL-ExecBench | 235 B200-targeted problems with hardware-derived Speed-of-Light (SOL) bounds[13] | Bound calculations depend on fixed baseline software; doesn't evaluate deployment safety |
Aggregate benchmark scores can mask localized regressions. A candidate might achieve a 1.5x average speedup across common shapes while silently producing incorrect results on strided views. Always evaluate candidates against your application's exact operator contract and production distribution.
Preserve a promotion receipt
Every promoted kernel requires an immutable, machine-readable promotion receipt that records its complete provenance:
1{
2 "operator": "weighted_rmsnorm",
3 "contract_version": "3",
4 "status": "promoted_production_ready",
5 "candidate_source_sha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
6 "candidate_binary_sha256": "5f4dcc3b5aa765d61d8327deb882cf992b95bc6809623e1f5899996d9962a6b2",
7 "dispatch": "valid_inputs && tested_cuda_arch && x_contiguous && weight_contiguous && H%128==0 && !backward_needed",
8 "target": {
9 "gpu": "NVIDIA H100 80GB HBM3 (UUID: GPU-12345678)",
10 "sm": "sm_90a",
11 "driver": "550.54.14",
12 "toolkit": "12.4.1",
13 "pytorch": "2.4.0+cu124"
14 },
15 "correctness": {
16 "suite_version": "hidden-v7",
17 "reference_sha256": "8f64243b827e834b6e5b871fa14b8a8b17b2b8e3a241270c8a81615d6c8b9d8a",
18 "status": "passed",
19 "cases_tested": 1420,
20 "cases_failed": 0,
21 "tolerance_policy": "rmsnorm-fp16-v3",
22 "case_results": "artifact://audit/correctness/rmsnorm_v3_results.parquet"
23 },
24 "sanitizers": {
25 "memcheck": {"status": "passed", "errors": 0},
26 "racecheck": {"status": "passed", "errors": 0},
27 "initcheck": {"status": "passed", "errors": 0},
28 "synccheck": {"status": "passed", "errors": 0}
29 },
30 "benchmark": {
31 "protocol": "paired-abba-v4",
32 "baseline_revision": "torch-2.4.0-native",
33 "raw_samples": "artifact://audit/bench/rmsnorm_v3_timing.parquet",
34 "cache_regime": "rotated_buffers",
35 "speedup_median": 1.34,
36 "achieved_bandwidth_tbs": 2.82
37 },
38 "memory": {
39 "peak_device_bytes": 16777216,
40 "workspace_bytes": 0,
41 "artifact_cache_entries": 1
42 },
43 "approval": {
44 "reviewer": "[email protected]",
45 "signature": "30450221008f...c89012"
46 },
47 "rollout": {
48 "feature_flag": "weighted_rmsnorm_generated_v3",
49 "canary_scope": "h100-cluster-east-1",
50 "rollback_target": "weighted_rmsnorm/reference@contract-v3"
51 }
52}A human reviewer inspects the candidate code, verifies that dispatch predicates match the library specification, reviews licensing, and confirms that the rollback target is tested before signing the receipt.
Promotion rubric
Promotion uses hard gates before evaluating performance scores:
| Gate | Promote condition | Required evidence |
|---|---|---|
| Contract | Stable schema, semantics, domain, fallback, and aliasing | Versioned operator specification |
| Correctness | Zero failures across visible, input-blind, hidden, and adversarial suites | Case results and tolerance policy |
| Safety | Zero memory, race, initialization, and synchronization hazards | Compute Sanitizer reports with zero errors |
| Artifact | Candidate source and loaded binary match; no forbidden behavior | Hashes, ptxas logs, symbols, dependencies |
| Performance | Paired improvement on target workload with baseline parity | Raw CUDA event samples and hardware records |
| Memory | Peak, workspace, host, and cache growth remain within budget | Allocator traces and cache cardinality |
| Operations | Reviewer, canary, alarms, owner, and one-step rollback ready | Signed receipt and rollout plan |
No speedup justifies bypassing a safety or contract gate. Once all hard gates pass, teams can rank candidates by latency, maintainability, and resource utilization.
Mastery check
Evaluation rubric
- Foundational: Distinguish between generated source code, benchmark pass rates, and production promotion criteria.
- Intermediate: Design a multi-scale hidden test suite, Compute Sanitizer verification plan, and Roofline sanity check for a GPU operator.
- Advanced: Implement a closed-loop refinement agent using NCU warp stall counters and manage canary rollouts with sub-millisecond fallbacks.
Diagnose a misleading pass
| Symptom | Likely gap | Next check |
|---|---|---|
| Random values pass, but a sliced view fails | Test varied values but left memory layouts contiguous | Add stride, offset, and non-contiguous view tests |
| Output values match, but caller's next layer corrupts | Kernel mutated input tensors or aliased storage | Verify input byte hashes before and after execution |
| Candidate is faster on every run, but speed exceeds physical limits | Benchmark measures host enqueue or kernel skips work | Record CUDA events and verify achieved bandwidth vs Roofline |
| Fixed-shape latency is excellent, but host RAM leaks | Runtime JIT-compiles a new binary for every novel dimension | Measure compilation cache cardinality across varying shapes |
| Kernel runs cleanly on test machine, crashes on another GPU | Kernel relies on architecture-specific warp behaviors | Add GPU architecture predicates and test on target hardware |