Skip to content

Commit 55ec81e

Browse files
authored
Merge pull request #403 from AdaWorldAPI/ccr-45a41fb4-0j3i0l
Synergy map R7: #402 (adder words, vectorized exp, Abakus cost gate)
2 parents 6e0a007 + cea7994 commit 55ec81e

1 file changed

Lines changed: 90 additions & 0 deletions

File tree

‎.claude/knowledge/synergy-map-2026-10-29.md‎

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -348,6 +348,96 @@ What is left for the probe is lance-graph work: register `Erf` over `vserf`,
348348
switch its `Where` DO to `blend_i32_scalar` when `Y` is a scalar (this also
349349
closes half of L17), plus L11–L15. V13 stays a probe.
350350

351+
## R7. #402: binary adder words, vectorized exp, the Abakus cost gate (2026-10-30)
352+
353+
#400 and #401 were merged between R6 and this pass and are recorded here
354+
only for the rows they moved:
355+
- #400 shipped R5's wishlist items 1–5: typed `Where` (`blend_f32/i64`),
356+
pair compares, copy-free `matmul_f32`, `gather_rows_f32`, and the float
357+
accumulation-order record.
358+
- #401 shipped the `ndarray::simd` re-exports and `hpc::checked_i64`.
359+
360+
### R7.1 What #402 shipped
361+
362+
- **`half_add_mask` / `full_add_mask`** in `simd_masking_ops`, re-exported
363+
through `ndarray::simd`. They are #391's `flip` and #389's `carry_save3`,
364+
unchanged.
365+
- **`pow2n_from_int` vectorized.** `simd_exp_f32` no longer builds 2^n
366+
through `to_array`.
367+
- AVX-512: `simd_exp_f32` is 44 instructions, down from 159.
368+
- `vsexp`, `vstanh` and `vserf` are about 4×, 3× and 2.4× faster on
369+
AVX-512, and 1.2–1.45× faster on AVX2.
370+
- **`U32x16` `Shl`/`Shr<Self>`** on AVX2, AVX, NEON, wasm and nightly. Only
371+
AVX-512 and scalar had them before.
372+
- **Lab only:** `Abacus<BITS>` in `examples/u9_domino`, with transactional
373+
overflow refusal. Report: `binary-abacus-polyfill-probe.md`.
374+
375+
### R7.2 Rows that moved
376+
377+
| row | before | now | evidence |
378+
|---|---|---|---|
379+
| H11 `vserf` | closed in #399, 2.3 ns/el on AVX-512 | still closed; **0.89–1.06 ns/el** | #402 timing table |
380+
| V13 summation order | probe first | ndarray half answered (#400): `sum`/`mean_axis` are tier-invariant; `gemm_f32` splits into an FMA and a non-FMA class. ORT's order is still not measured | `float-accumulation-order.md` |
381+
| L11–L15 registrations | open, lance-graph | unchanged; #400 added the words L13 and L14 can register over (`gather_rows_f32`, copy-free `matmul_f32`) | #400 |
382+
| AVX2 `U8x64::mask_blend` (R2 burn-down #1) | top AVX2 burn-down item | unchanged, joined by a second cause (**N24**) | — |
383+
| #389 facade gap "sign plane to `+1/-1` bytes" | recorded, not added | still open; no consumer has asked since | `u9-abacus-probe.md:84` |
384+
385+
### R7.3 New dots
386+
387+
- **N22 — the adders are now facade words.** Any consumer that adds 64-lane
388+
masks at chosen significances can use `half_add_mask`/`full_add_mask`
389+
instead of restating the XOR/AND law. No consumer outside the fixtures
390+
uses them yet. A carry-save popcount over many mask words, the CSA tree
391+
that a `count` fold over hundreds of masks would use, is the obvious
392+
candidate. It has not been looked for in lance-graph mask-risc.
393+
- **N23 — every exp-based word got faster at once.** `vsexp`, `vstanh`,
394+
`vserf` and, through them, `sigmoid_f32` and the softmax family all route
395+
through `simd_exp_f32`.
396+
- For the ONNX registry this lowers the cost of `Erf`, `Sigmoid`, `Tanh`
397+
and `Softmax` without any registry change.
398+
- Against Tract's `Erf` kernel the gap is now about 4× in Tract's favour
399+
(it was about 10×). Tract's kernel trades accuracy for that: at most
400+
about 9×10⁸ ULP, and `erf(1e-10) = 0`. `vserf` stays within 2 ULP.
401+
- **N24 — AVX2 `select` packs its masks lane by lane.** After the change,
402+
AVX2 `simd_exp_f32` still has 42 `vpextrw`/`vpinsrw`. They come from
403+
packing the `simd_gt`/`simd_lt` masks for `select`, not from `pow2n`. This
404+
is a second array-backed AVX2 cost next to `mask_blend` (#388, #389, #395),
405+
and it is why AVX2 gained only 1.2–1.45×.
406+
- **N25 — NEON `simd_exp_f32` has about 47 scalar `fcmp`/`csel`.** They
407+
exist on master too, so they predate #402. They sit in the compare/select
408+
path and are not diagnosed further.
409+
- **N26 — the eager domino counter is not transactional; `Abacus` is.**
410+
- F (`Eager`) leaves its lower columns updated when a carry leaves the top
411+
column.
412+
- `Abacus` restores them by recomputing the carry chain forward from the
413+
input mask, so a successful add keeps no undo log.
414+
- Cost: equal to F on dense masks; slower and noisier on sparse masks
415+
(3.7–5.3 vs 2.3 ns/add on AVX-512 without VNNI), not explained.
416+
- Both are about 4× faster than 64 per-lane adds on dense and single-lane
417+
masks, and roughly even on random masks.
418+
419+
### R7.4 Fruit, revised
420+
421+
Closed this pass: H11's speed half (N23); the `U32x16` variable-shift gap on
422+
five backends.
423+
424+
| id | fruit | size | note |
425+
|---|---|---|---|
426+
| L20 | diagnose N25: which `simd_exp_f32` step lowers to scalar `fcmp`/`csel` on NEON | low | read the aarch64 disassembly of `probe_exp`; master and #402 are identical there |
427+
| L21 | harvest lance-graph mask-risc for a count/sum fold over many mask words (N22): a candidate consumer for `full_add_mask` and for PR B | low | `harvest-scout`; candidates only, then Read |
428+
| H12 | AVX2 compare-mask packing for `select` without per-lane extract/insert (N24) | high | backend work in `simd_avx2.rs`; measure against `simd_exp_f32` and the #395 rows |
429+
| H13 | PR B: promote `Abacus` to a public type | high | blocked on a real consumer (L21); semantics and tests already exist in the fixture |
430+
| — | PR C: facet bit-plane helper | not planned | planes are one AND plus one `cmpeq_mask` on existing words; #389 measured that reuse never breaks even |
431+
432+
### R7.5 Not done this pass
433+
434+
- **Untimed tiers:** AVX, SSE2, NEON and wasm were not timed; only
435+
emulators are available here.
436+
- **CI:** #402 merged while four of its test jobs (`tests/stable`,
437+
`tests/beta`, `tests/1.99.0`, `native-backend/stable`) were still running.
438+
Their outcome on `de03001` was not seen here. The same code passed the full
439+
lib suite locally (2,702 tests).
440+
351441
## 0. What the six ndarray PRs did
352442

353443
| PR | closed | opened or left |

0 commit comments

Comments
 (0)