Repository navigation
dasLLAMA: the fp32 batch GEMM tile, the Qwen3-ASR conv front across lanes, the Granite Rapids diagnosis - #4365
Conversation
ast-grep 0.51.0 ignores the native custom-language libraries sgconfig.yml names unless every invocation carries --custom-languages allow, and the daslang grammar is such a library, so grep_usage and outline (and the C++ scans beside them) answered nothing on a box with that version. The version probe already reads the binary's "custom languages are ignored" warning; it now records it, and every run/scan carries the allow flag when the binary printed it. Older binaries, which reject the flag, see no change: utils/mcp/test_tools.das 497/497 on both 0.42.1 and 0.51.0. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
The forward_profile report is an info-level log, which the default log filter drops, so a --prof run printed the window header and nothing under it. The flag now raises DAS_LOG_LEVEL to info when the environment leaves it unset (the builtin to_log reads the variable live), and the refusal on a rail-less build names -jit-no-cache: the JIT DLL cache serves the compile that erased the markers. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
matmul_batch_core computed every output as its own dot, two loads a FMA, and the audio towers' conv fronts and the TTS linears run every fp32 GEMM through it: Qwen3-ASR's conv2d im2col GEMM was 13.3 s of a 15.2 s encode on the Granite Rapids box. The core now walks the row range by token blocks that keep the X rows in L2, and inside them f32_batch_tile - four weight rows by four tokens, sixteen accumulators in the kernel's own lanes, eight loads a sixteen FMAs - with the row and token tails through dot. The tile is a [tuned] kernel (fallback vec8) the loop-hint tuner races with the other twenty-five; its outputs agree with the per-token dot to the lanes' rounding, so test_matmul_batch holds the fp32 path to 1e-5 relative and the Q8 path bit for bit as before, with a tails shape and a many-block shape added. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
conv2d_s2 filled its im2col columns in one lane and ran the erf GELU over every output in one lane - two million erf evaluations a chunk - while the GEMM between them ran on all of them; on the Granite Rapids box that was most of a 7.7 s encode of the gb1 clip. The im2col splits its output rows across lanes (pure copies, the same bytes under any split) and the GELU takes gelu_erf_batch, the row-threaded twin of the same erf, so every element rounds as before. The encode reads 2.9 s on that box after it (asr_stage_probe, debug-jit). Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
There was a problem hiding this comment.
🔵 Needs a closer look
It changes a core fp32 GEMM to a non-bit-exact tile whose rounding can flip near-tie MoE prefill routing and shift multiple audio models' outputs, a numeric/behavioral change across performance-critical paths that warrants human verification despite no concrete defect being found.
No open issues 🎉
What changed in this PR
This PR advances dasLLAMA's CPU inference performance work on three fronts. It replaces the fp32 batch (prefill) GEMM's dot-per-cell row nest in matmul_batch_core with a 4×4 weight-row-by-token register tile (f32_batch_tile, a [tuned] loop-hint kernel) that dispatches over an absolute lattice, so any lane/row/token split produces identical bits while the tile accumulates each dot in its own SIMD lanes (a deliberate, documented departure from the per-token dot, held within 1e-5 of a double oracle). It also unifies the Qwen3-ASR/gemma4a/canary conv-front im2col into a shared threaded im2col_k3s2p1 and routes GELU through the row-threaded gelu_erf_batch. Supporting changes fix two tooling regressions (ast-grep 0.51 custom-languages flag for the MCP C++/daslang scanners; lcpp_bench --prof raising the log floor) and record the Granite Rapids diagnosis across ledgers and architecture docs.
Changes:
- New fp32 batch GEMM tile + absolute-lattice dispatch, with its race harness, tuner wiring, and bit-for-bit/oracle tests.
- Shared
im2col_k3s2p1across the three audio conv fronts; MoE-router parity comment updated to reflect tile rounding. - Tooling fixes (ast-grep
--custom-languages allow,--proflog floor) plus extensive ledger/architecture/followup documentation.
| File | Description |
|---|---|
dasllama/dasllama_math.das |
Core fp32 batch GEMM rewritten as f32_batch_tile/f32_batch_block/f32_dot_rows over an absolute 4×4 lattice with X-block and min-n knobs. |
dasllama/dasllama_tower.das |
New shared threaded im2col_k3s2p1; adds gelu_erf_batch usage context. |
dasllama/dasllama_qwen3a.das, dasllama_gemma4a.das, dasllama_canary.das |
Replace inlined im2col loops with im2col_k3s2p1; qwen3a also switches to gelu_erf_batch. |
dasllama/dasllama_common.das |
MoE-router prefill comment notes tile rounding can part a near-tie top-k. |
harness/f32_batch_race.das |
New one-process race of the two constants and tile-vs-nest. |
harness/tune_kernels.das |
Registers f32_batch_tile grid + bench; bumps TUNED_KERNEL_COUNT to 26. |
tests/test_matmul_batch.das |
Oracle/lanes/nest-arm tests with NaN sentinels and poison controls. |
tests/_compares.das, _model_tier.das, _tts_parity.das, test_whisper.das, test_model_image.das |
transcript_words word-list compares, widened seam bars with rotated-input controls, knob save/restore, check_exceeds logging. |
benchmarks/lcpp_bench.das |
--prof raises DAS_LOG_LEVEL to info so the report prints; clearer rail-missing hint. |
utils/mcp/tools/*.das |
ast-grep --custom-languages allow threaded through grep_usage/outline/cpp scanners. |
*.md (ARCHITECTURE_, REVIEW_, PERF_LEDGER, followup_general, CLAUDE) |
New release-boundary/CPU-reference sections, ledger entries, and followup rows 239/240. |
Review effort: Balanced
The ledger carries the diagnosis (the DeltaNet scan and the f32 conv front, not the AMX crowns), the tile race's lines, the three boxes' re-measured ASR, whisper and kitten rows with their provenance, and the reference recipes behind them. ARCHITECTURE_MEASUREMENT_RELEASE.md states where a board row is published - at a release re-mint, never from a branch - and ARCHITECTURE_MEASUREMENT_AUDIO.md the ASR CPU references. REVIEW_MEASUREMENT.md's figure rule narrows to the pick the diff lands and its re-mint rule routes the board row to the release re-mint; row 241 names the bench exe's missing per-rep spread. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
The gemma4a Metal cell and the whisper word-level cell read both transcripts through transcript_words (each_word over the text), so punctuation and spacing a backend renders apart no longer red a cell whose words agree; the gemma4a cell's control is the GPU route fed a half-silenced clip reading other words. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
3c0bd02 to
d48a31f
Compare
There was a problem hiding this comment.
🔵 Needs a closer look
It rewrites a core fp32 prefill GEMM with deliberate floating-point behavior changes (batch output no longer bit-identical to per-token matmul, and MoE prefill routing can diverge from decode on near-ties), affecting multiple models, which needs human numerical/perf verification.
No open issues 🎉
Review effort: Balanced
Behavior change: the fp32 batch GEMM's outputs round in a 4x4 tile's accumulators - a batched tower GEMM no longer matches the per-token dot bit for bit (within 1e-5 relative of a double oracle); Q8 paths are untouched.
Why. The Granite Rapids board read the 35B prefill at 0.91x of llama.cpp and the Qwen3-ASR CPU row at 0.58x. The prefill loss is the DeltaNet scan on eight lanes, not the AMX path (the tune crowns move neither model end to end). The ASR loss was the audio towers' fp32 batch GEMM, a dot per output cell at two loads a FMA, plus the Qwen3-ASR conv front's im2col and erf GELU running in one lane. Separately, ast-grep 0.51 silently disabled the MCP
grep_usageandoutlinetools, andlcpp_bench --profprinted an empty report.What changes.
matmul_batch_corewalks four-row by four-token tiles (f32_batch_tile, a[tuned]kernel the loop-hint tuner races) over an absolute lattice: the dispatch unit is a row tile, a token chunk is whole tiles, a 256 KB X block, so which kernel rounds an output depends on the output alone and any lane count lands the same bits. The tile serves every dot length; the row nest stays as the race's arm behindset_f32_batch_tile_min_n.harness/f32_batch_race.dasraces the two constants and the tile against the nest in one process (the ledger entry carries its lines).im2col_k3s2p1(gemma4a and canary call it too) and its GELU the row-threadedgelu_erf_batch; the same bytes, more lanes.--custom-languages allowwhen the ast-grep probe reports the warning.--profraises the log floor to info when the logger would filter its report.test_matmul_batchcompares against a plain double oracle under a NaN sentinel with anall_finiteassert, holds the threaded walk to the one-lane walk bit for bit, and the row nest under the knob to the per-tokenmatmulbit for bit (the tile at the shipped knob rounding apart is the control); the kitten seam bars widen to 2.5e-4 of peak (conv_post) and 1e-3 absolute (waveform) with a rotated-input control that must land outside both; the gemma4a Metal transcript compares word lists with a half-silenced-clip control;check_exceedslogs the control's distance.ARCHITECTURE_CPU_KERNELS.md#f32-batch-tile-lattice,ARCHITECTURE_MEASUREMENT_RELEASE.md#board-rows-release-boundary(a board row lands at a release re-mint),ARCHITECTURE_MEASUREMENT_AUDIO.md#asr-cpu-references;REVIEW_MEASUREMENT.md's figure rule and re-mint rule (the between-release diff writes a dated ledger entry and names the followup row the release re-mint owes);REVIEW_MEDIA_CELLS.mdadmits a word-list compare where the flipped token is punctuation or casing.Observable behavior.
harness/f32_batch_race.das -- --reps 5, GFLOP/s, tile against nest): M5 1405 against 509 and 1493 against 525; Xeon 1064 against 86 and 999 against 85. X block on the Xeon: 1053 at 256 KB, 349 at 4 MB.test_qwen4exp) still equals the inline run bit for bit.Where to look.
matmul_batch_coreandf32_batch_blockindasllama_math.daswithARCHITECTURE_CPU_KERNELS.md#f32-batch-tile-lattice;conv2d_s2indasllama_qwen3a.dasandim2col_k3s2p1indasllama_tower.das; the two entries at the head ofPERF_LEDGER.md.Validation, claims, ledger
Validation
dasllama-benchexe on the branch and ran the Qwen3-ASR, whisper and kitten CPU cells against their references; the walls are in the ledger entry with their commands, the record stores are not committed (the boards publish with the release re-mint, row 238). The bench exe prints each clip's best of its reps alone, so these cells carry no per-rep spread - a rig gap,followup_general.mdrow 241.asr_stage_probe, debug-jit, gb1): conv.mm 13293 -> 5719 -> 1446 ms, encode 15227 -> 7728 -> 2924 ms; the M5 encode 287 ms throughout (its blocks on the Metal seat).daspkg release --fat arm-i8mmfrom this tree, the 1B Q8_0 at-r 2):sanity: frozen fixture - 8/8 opening tokens match ", in a small village nestled in the";sanity (tg128): warmup argmax 315 " of" (logit 7.824408); the run printed notune gate:line.--area audio(11 files, the only redtest_vulkan_tower_kernels.das, the M5's Vulkan class - no device);--suite image --arm mtowerunderDASLLAMA_PARITY_FULL=1(52 passed, 0 failed - gemma4a E2B and E4B with the half-silenced control);test_matmul_batch13/13; the kitten and kokoro oracle cells with the rotated-input control;test_qwen4exp's mixer cell.dotlength mutated reds the nest-arm cell; the tile's store swapped reds the 100x13 and 1152x480 cells; the old seam bars against the shipped code red (23 conv_post and 1057 waveform elements outside).--fullran once on this tip (the fast tier red on three long lines, wrapped; the lanes then ran targeted: lint, docs, tests-cpp, tests-interp, tests-jit, tests-aot, utils-tests all green); the one red is this box's environment, homebrew Sphinx without sphinx_sitemap, the same as PR 4364's.f32_batch_blockcites#f32-batch-tile-lattice;f32_dot_rowscites#kernel-visibility-lifted-workers;f32_batch_tileandmatmul_batch_corecarry none (the lattice section names them).Claims - stated, not tested
lcpp_bench --profthroughmain,outline's file-plus-glob command (no caller passes both), the C++ scans'--custom-languagesflag (ast-grep 0.51 answers the same either way).Not done
vdpbf16ps,bfdot, the AMX bf16 tile over bf16 planes with an f32-to-bf16 activation panel) that the reference's encoders run, the conv front's first layer and GELU, the Qwen3-ASR decoder's attention over the ~3000 audio tokens: row 240, the next leg, on the same three boxes (stopped, not terminated).matmul_bf16_batch_atkeeps the old nest; it moves with the bf16 family.heldentries: the release re-mint, row 238.REVIEW_MEASUREMENT.mdrules (the changed board cell's before/after rows, the re-minted row, the new cell's mint) still write rows between releases; they route to the release re-mint in a separate rule pass.