Skip to content

Add a portable SIMD block index for forward overlap queries - #27

Draft
sstadick wants to merge 22 commits into
masterfrom
worked/portable-simd-index
Draft

Add a portable SIMD block index for forward overlap queries#27
sstadick wants to merge 22 commits into
masterfrom
worked/portable-simd-index

Conversation

@sstadick

@sstadick sstadick commented Jul 28, 2026

Copy link
Copy Markdown
Owner

A Note On AI 🤖

I used agents extensively to benchmark different possible implementations and try out different indexing methods etc. The two key ideas were, surprisingly, my own, using the block-based index and inter-block simd comparisons.

I'm still conflicted about having agents do any of this, as this is not a library that has been touched by AI previously, and I don't know how dependents on this lib feel about agentically written code. If you have strong feelings and read this, open an issue and lets discuss it.

Summary

This replaces the original max_len-bounded forward scan with an always-on
32-interval block index while preserving rust-lapper's existing borrowed,
start-ordered iterator identity.

Blocks that are certainly before a query are skipped using exact maximum-end
summaries and forward next-greater links. Dense active prefixes are returned
directly, while mixed blocks are classified with an exact 32-bit overlap mask.
The mask backend uses AArch64 NEON, runtime-dispatched x86-64 AVX2, or an exact
scalar fallback.

Compatibility

  • The public query API and forward result order remain unchanged.
  • All primitive signed and unsigned coordinate types use specialized SIMD
    kernels where supported.
  • Custom PrimInt implementations use the scalar mask.
  • Constructors, insertion, merging, and deserialization rebuild the derived
    index.
  • Serde retains the original six-field representation.
  • There is no workload heuristic or user-visible mode.

The branch adds an I: 'static bound for safe TypeId-based primitive
dispatch. Stable Rust cannot specialize primitive SIMD kernels while retaining
a blanket custom-PrimInt fallback, so the bound is accepted and documented.
It excludes lifetime-carrying coordinate types, not short-lived Lapper
values.

Performance

Apple M3/AArch64 medians versus rust-lapper 1.3.0:

Dataset Original total This branch total Speedup
1-2 8.534 ms 5.729 ms 1.49x
7-3 5,075.695 ms 66.385 ms 76.46x
8-7 920.998 ms 588.766 ms 1.56x

All implementations returned identical overlap counts. Baseline and final
values came from separate controlled runs, so they are orientation numbers
rather than paired percentage estimates.

Validation

  • cargo fmt --all -- --check
  • cargo test --all-features
  • cargo clippy --all-targets --all-features -- -D warnings
  • AArch64 assembly inspection and native comparative benchmarks
  • Native AArch64 NEON execution on Apple and GitHub ARM64 runners
  • Native AVX2 execution and primitive-mask verification on an AMD EPYC 7763
  • x86-64 scalar dispatch and full tests under a QEMU Nehalem CPU model
  • Rust 1.59 MSRV and current-stable all-feature tests
  • Default, serde-only, unstable-sort-only, and all-feature configurations
  • i686, PowerPC64LE, and Wasm scalar-fallback compilation

Native Intel/AMD AVX2 performance validation remains outstanding.

Production gates

The exact five-gate checklist is recorded in plans/productionization.md:

  1. In progress: AVX2 correctness is native; native x86 performance and a
    physical non-AVX2 host remain.
  2. Complete: the declared MSRV is Rust 1.59.
  3. Complete: the documented I: 'static bound is accepted.
  4. Complete: construction-time cached dispatch regressed all three
    workloads and was rejected.
  5. Complete: the expanded final CI matrix is green.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant