feat(ffai): vision/audio/TTS/video kernel batch + kernel_tests_harness dead-strip fix - #252
Merged
ekryski merged 36 commits intoJun 3, 2026
Conversation
Collaborator
Author
ekryski
marked this pull request as ready for review
June 2, 2026 03:15
ekryski
force-pushed
the
ek/transpose-tokens-heads-kernel
branch
from
June 3, 2026 04:17
c3b62b6 to
223aafc
Compare
ekryski
added a commit
that referenced
this pull request
Jun 3, 2026
## Summary Lands `docs/KERNEL_ORGANIZATION.md` as a standalone, **docs-only** change so it can be reviewed and discussed without wading through kernel-implementation diffs. The doc is a **proposal** for `metaltile-std`'s kernel source layout — file granularity, the canonical per-kernel file shape (kernel → `kernel_tests` → `kernel_benches`), and a family-by-family migration plan that intentionally avoids a big-bang pass. It coordinates with (but is orthogonal to) the CLI subprocess-rewrite spec: that spec governs the crate/CLI architecture; this one governs the kernel files inside `metaltile-std`. ## Why split it out It was originally written alongside the vision/audio/TTS/video kernel batch in #252. Pulling it into its own PR lets reviewers evaluate the proposed organization on its own merits and land it independently — #252 drops the file in the same change. ## Changes - Add `docs/KERNEL_ORGANIZATION.md` (extracted verbatim from #252). - Index it under **Design & planning** in `docs/README.md`. No code changes.
0xClandestine
pushed a commit
that referenced
this pull request
Jun 3, 2026
## Summary Lands `docs/KERNEL_ORGANIZATION.md` as a standalone, **docs-only** change so it can be reviewed and discussed without wading through kernel-implementation diffs. The doc is a **proposal** for `metaltile-std`'s kernel source layout — file granularity, the canonical per-kernel file shape (kernel → `kernel_tests` → `kernel_benches`), and a family-by-family migration plan that intentionally avoids a big-bang pass. It coordinates with (but is orthogonal to) the CLI subprocess-rewrite spec: that spec governs the crate/CLI architecture; this one governs the kernel files inside `metaltile-std`. ## Why split it out It was originally written alongside the vision/audio/TTS/video kernel batch in #252. Pulling it into its own PR lets reviewers evaluate the proposed organization on its own merits and land it independently — #252 drops the file in the same change. ## Changes - Add `docs/KERNEL_ORGANIZATION.md` (extracted verbatim from #252). - Index it under **Design & planning** in `docs/README.md`. No code changes.
… attention Grid3D element-copy kernel reshaping [n_tokens, n_heads, head_dim] token-major to [n_heads, n_tokens, head_dim] head-major, so a vision / audio tower's attention can stay GPU-resident: stage-1 (per-head RMSNorm + ffai_rope_2d) emits token-major Q/K/V, but ffai_sdpa_bidirectional reads K/V head-major. Paired #[test_kernel] oracle, exact (tol 0) across f32/f16/bf16; bench at the SigLIP production shape (576×16×64).
… linears ffai_clamp_scalar: out[i] = min(max(x[i], lo), hi) with lo/hi as 1-element f32 buffers (runtime scalars). Gemma 4's Gemma4ClippableLinear (vision tower + audio encoder, use_clipped_linears=True) clamps each projection's input and output to per-linear scalar bounds from the checkpoint; this applies one on the GPU so the attention pipeline stays GPU-resident. Grid3D, paired oracle test exact across f32/f16/bf16.
…rnel ffai_resize_normalize: the one GPU op every VL preprocess needs — bilinearly resample an interleaved [src_h,src_w,3] [0,1] image to target_h×target_w, normalize (v-mean[c])/std[c] per channel, write planar NCHW [3,th,tw], in one Grid3D dispatch (replaces the CPU triple-loop resize + normalize). align_corners =false half-pixel sampling (HF convention); runtime u32 dim buffers so one kernel serves every variable-resolution size. Paired oracle test vs a CPU bilinear reference — max|Δ| 2.4e-7 f32, exact f16/bf16.
…d to FFAI The emit pipeline enumerates via the #[bench] registry; without a kernel_benches module the kernel built + passed correctness but wasn't emitted into the metallib/Swift wrappers. Add the bench (640x480->448x448).
Channel-last sibling of depthwise_conv2d for the FastVLM / FastViTHD (MobileCLIP) vision stem, which keeps its whole feature pyramid in NHWC — wrapping the NCHW kernel would force a transpose around every depthwise conv. Same Grid3D one-thread-per-output-element structure, NHWC input/output indexing (channel fastest), independent k_h/k_w (FastViT mixes square + non-square depthwise). kernel_tests (3x3 s1/s2 + 7x7 non-square) pass GPU correctness 9/9 (max|Δ| <= 4e-6 f32); kernel_benches included so it emits.
ffai_sdpa_bidirectional_windowed_d80 — each query attends only the keys in its own contiguous window [seg_start[i], seg_start[i]+seg_len[i]) instead of the full [0,n_kv). The variant Qwen2.5-VL's windowed-attention blocks (and the MiniCPM-V resampler) need: caller permutes tokens into window order so a window is one slice, passes per-query seg_start/seg_len. Verbatim copy of sdpa_bidirectional_d80's online-softmax + cross-simdgroup reduction (same ragged 3-elem d80 layout, same TPG=1024 reduction dispatch — no freeze hazard), only the K walk is bounded to the segment. kernel_tests (uniform + ragged windows) pass GPU correctness 6/6 (max|Δ| 7e-7 f32); benches incl.
ffai_sdpa_rel_pos_conformer_d128 — the ESPnet/Transformer-XL RelPositionMultiHeadedAttention the Conformer acoustic encoders use (Parakeet, FireRedASR2, GraniteSpeech, Gemma4Audio). Score = scale·((Q+u_h)·K + (Q+v_h)·rel_emb[dist]) before bidirectional softmax — a CONTENT-DEPENDENT position term (per-distance embedding vector dotted with the query), unlike the scalar bias[head,rel] of sdpa_bidirectional_d128_relpos. Folds q/u/v by scale at the load. GraniteSpeech is the u=v=0 special case. Models on the d128_relpos reduction structure (TPG=1024, 4-elem lanes). Both oracle cases (full u/v + zero-uv) pass GPU correctness 6/6 (max|Δ| 1.4e-6 f32).
avg_pool2d_nhwc — k_h×k_w box average with stride, channel-last, for the Gemma 4 vision pool + tile-model downsampling (replaces a CPU pool loop). count_include_pad=false so edge windows divide by their real tap count. Grid3D one-thread-per-output. 6/6 GPU correctness (exact for in-budget).
frame_diff_luma — box-downscale two RGB frames to BT.601 luma and write |luma0-luma1| per cell. Summing gives a global motion score to gate the real-time video tower (skip near-static frames; process only on motion) so a 30fps capture pays tower cost only a few times/sec (multi-modal §7c). Grid3D one-thread-per-output-cell. 6/6 GPU correctness.
mel_spectrogram_magnitude — |STFT| (amplitude) front-end: sqrt(re²+im²) through the Mel filterbank, vs the power (re²+im²) front-end of mel_spectrogram. The Gemma 4 audio encoder + several streaming-ASR front-ends are magnitude-trained; feeding power degrades them. Replaces the Gemma 4 CPU DFT. Direct-DFT Grid3D one-thread-per-(frame,mel). 3/3 GPU correctness (looser f32 tol — sqrt+log amplifies the benign DFT accumulation-order delta).
im2col_patch — unfold an NCHW image into one row per non-overlapping patch×patch block, flattened (c,py,px), feeding the patch-embed GEMM. Replaces the scalar CPU unfold (Gemma 4 unfoldPatches + any patch-embed tower) with a single GPU gather. Handles non-square (variable-resolution) grids. Grid3D one-thread-per-output. 6/6 GPU correctness (exact).
pos_emb_2d_add — out[patch,d] = tokens[patch,d] + pos_x[col,d] + pos_y[row,d] (col=patch%grid_w, row=patch/grid_w), the post-patch-embed position step for Gemma 4 + factorized-2D-pos towers (replaces a CPU loop). Variable-resolution towers interpolate the learned tables to grid_w/grid_h first, then this does the gather+add. Grid3D one-thread-per-output. 6/6 GPU correctness (exact).
ffai_sdpa_decode_sink_buf — decode SDPA reading a PER-HEAD learned attention sink from a [n_q_heads] buffer (load sink[q_head]), vs sdpa_decode's scalar sink_logit constexpr that forces a per-head host sync. All heads run in one dispatch; removes the host-side per-layer sink sync in GPTOSSAttention. The sink is a virtual key (score sink[q_head], value 0) folded into the softmax denominator. Adds ragged bounds-masking (4 elems/lane, masked) so it covers GPT-OSS d64 AND d128 in one kernel — sink-token range + sliding window preserved. 6/6 GPU correctness (d64+d128, max|Δ| 4.8e-7 f32).
…ant) ffai_resize_normalize_bicubic — higher-quality sibling of ffai_resize_normalize: a 4×4 cubic-convolution sampler (Keys, a=-0.75) instead of 2×2 bilinear, preserving edges far better when down-scaling a large photo to a tower's native grid (where bilinear aliases). Same fused interface (interleaved→normalize→planar NCHW, runtime u32 dim buffers, one Grid3D dispatch). Matches torch interpolate(mode='bicubic', align_corners=False): half-pixel centers, 4 taps floor(src)-1..+2, edge-clamp per tap, partition-of-unity weights (no renormalize). Per-tap branch specialization avoids a runtime select and is exact at boundaries. 6/6 GPU correctness (down + up-scale, max|Δ| 2.7e-6 f32).
ffai_adain1d — per-row instance-normalize over the time axis then per-row affine from the style vector: out[r,t] = gamma[r]·(x[r,t]-mean_r)·rsqrt(var_r +eps) + beta[r]. The style-conditioning op all through the Kokoro acoustic decoder + prosody/duration predictors (distinct from RMS/LayerNorm: it normalizes across TIME per channel, scale/shift are per-row scalars). Reduction kernel, one threadgroup per row (simd_sum + cross-simdgroup combine), two passes (reduce, write). 9/9 GPU correctness (short + long seq).
ffai_lstm — runs the WHOLE LSTM sequence recurrence on the GPU in one threadgroup (thread per hidden unit, h/c in threadgroup memory across timesteps, barrier between state read/write). Complements the existing kokoro.rs lstm_cell which does one step + host recurrence; this is the 'GPU from the start' BiLSTM the session-plan flagged — bidirectional = two dispatches (forward out_offset 0, backward out_offset hidden) into a shared [seq_len, 2*hidden] buffer. reverse flag for the backward walk; gate order i,f,g,o; manual sigmoid/tanh via exp (exact tanh identity). 9 tests pass GPU correctness (fwd/bwd/h40, max|Δ| 8e-7 f32). Also removes the redundant standalone adain1d.rs added earlier — kokoro.rs already ships an identical AdaIN1d kernel (same subop).
…d exp The body parser exposes sigmoid/tanh (kernel/body.rs) and the codegen emits the mt_sigmoid preamble + Metal's builtin tanh, so the gate activations should use them directly (as kokoro.rs::lstm_cell already does) rather than the manual 1/(1+exp(-x)) / 2/(1+exp(-2x))-1 forms. Clearer and marginally more accurate. 15/15 GPU correctness.
Kernels shouldn't be filed under a model name (many models share them).
Split ffai/kokoro.rs:
- adain1d kernel → adain1d.rs (op kokoro→norm); generic AdaIN doc.
- lstm_cell kernel → lstm.rs alongside ffai_lstm (the per-step form next to
the full-sequence form — cohesive LSTM file); op kokoro→lstm, and it now
uses the sigmoid()/tanh() DSL intrinsics like ffai_lstm.
Kernel function names unchanged (adain1d, lstm_cell) so the FFAI by-name emit
is unaffected. 18 GPU-correctness tests pass (lstm 15, adain 3).
Rename + scrub the model name: op 'fishspeech_conv1d'→'conv1d', bench names 'ffai/fishspeech_conv1d/*'→'ffai/conv1d/*', doc reframed generically (the dilated + transposed Conv1d a HiFi-GAN-style vocoder uses). Kernel fns (conv1d_dilated, conv1d_transpose) unchanged → FFAI by-name emit unaffected. 15/15 GPU correctness. Also fixes the stale super::kokoro doc link in lstm.rs.
Cohesive-family grouping (no DSL reason to keep separate): the bicubic sampler variant lives alongside the bilinear in resize_normalize.rs (shared tests via cpu_ref_bicubic + reused u32_bytes). Kernel fns unchanged. 9/9 GPU correctness.
The magnitude (|STFT|) front-end variant lives alongside the power front-end (+ the FFT-route stft_window/filterbank) in mel_spectrogram.rs, sharing the hann/triangular_filterbank/naive helpers. Kernel fns unchanged. 6/6 GPU correctness.
Proposes the target metaltile-std kernel layout: organize by KERNEL FAMILY (sdpa/, rope/, norm/, moe/, conv/, ssm/, quant/, core/, …) under a kernels/ umbrella, dissolving the ffai/ vs mlx/ split — which is organized by 'does MLX have it', a per-bench attribute (mlx=/MetalRef) that's already optional and losing value as we supersede MLX. Defines: one cohesive file per kernel family (all dtype/bit-width/head-dim/shape variants together, with kernel+bench+test spec); when a new file IS warranted (distinct algorithm, not a permutation); the quant/ umbrella for the in-flight fp4/fp8/int8 + affine/aura/turbo work (scheme=file, format=macro cell); the lane-packing macro as the prerequisite that collapses the sdpa d-variants; no-model-names rule; and an incremental, conflict-safe family-by-family migration plan. Not executed — proposal.
The v4 gist restructures the crate/CLI architecture (subprocess runner,
tile.toml, harness, dep-graph reduction); this spec restructures the kernel
files. They're orthogonal but touch the same surface (metaltile-std/src/lib.rs
+ every kernel file's test/bench imports), so add §10 'Coordination with v4':
v4 lands first, the kernel reorg applies on its end-state. Folds in v4's
constraints — top-level src = only lib.rs+utils.rs (kernels/ is a dir module,
fine); harness types move to metaltile::harness::{bench,test} (kernel-file
'use' updates); bench_types.rs deleted → dtype_label to utils.rs; probe/
deleted (not carried into kernels/); metaltile-std facade-only; MLX ref becomes
the ProtocolMessage ref_gbps field (reinforces §7). Net order: v4 → lane-pack
macro → family migration.
…actor) Strip the legacy #[kernel(bench(...))] inline bench metadata from the kernels added on this branch; the registry now sources bench specs from the separate #[bench] kernel_benches modules (dev #228/#244). Test specs already use in-source #[test_kernel]. Registry-consistency gates pass.
Adds dense-equivalent FLOP counts to the compute-bound kernels' benches so the #247 roofline/GFLOP/s columns are populated: conformer rel-pos SDPA (6·H·Nq·Nkv·D), windowed SDPA (4·H·Nq·win·D), decode sink (4·H·Nkv·D), depthwise conv2d, and both LSTM variants. Memory-bound kernels (resize, mel, im2col, pool, pos-emb, frame-diff, adain, transpose, clamp) leave it blank per the spec convention.
…acuously The cargo `kernel_tests_harness` only called `all_tests()`. With nothing in the binary referencing the kernel code, macOS `-dead_strip` removed every metaltile-std kernel translation unit — and with them the `#[test_kernel]` inventory submissions — so `all_tests()` iterated zero entries and the test passed while exercising nothing (runtime ~1.4s). Reference `metaltile_std::all_kernels()` to anchor the kernel TUs (the same anchor `kernel_registry_consistency` already relies on for `all_benches()`), and assert both the kernel and test registries are non-empty so this can never silently regress. The harness now runs all ~428 GPU #[test_kernel] checks (~24s) under `cargo test --workspace`.
Annotate the kernels that do real arithmetic so the #247 roofline/AI/GFLOP-s columns populate and the bottleneck verdict uses the principled AI-vs-ridge path: mel_spectrogram + mel_spectrogram_magnitude (per-thread full DFT power spectrum — compute-bound despite tiny bytes), avg_pool2d_nhwc (k² adds), adain1d (mean/var/affine), resize_normalize bilinear (4-tap) + bicubic (16-tap). Pure data-movement kernels (im2col, transpose, pos_emb_add, clamp, frame_diff) stay blank — flops≈0 adds noise and the bandwidth/occupancy fallback already labels them correctly.
The kernel-layout proposal now lands independently as a docs-only change so it can be reviewed without the kernel-implementation diffs in this PR. Removed here to avoid duplicating the file across two PRs.
…oro GPU vocoder Three elementwise/gather kernels the StyleTTS2 decoder + iSTFTNet generator need between convs to stay GPU-resident across thousands of frames: - ffai_leaky_relu: out = x>0 ? x : slope*x (runtime f32 slope; the AdaIN res-block / generator activation, slope 0.2/0.1/0.01) - ffai_snake1d: x + (1/a)*sin^2(a*x), learnable per-channel alpha over a channels-first [C, length] map (the BigVGAN/iSTFTNet periodic activation) - ffai_upsample_nearest1d: nearest [C, in_len] -> [C, factor*in_len] gather (the AdainResBlk shortcut + F0/N predictor up-sample) All Grid3D one-thread-per-element (no reduction TPG / freeze hazard), f32/ f16/bf16, with kernel_tests oracles (pass) and benches. Full make test green; MSL compiles under xcrun metal.
…oder pool ffai_conv1d_transpose_depthwise: ConvTranspose1d with groups == channels — each output channel uses only its own input channel + per-channel kernel [C, k]. The decoder AdainResBlk pool (ConvTranspose1d(C,C,3,stride=2, padding=1,groups=C)) needs this; the dense conv1d_transpose sums over all input channels. Gather/adjoint form, Grid3D one-thread-per-output, f32/f16/ bf16, kernel_tests oracle (pass) + bench.
Expose erf in the kernel prelude (the IR/macro already lower it to the hardware erf) and add ffai_gelu_erf = 0.5*x*(1+erf(x/sqrt2)) — PyTorch nn.GELU() default. The tanh-approx mt_gelu drifts enough over PLBERT's 12 shared layers to shift the prosody predictor's rounding-sensitive durations, so the GPU front-end needs the exact form. Grid3D, f32/f16/bf16, test + bench.
…nstant rows) The variance was computed as E[x^2] - E[x]^2, which suffers catastrophic f32 cancellation when a channel is near-constant over a long time axis (e.g. the Kokoro iSTFTNet generator at ~7800 frames): the result can go slightly negative and rsqrt(negative) is NaN, poisoning the whole utterance. The true variance is >= 0, so clamp it. Matches the CPU two-pass reference.
…edictor.shared shape) The existing tests cap at hidden 40 / seqLen 8. Add the production Kokoro predictor.shared shape (hidden 256 = 8 full simdgroups, 65 steps, input 640) to exercise the cross-simdgroup threadgroup recurrence over a long sequence. Passes — the kernel is correct in isolation; the Kokoro full-chain NaN that motivated this is context-dependent (FFAI known-issues.md).
The de-model-naming renames in this branch (fishspeech_conv1d -> conv1d_dilated_transpose, resize_normalize_bicubic folded into resize_normalize) collided with upstream additions that kept the old module names; the rebase's union merge re-added the now-orphaned 'pub mod' decls. Drop them (the files are gone) and repoint the upstream fishspeech_conv1d_block_scaled doc comment at the renamed file.
ekryski
force-pushed
the
ek/transpose-tokens-heads-kernel
branch
from
June 3, 2026 19:23
60d3b24 to
7281e93
Compare
- gelu_erf test oracle now computes the Abramowitz-Stegun erf in f64 (its coefficients carry more than f32 precision, tripping clippy::excessive_precision), casting the result to f32. - conv1d_transpose_depthwise oracle uses num.is_multiple_of(stride) instead of num % stride != 0 (clippy::manual_is_multiple_of). cargo clippy --all-targets --all-features -- -D warnings runs clean.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
This branch adds the GPU kernels FFAI (an Apple-Silicon LLM/VLM/audio inference engine built on metaltile) needs to move its remaining vision, audio, video, and TTS paths off CPU, plus a test-infrastructure fix that closes a silent gap in the kernel-correctness gate. Every kernel ships a paired
#[test_kernel]GPU-correctness test against a CPU oracle in the same commit; all pass viatile test.What changed
New FFAI kernels (each with a
#[test_kernel]GPU-correctness test +#[bench]):transpose_thclamp_scalarresize_normalize(+_bicubic)depthwise_conv2d_nhwcsdpa_bidirectional_windowed(d80)sdpa_rel_pos_conformer(d128)sdpa_decode_sink_bufavg_pool2d_nhwc,im2col_patch,pos_emb_2d_add,frame_diff_lumamel_spectrogram_magnitudelstm(ffai_lstmfull-sequence +lstm_cell),adain1dconv1d_dilated,conv1d_transposeCleanups
kokoro.rs→adain1d.rs/lstm.rs,fishspeech_conv1d.rs→conv1d_dilated_transpose.rs(kernels named by what they compute, not the model).#[kernel]+#[bench]form after the macro refactor..flops()annotations on the compute-bound kernels (conformer/windowed/sink SDPA, depthwise conv, LSTM, conv1d) so feat(bench): wall-clock latency, GFLOP/s, roofline %-of-peak + bottleneck verdict #247's GFLOP/s + roofline columns populate; memory-bound kernels left blank.Test-infrastructure fix (
test(harness): anchor kernel TUs …)kernel_tests_harnessonly calledall_tests(); with nothing referencing kernel code, macOS-dead_stripremoved every metaltile-std kernel translation unit — and its#[test_kernel]inventory submissions — so the harness iterated zero entries and passed vacuously (~1.4 s, exercising nothing). It now referencesall_kernels()to anchor the TUs (the same anchorkernel_registry_consistencyrelies on) and asserts both registries are non-empty. The harness now actually runs all GPU#[test_kernel]checks (~24 s) undercargo test --workspace.Docs
docs/KERNEL_ORGANIZATION.md— proposed organization of the kernel/ops tree by kernel family, reconciled with the v4 CLI subprocess rewrite. For discussion.Update — complete the StyleTTS2 / Kokoro GPU chain
The original TTS batch above (
adain1d,lstm,conv1d_dilated/conv1d_transpose) shipped the building blocks. These follow-on commits add the remaining kernels so the entire Kokoro / StyleTTS2 text→waveform chain (PLBERT text encoder → prosody predictor → AdaIN decoder → iSTFTNet generator → vocoder) runs GPU-resident in FFAI, verified end-to-end against the CPU / mlx-audio reference.New kernels (each with a paired
#[test_kernel]+#[bench]):leaky_relusnake1dx + (1/α)·sin²(αx)with per-channel learnable α — the BigVGAN / iSTFTNet periodic activationupsample_nearest1dAdainResBlk1dshortcut + F0/N predictor up-samplerconv1d_transpose_depthwisegroups == channels) conv-transpose — the StyleTTS2 decoderpool(the denseconv1d_transposesums over all in-channels)gelu_erf(+ a newerfprelude intrinsic)0.5·x·(1+erf(x/√2))GELU — PLBERT'snn.GELU()default; the tanh-approxmt_geludrifts enough over 12 ALBERT layers to shift the predictor's rounding-sensitive durationsCorrectness fix to an existing kernel
adain1d: clamp variance ≥ 0 beforersqrt. Variance was computed asE[x²] − E[x]², which suffers catastrophic f32 cancellation when a channel is near-constant over a long time axis (the Kokoro generator runs adain over ~7,800 frames): the result can go slightly negative →rsqrt(negative)= NaN, poisoning the whole utterance. The true variance is ≥ 0, so clamp it; this matches the CPU two-pass reference. Latent bug affecting anyadain1dconsumer, not just Kokoro.LSTM coverage
ffai_lstmGPU-correctness test at the real Kokoropredictor.sharedshape (hidden 256 = 8 full simdgroups, seqLen 65, input 640) — the prior tests capped at hidden 40 / seqLen 8, never exercising the cross-simdgroup threadgroup recurrence over a long sequence. Passes. (FFAI side carries a note: the Kokoro front-end LSTMs run on CPU as a workaround for a context-dependent NaN that only appears after the full chain's many prior GPU dispatches and is not reproducible standalone — the kernel is bit-exact in isolation.)Verification
tile test— every new kernel passes against its CPU oracle (e.g.sdpa_decode_sink_buf6/6,sdpa_rel_pos_conformer6/6,ffai_lstm(incl. hidden-256/seqLen-65),conv1d_*+conv1d_transpose_depthwise,snake1d,leaky_relu,upsample_nearest1d,gelu_erf,resize_normalize_bicubic).make test— full workspace gate green (0 failures);make emit-all— every kernel emits valid MSL underxcrun metal; the empty-body MSL detector is clean.kernel_registry_consistency+ the fixedkernel_tests_harness(all GPU checks, ~24 s) pass.gelu_erf/layerNorm) → predictor F0/N AdaIN curves → AdaIN decoder (conv1d_transpose_depthwisepool) → iSTFTNet generator (leaky_relu/snake1d/conv1d_*) → vocoder iSTFT — producing a waveform identical to the verified CPU path (energy 75.2; per-stage parity ~1e-5). Also: GPT-OSS-20B greedy decode throughsdpa_decode_sink_bufproduces coherent output (156/200 unique tokens).Representative bench (
tile bench -f sdpa_rel_pos_conformer, M1 Max), showing the GFLOP/s column from the.flops()annotation:AI assistance
This PR used AI assistance (Claude) under human direction and review — spanning kernel design, DSL authoring, CPU-oracle tests, the dead-strip root-cause analysis, the adain1d NaN diagnosis, the bench annotations, and this description. Each kernel was validated against its CPU reference before inclusion.