simd: mask_ternlog family + contiguous fast path for stride-4 eq masks - #301
Conversation
Two additions to the mask-op family in src/simd_int_ops.rs, both consumed by lance-graph-java's lgj_hop: 1. mask_ternlog::<IMM>(a, b, c, dst) / mask_ternlog_assign::<IMM>(a, b, c) — any 3-input Boolean function of three masks in one pass, IMM being the VPTERNLOG truth table (named tables in simd::ternlog). AND is the rank-1 member of this family; a consumer spelling `a & b & c` as two mask_and_assign passes through a scratch write now spends one AND3 pass (one VPTERNLOGQ per 512 bits). Tail contract: conforming inputs give a conforming dst iff IMM is even; every named immediate is. Parity over all 256 tables x 13 lengths against an independent bit-serial reference, AND3 == and∘and (non-vacuous), tail-iff-even with the odd can-it-fire arm, length-mismatch panics. Re-exported via ndarray::simd. W1a family- shape deviation recorded in .claude/blackboard.md (same as mask_andnot). 2. eq_u32_strided_to_mask at stride_bytes == 4 gathered 16 bounds-checked scalar reads into a temporary before the U32x16 compare — a copy where a cast belonged, and exactly the shape of every lane in a facet-major columnar store. A contiguous path now aliases one fixed [u8; 64] window per 16 elements (safe try_into, bounds proven up front), which lowers to a single vector load. Existing stride4-vs-contiguous parity test covers it. Measured through lance-graph-java's columnar_hop_bench (65 536 rows, 32 facets, both changes): lgj_hop 6.3-7.5 ms -> 1.1-1.85 ms, equivalence asserted before timing. Gates: cargo fmt clean; cargo clippy --lib --features std -D warnings clean; cargo test --lib --features std 2272 passed. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016WkNBjHc2e3zuyz9i8qJEv
|
Caution Review failedThe pull request is closed. ℹ️ Recent review info⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Essentials Run ID: 📒 Files selected for processing (3)
📝 WalkthroughWalkthroughThe SIMD API adds generic ternary mask operations with scalar-tail handling and validation. The equality-mask implementation adds a contiguous stride-4 vector-load path. Hop selection now uses one three-mask operation. ChangesSIMD mask operations and equality optimization
Estimated code review effort: 3 (Moderate) | ~20 minutes Suggested reviewers: Poem
✨ Finishing Touches📝 Generate docstrings
Comment |
Bugbot couldn't run - usage limit reachedBugbot is counted against Cursor usage for this user or team, and this run hit a usage or spend limit. A user or team admin can review and increase usage limits in the Cursor dashboard. (requestId: serverGenReqId_42508340-991f-44b9-afe4-cfa691036b75) |
What
Two additions to the mask-op family in
src/simd_int_ops.rs, both consumed by lance-graph-java'slgj_hop(companion PR on the same branch name there).1.
mask_ternlog::<IMM>(a, b, c, dst)/mask_ternlog_assign::<IMM>(a, b, c)Any 3-input Boolean function of three masks in one pass —
IMMis the VPTERNLOG truth table (named tables insimd::ternlog). AND is the rank-1 member of this family: a consumer spellinga & b & cas twomask_and_assignpasses through a scratch write now spends oneAND3pass (oneVPTERNLOGQper 512 bits; polyfill elsewhere viaU64x8::ternlog, all arms already present from W1a-#9).dstiffIMMis even; every named immediate is; subset-shaped tables inheritmask_andnot's "subset ofa" guarantee.AND3 == and∘and(non-vacuous — both narrowers must contribute); tail-iff-even with the odd (NOR3) can-it-fire arm; length-mismatch panics for both forms.ndarray::simd. W1a family-shape deviation recorded in.claude/blackboard.md(same rationale asmask_andnot, 2026-08-18).2. Contiguous fast path in
eq_u32_strided_to_maskAt
stride_bytes == 4the kernel gathered 16 bounds-checked scalaru32reads into a temporary array before theU32x16compare — a copy where a cast belonged. That is exactly the shape of every lane in a facet-major columnar store, so lance-graph-java's minor-10 store was contiguous and still being read as strided. Now one fixed[u8; 64]window per 16 elements (safetry_into, bounds proven up front) → a single vector load. Existingeq_u32_strided_stride4_matches_contiguous_primitiveparity test covers it; nounsafe.Measured
lance-graph-java
columnar_hop_bench, 65 536 rows × 32 facets, equivalence asserted before timing, both changes together:16 MB of lane read per hop: 2.1 GB/s → ~13 GB/s.
Gates
cargo fmt --checkclean ·cargo clippy --lib --features std -- -D warningsclean ·cargo test --lib --features std2272 passed.🤖 Generated with Claude Code
https://claude.ai/code/session_016WkNBjHc2e3zuyz9i8qJEv
Generated by Claude Code
Summary by CodeRabbit
New Features
Performance
Compatibility