Skip to content

Commit 3dfa3b0

Browse files
committed
Document U64x8::sum8_u8_add_masked
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01XAqKMMjKnig6MXTd41Lf2v
1 parent 6d15c1b commit 3dfa3b0

2 files changed

Lines changed: 29 additions & 0 deletions

File tree

‎.claude/blackboard.md‎

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3898,3 +3898,12 @@ negative zero; both fixed, every exact kernel now checked against an i64 referen
38983898

38993899
Loose ends: fused single-widen SM9 op for non-VNNI tiers; NEON SDOT/USDOT and AVX-VNNI unused; no NEON/wasm timings;
39003900
recall on a real TurboVec index is the TurboVec owner's measurement.
3901+
3902+
## U64x8::sum8_u8_add_masked: vertical masked byte sum (2026-10-29, branch claude/sum8-u8-masked)
3903+
3904+
Facade word closing the gap #389 recorded for candidate E's anchor term: lane j += sum of kept bytes 8j..8j+8, no
3905+
horizontal reduction. One realization per backend (AVX-512 maskz + vpsadbw; AVX2 register mask + vpsadbw; AVX psadbw per
3906+
quarter; NEON uaddlp/uadalp; wasm extadd_pairwise; scalar; nightly SWAR). Parity in simd.rs + wasm/neon harnesses
3907+
(0x506/0x507); 7 tiers green; 7 disable runs red. 0.687 ns/64 bytes on AVX-512 (281-285x the reference loop), 1.99 ns on
3908+
AVX2 (98x). Knowledge: `turbovec9-u9-substrate.md` § second facade word. Not yet wired into #389.
3909+

‎.claude/knowledge/turbovec9-u9-substrate.md‎

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -157,3 +157,23 @@ from this session.
157157
- No fused single-widen SM9 op for non-VNNI tiers.
158158
- No signed i8 x i8 facade word.
159159
- Recall on a real index.
160+
161+
## Second facade word: `U64x8::sum8_u8_add_masked` (2026-10-29)
162+
163+
`U64x8::sum8_u8_add_masked(self, a: U8x64, keep: u64) -> U64x8` adds to lane `j` the sum of the bytes `a[i]`, `i` in `8j..8j+8`, whose bit `i` in `keep` is set. It is exact. Each call adds at most 8 * 255 = 2,040 per lane, so the u64 lanes wrap only after more than 9 * 10^15 calls. There is no horizontal reduction; reduce once at the end.
164+
165+
It was added for the power-of-two anchor term of candidate E in PR #389. With `|b| = low7 + 128*bit7`, `a*|b| = a*low7 + 128*(sum of a where bit 7 of b is set)`. The facade only had `U8x64::sum_bytes_u64`, which reduces horizontally on every call.
166+
167+
| Tier | Lowering |
168+
|---|---|
169+
| AVX-512 | zero-masked `vmovdqu8`, `vpsadbw` against zero, `vpaddq` |
170+
| AVX2 | mask built in registers as in `dot4_u8_i8_add_masked`, AND, `vpsadbw`, `vpaddq`, two halves (LLVM emits 2 `vpshufb`; none in the source) |
171+
| AVX without AVX2 | `mask_byte_spread`, `cmpeq`, AND, `psadbw` per 16-byte quarter |
172+
| NEON | `vtstq_u8` mask, AND, `uaddlp` x2, `uadalp`; no scalar loop |
173+
| wasm simd128 | `i8x16_eq` mask, AND, two `extadd_pairwise`, fold of 32-bit halves, `i64x2_add`; no shuffle |
174+
| scalar | per-lane loop, the correctness anchor |
175+
| nightly-simd | `Mask::from_bitmask(keep).select`, SWAR fold |
176+
177+
Measured on an AVX-512 VNNI Xeon (4,096 random vectors and masks, medians of 1,001 runs): 0.687 ns per 64 bytes at target-cpu=native against 192.8 - 196.0 ns for the plain reference loop (281 - 285x); 1.987 - 1.991 ns at x86-64-v3 against 194.1 - 195.4 ns (98x). NEON and wasm were not timed.
178+
179+
Tests: `sum8_masked_matches_reference`, `sum8_masked_gates_each_byte_by_its_own_bit`, `sum8_masked_all_kept_agrees_with_sum_bytes` in `dot4_nibble_facade_parity`, plus the doc example (run as a doctest on the native and v3 builds) and parity codes 0x506 and 0x507 in `wasm-simd-parity` and `neon-simd-parity`.

0 commit comments

Comments
 (0)