Skip to content

Replace block-aligner with a custom SIMD aligner#612

Closed
NicolasBuchin wants to merge 1 commit into
mainfrom
sim-aligner
Closed

Replace block-aligner with a custom SIMD aligner#612
NicolasBuchin wants to merge 1 commit into
mainfrom
sim-aligner

Conversation

@NicolasBuchin

Copy link
Copy Markdown
Collaborator

Replace block-aligner with a custom SIMD aligner

The piecewise path used block-aligner for the global alignments between anchors and for the x-drop extensions off the first and last anchor. Both now go to src/simdaligner, and the block-aligner dependency is dropped.

The kernel does affine-gap alignment on the difference recurrence of Suzuki & Kasahara (BMC Bioinformatics, 2018). Storing adjacent-cell differences bounds every value by the scoring scheme alone, with no length term, so 8-bit lanes hold at any sequence length. That gives 32 lanes per AVX2 vector with no widening path and no overflow-and-restart. SimdAligner::new rejects schemes that would violate the bound rather than wrap a lane. Note that there is one kernel and no scalar fallback.

Between anchors it is called unbanded, i.e. exact: optimal score under the scheme, no x-drop, no early exit. block-aligner capped its block size, so long anchor gaps could fall back to a heuristic result. Now we guarantee exactness. We also guarantee that among equally scoring alignments the CIGAR returned is the one minimising the edit distance, and it is the exact CIGAR representation strobealign already uses, so there is no translation left and no wrappers in the piecewise aligner.

Off the ends of the chain, x-drop is removed. Instead we use a bandwidth heuristic: extensions against a longer reference are confined to w diagonals off the anchor diagonal, and shorter ones are exact. Within the bandwidth the result is optimal. --xdrop is removed and --bw <N> is added, defaulting to 1024 bandwidth. Note that x-drop also went through a block-length heuristic, so it was never exact either.

Results are in ends.pdf and ends-se-accuracy-table.pdf: single-end align, fruitfly/maize/chrY/CHM13 crossed with sim0/sim4/sim6, 50–30000 bp. Runtime is lower throughout, with the gap widening past ~500 bp and widest on sim6 and chrY. Accuracy is practically unchanged below 15 kb and improves a bit from 25 to 30 kb. On short reads the runtime difference is harder to resolve end to end, since this was run on my laptop, so I also benchmarked the alignment calls directly against block-aligner across a range of sizes: over a corpus of ~1M real between-anchor calls the SIMD kernel is 3.4x faster overall and faster in every size bucket including the smallest, with identical scores.

One caveat: the new aligner is x86_64 and AVX2 only (SimdAligner::is_supported to check, new panics otherwise), and the piecewise aligner imports it unconditionally, so as it stands the crate does not build on aarch64 at all, I need to add arm64 support.

One last mention: the new aligner also comes with a new alignment type, split reference alignment. Not yet in use, but it will probably be needed for duplication detection.

Todo:

  • Arm64 support

@NicolasBuchin
NicolasBuchin marked this pull request as draft July 18, 2026 13:51
The piecewise path used block-aligner for the global alignments between
anchors and for the x-drop extensions off the first and last anchor. Both
now go to src/simdaligner, an AVX2 kernel on a difference recurrence, and
the block-aligner dependency is dropped.

Runtime is lower and the extensions off the ends of the chain are more
accurate. x-drop is not needed any more, so `--xdrop` is removed. The new
`--bw` sets the bandwidth.

Note the new aligner is x86_64-only, where block-aligner also had NEON and
wasm backends.

Is-new-baseline: yes
@NicolasBuchin
NicolasBuchin deleted the sim-aligner branch July 18, 2026 15:41
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