|
1 | 1 | # gemm-ternlog-mask-consolidation-v1 — one GEMM entry per dtype, masks as the prefilter, ternlog as the mask ALU |
2 | 2 |
|
| 3 | +> **Status:** DRAFT v1.4 (2026-09-05) — §12 RUNS D-GTM-0g/0h/0i/0j/0k. 0k passes |
| 4 | +> cleanly (mask hot path = 0 bytes/step, measured by a counting allocator). **0j |
| 5 | +> falsifies the framing:** there is no density crossover — masks win 745×→297× from |
| 6 | +> 0.02% to 100% relation density — because "GEMM wins when dense" is wrong for a |
| 7 | +> BOOLEAN relation; the real boundary is a TYPE one (Boolean ⇒ masks, valued ⇒ GEMM). |
| 8 | +> The dense-f32 baseline is mis-specified and the headline numbers are explicitly NOT |
| 9 | +> evidence (§12.5); the missing arm is CSR SpMV. D-GTM-0l is now the decisive probe. |
| 10 | +> |
3 | 11 | > **Status:** DRAFT v1.3 (2026-09-05) — §11.10 strengthens the invariant to |
4 | 12 | > `substrate == mask geometry == projection surface`: the 3-D field (diamond tracts, the |
5 | 13 | > "cube") is never allocated — it is a mask-address projection of the 2-D 6×2×8 surface, |
@@ -687,3 +695,110 @@ the 3×4 standing watch; nothing to probe about arity. |
687 | 695 |
|
688 | 696 | Those two probes together are the hologram's test: recover the relation (0l) |
689 | 697 | without allocating it (0k). Nothing else in the program changes. |
| 698 | + |
| 699 | +## §12 — WAVE 0 MEASURED: D-GTM-0g/0h/0i/0j/0k run, and the hypothesis's own framing is corrected |
| 700 | + |
| 701 | +Probe: `examples/hex_trie_vs_gemm_probe.rs` (`--release`, committed). N = 4096, |
| 702 | +mask = 512 B, dense relation matrix = 64 MB. Task, identical for both arms: |
| 703 | +`D` steps of `state = R(state) ∩ constraint`, with a **correctness gate** — |
| 704 | +survivor counts must match or the run aborts. |
| 705 | + |
| 706 | +### 12.1 The gate fired, and it found a bug in the probe itself |
| 707 | + |
| 708 | +First run: PREFIX passed at every cell, RANDOM failed immediately |
| 709 | +(`gemm 912 vs mask 930`). Cause: the GEMM arm computes |
| 710 | +`{ i : srcs(i) ∩ active ≠ ∅ }` while the mask arm was unioning `srcs(i)` over |
| 711 | +active `i`. **Those agree only for a SYMMETRIC relation** — true of bucket |
| 712 | +membership, false of a random relation. The mask arm must union the TRANSPOSE |
| 713 | +(`fwd[j]` = what `j` can activate). Fixed; recorded because the asymmetry is |
| 714 | +easy to reintroduce and the gate is the only thing that catches it. |
| 715 | + |
| 716 | +A second flaw was caught by reading, not by any gate: the mask arm first timed |
| 717 | +at 0.000–0.001 ms — **at or below timer resolution**, so every "speedup" in that |
| 718 | +table (25,940× … 853,300×) was a ratio against quantization noise. Both arms now |
| 719 | +run to a 50 ms floor and report ns/step. |
| 720 | + |
| 721 | +### 12.2 What was measured (all cells passed the equality gate) |
| 722 | + |
| 723 | +**State-density sweep**, depth ∈ {1, 8, 32}: |
| 724 | + |
| 725 | +| relation | mask ns/step | GEMM ns/step | mask B/step | GEMM B/step | |
| 726 | +|---|---|---|---|---| |
| 727 | +| PREFIX (structured) | **21–79**, flat in state density | 8.4–8.8 M | **0** | 73,728 | |
| 728 | +| RANDOM (no structure) | 305 (1%) → 35,522 (99%), scales with active bits | 10.6–13.0 M | **0** | 73,728 | |
| 729 | + |
| 730 | +**Relation-density sweep** (RANDOM, state 50%, depth 8) — the axis the first |
| 731 | +table missed: |
| 732 | + |
| 733 | +| edges/row | relation density | GEMM ns/step | mask ns/step | speedup | |
| 734 | +|---|---|---|---|---| |
| 735 | +| 1 | 0.02% | 8,758,129 | 11,743 | 745.8× | |
| 736 | +| 16 | 0.39% | 12,050,934 | 42,601 | 282.9× | |
| 737 | +| 64 | 1.56% | 12,309,149 | 41,855 | 294.1× | |
| 738 | +| 256 | 6.25% | 13,112,322 | 42,667 | 307.3× | |
| 739 | +| 1024 | 25.00% | 12,525,352 | 42,559 | 294.3× | |
| 740 | +| **4096** | **100.00%** | 12,776,345 | 43,024 | **297.0×** | |
| 741 | + |
| 742 | +### 12.3 D-GTM-0k — ANSWERED, and it is the one clean result |
| 743 | + |
| 744 | +**Mask hot path: 0 bytes/step at every density, every depth, both relation |
| 745 | +shapes.** GEMM: 73,728 B/step (a packing buffer inside `gemm_f32`). The |
| 746 | +invariant's own falsifier passes — nothing is materialized on the mask path, |
| 747 | +measured by a counting global allocator rather than asserted. |
| 748 | + |
| 749 | +### 12.4 D-GTM-0j — there is NO crossover, and that falsifies the framing rather than confirming it |
| 750 | + |
| 751 | +§11.1 pt 6 says *"GEMM is attractive when information is dense; a hex/trie field |
| 752 | +may win when cognition is mostly successive elimination."* **Measured, the |
| 753 | +density axis does not produce a crossover at all** — the mask arm wins by ~300× |
| 754 | +at 0.02% and by 297× at 100%. Both costs are flat in relation density: GEMM pays |
| 755 | +`O(N²)` FMAs regardless, the mask arm pays `O(active · N/64)` word-ORs |
| 756 | +regardless. |
| 757 | + |
| 758 | +⊘ **So "GEMM wins when dense" is FALSE as stated for a Boolean relation.** The |
| 759 | +honest correction, and it is a TYPE boundary rather than a density: |
| 760 | + |
| 761 | +> **Masks win whenever the relation is Boolean; GEMM is required when the |
| 762 | +> relation carries VALUES.** A bitmask is 32× denser than f32 *before any |
| 763 | +> algorithm runs*, so a Boolean relation in f32 was never the right |
| 764 | +> representation. Where a weight must be accumulated (evidence strength, a |
| 765 | +> learned probability, a distance), the mask arm cannot express the operation at |
| 766 | +> all — that, not density, is where GEMM becomes mandatory. |
| 767 | +
|
| 768 | +### 12.5 The baseline is mis-specified, and the headline numbers are NOT evidence |
| 769 | + |
| 770 | +Stated plainly so no future session cites 297× as support: |
| 771 | + |
| 772 | +1. **A dense f32 matrix for a 0/1 relation is an unfair baseline.** The mask arm |
| 773 | + is not beating GEMM; it is beating a 32×-wasteful *representation* of a |
| 774 | + Boolean relation. The number is real and the credit is misattributed. |
| 775 | +2. **The missing arm is CSR SpMV.** A sparse f32 baseline costs `O(nnz)`, so at |
| 776 | + `deg = 1` it is ~4,096 FMAs — the same order as the mask arm's 11.7 µs, and |
| 777 | + it would plausibly cross. Until that arm is built, no claim about "mask beats |
| 778 | + sparse GEMM" is available, and none is made here. |
| 779 | +3. **The structured/unstructured separation is the one comparison that IS |
| 780 | + internally fair** (same arm, same representation, same task): PREFIX 21–79 ns |
| 781 | + flat vs RANDOM 305–35,522 ns scaling with active bits. ~3 orders of |
| 782 | + magnitude, and it degrades exactly where the mask arm has no structure to |
| 783 | + exploit — which is the E-Q8 discipline applied to compute rather than recall. |
| 784 | + |
| 785 | +### 12.6 D-GTM-0h — a limit of the sandbox, stated rather than papered over |
| 786 | + |
| 787 | +`perf` is unavailable here, so register/cache residency could not be measured |
| 788 | +with counters. The timing proxy is suggestive only: PREFIX per-step cost *falls* |
| 789 | +from ~70 ns at depth 1 to ~21–27 ns at depths 8 and 32 (loop-invariant setup |
| 790 | +amortizing over more steps), with no knee up to depth 32 — consistent with |
| 791 | +staying resident, and **not proof of it**. Graded [S] pending a machine with |
| 792 | +counters. |
| 793 | + |
| 794 | +### 12.7 What W0 now leaves open |
| 795 | + |
| 796 | +- **D-GTM-0g** — partially answered; needs the CSR SpMV arm (12.5 pt 2) before |
| 797 | + "mask/trie vs GEMM" means anything beyond "packed beats unpacked". |
| 798 | +- **D-GTM-0l** — unrun. It is now the *decisive* probe: with the density axis |
| 799 | + dead, the hypothesis stands or falls on whether packed-prefix routing can |
| 800 | + express real long-range relations without codebook entropy exploding, on the |
| 801 | + R2IL/C64 ore. |
| 802 | +- **The weighted arm** — new, implied by 12.4: the type boundary needs its own |
| 803 | + measurement (where does accumulating a value force GEMM?). |
| 804 | +- 0c / 0d / 0e remain unrun. |
0 commit comments