Repository navigation
Add I32x16::dot4_u8_i8_add_masked for exact 9-bit sign-magnitude dot products - #387
Conversation
dot4_u8_i8_add_masked is dot4_u8_i8_add with the bytes of `a` whose bit in `keep` is clear replaced by 0. Two calls over the same magnitudes, one with the positive plane and one with its complement, give an exact 9-bit sign-magnitude dot product against i8 weights (the full i8 range, -128 included) with i32 accumulators and no widening of the operands. AVX-512 uses one masked move before vpdpbusd; AVX2, AVX, NEON and wasm expand the mask with one AND and one byte compare per register; nightly selects through core::simd::Mask. examples/u9_cost_probe.rs times the candidates per 64 lanes and measures the reconstruction error of each 9-bit layout on a unit Gaussian. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01XAqKMMjKnig6MXTd41Lf2v
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01XAqKMMjKnig6MXTd41Lf2v
The AVX2 arm applies the byte mask inside the dot4 loop instead of writing a masked copy first. The probe gains a facade section that times dot4, two plain accumulators and the two masked accumulators on whatever tier the build compiled. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01XAqKMMjKnig6MXTd41Lf2v
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01XAqKMMjKnig6MXTd41Lf2v
|
Important
This repository does not receive automatic reviews because it has fewer than 10 stars.
|
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 0c7531317e
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
…ask in registers Kernel B subtracted 256 * w for a negative zero (magnitude 0, plane bit clear): the sign limb now skips zero magnitudes. Every exact SM9 kernel, and the facade pair, must match an independent i64 reference before its time is printed. The facade kernels returned lane 0 only, which let the optimizer drop half of the AVX2 work; they now fold all 16 lanes. The AVX2 masked dot4 builds its byte mask from the u64 with a variable shift and a multiply instead of a stored spread. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01XAqKMMjKnig6MXTd41Lf2v
Updates the handoff tables with the checked, all-lane measurements: the AVX2 masked pair costs 6.35-6.44 ns per 64 lanes, about 4x one dot4, not the 4.5 ns the lane-0 timing reported. Silences dead_code on the stored mask spread for the tiers that build the mask another way. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01XAqKMMjKnig6MXTd41Lf2v
Records D-POF-ANT-0's verdicts and the rows they move: AVX2 mask_blend is now the loss in three probes; E2 replaces E5 as the AVX-512-without- VNNI U9 candidate; #395's A5 oracle can serve lance-graph's X1-X9 and #1848 B0. New dots: conjugate_mask's scalar byte expansion can reuse mask_byte_spread/BIT_IN_BYTE from #387; the per-tier U9 kernel choice should be one table. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01XAqKMPh2Seh2WLccCksAdY
Follow-up to #386. This adds one facade word and a cost probe. The question it answers: can a native 9-bit TurboVec9 index score at close to u8 cost?
What changes
I32x16::dot4_u8_i8_add_masked(self, a: U8x64, keep: u64, b: I8x64)isdot4_u8_i8_addwith the bytes ofawhose bit inkeepis clear replaced by 0. Two calls over the same bytes give an exact 9-bit sign-magnitude × i8 dot product. The magnitude is inaand the positive plane is inkeep:How each backend realizes it:
vpdpbusd, or the widen path when VNNI is absent.BIT_IN_BYTEand one byte compare per register, with no shuffle.core::simd::Maskselect.The word is plain arithmetic, so it does not care which contract produced the bytes. DR512/Codec9 values and TurboVec9 centroid IDs are kept apart,
lut9/lut_u8are unchanged, and no codec is duplicated.Measured (AVX-512 VNNI Xeon,
examples/u9_cost_probe.rs, ranges over 3 runs)Every exact sign-magnitude kernel must match an independent i64 reference before its time is printed. Every facade kernel folds all 16 accumulator lanes into its result.
dot4_u8_i8_add(#386)xor 0x80bias)dot(lo) - 256·dot(sign)dot(m) - 2·dot(m & neg), one accumulatordot(m & pos) - dot(m & neg), two accumulators (this word)vpermi2b+ blendsPrecision on N(0,1), against scan cost:
Streaming from DRAM (64 MiB of codes), the per-dimension cost is 0.035 – 0.037 ns for i4 and 0.048 – 0.052 ns for stored 9-bit.
Answer to the acceptance question: on AVX-512 VNNI, yes, with stored values. Scoring costs about the same per dimension as today's i4 permute-dot from L1, and 1.4× per dimension from DRAM, for +25.8 dB. With IDs plus an in-scan 512-entry lookup, no: the lookup costs about 5× the arithmetic. TurboVec's levels do not depend on the query, so the decode belongs at encode time.
AVX2 (no VNNI) is the weak tier. The masked pair costs 6.35 – 6.44 ns per 64 lanes, against 1.59 – 1.79 ns for one
dot4. Each masked call adds about 1.4 ns of mask expansion on top of its own 16-bit widening. A fused single-widen op would avoid both the second widening and the mask; it is not built.The Lloyd-Max codebooks in the probe are probe-local fits, not TurboVec's solver. None of these numbers are recall measurements.
Tests
simd::dot4_nibble_facade_paritypasses 8/8 on every arm:The suite covers a reference corpus, per-bit gating, all 512 sign-magnitude codewords × weight edges against an i64 oracle, and the 16,448-call overflow bound.
The NEON and wasm parity programs pass, with new codes 0x504 and 0x505.
clippy -D warningsis clean on native, v4, v3 and v2.Disable runs, all red as expected:
BIT_IN_BYTEon AVX2;Handoff
.claude/knowledge/turbovec9-u9-substrate.mdcarries the proposed scan layout: per 64 dims, 64 magnitude bytes plus one u64 positive plane, vector-major. It also lists the decisions that stay with the TurboVec owner: grid clip, how the encoder writes 0, and recall on real data. No TurboVec code was changed.🤖 Generated with Claude Code
https://claude.ai/code/session_01XAqKMMjKnig6MXTd41Lf2v