Repository navigation
Speed up Compat::Corrected ends-free (fast kernel, exact pruning); fix #41 - #42
Merged
Merged
Conversation
Corrected mode cost +26-28% instructions (+26-51% time) over C mode on ends-free with match < 0. Profiling showed it was not the extra steps (+0.8%) but the `_best` extend kernel, which called `endsfree_left` on every diagonal. It now walks the offsets like the C-mode kernel and checks `termination_endsfree` first. Overhead on long.seq is now +2-2.5% instructions (+7-12% time); C mode unchanged. Also prune, exactly: from diagonal k at score s any completion totals at least s + M*|k - k_end|, so once there is an end candidate the wavefronts are trimmed to the diagonals that could still beat it, with the dropped cells nulled. Output is byte-identical to unpruned (600 configs over generated pairs and long.seq). Only with no heuristic or BandedStatic, since the other heuristics read the wavefronts. Fix (FIXED_BUGS 14c): null steps no longer end a corrected search while a candidate is pending. With BandedStatic the band (or pruning) can empty every wavefront before begin-free seeds outside it are reached, returning a worse end. Tests: random_long_against_oracle (pruning trims most cells; a band one diagonal narrower fails), banded_static_pending_seeds (fails without the fix), Wavefront::trim_nulled unit test. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The CIGAR buffer is 2 * (|P| + |T|) ops, as in C, and the backtraces write backwards, leaving begin_offset one below the first op. With usize offsets, `max_ops - 1` underflowed when a fresh aligner got an empty pattern and text: a panic in debug builds (release wrapped and happened to return the right result). `cigar_buffer_len` now adds one slot at all three sizing sites, which also covers a completely full buffer. Test: aligner::tests::test_empty_sequences_cigar (edit and affine, high/med/low, end-to-end and ends-free, BiWFA); fails without the fix. The full test suite now passes in debug as well as release. Fixes #41 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Follow-up to #40 (part of #31 / #32). Makes
Compat::Correctedends-free withmatch < 0nearly as fast as C mode, so dada2-rs (HPCBio/dada2-rs#51) can re-measure it against NW.Changes
Faster extend kernel. The corrected-mode overhead (+26–28% instructions, +26–51% time over C mode) wasn't from the extra steps: those were only +0.8% on
long.seq. It came from the_bestextend kernel, which calledendsfree_left(twoOptions, merged) on every diagonal. Samply showed extend at +74%. The kernel now walks the offsets like the C-mode kernel and runs the cheaptermination_endsfreecheck first, counting the bases left only at an end.Exact pruning. From diagonal
kat scores, any completion totals at leasts + M·|k − k_end|(k_end = |T| − |P|). The bases left differ byk − k_endall along a diagonal, and each of them costs at leastM. Once an end candidate exists, every component at each score is trimmed to the diagonals that could still beat it (ties kept), and the dropped cells are set toOFFSET_NULL, so later steps can't read them (Wavefront::trim_nulled). This runs only with no heuristic orBandedStatic, because the other heuristics read the wavefronts.Bug fix (FIXED_BUGS 14c). Null steps no longer end a corrected search while a candidate is pending. With
BandedStatic, the band (or the pruning) can empty every wavefront before begin-free seeds outside it are reached, and the search then returned a worse end. Example: SW 1 instead of 2 ontests/data/corrected_banded_seeds.seq, band-10,200.Fixes Debug panic (subtract overflow) in backtrace when both sequences are empty #41: a fresh aligner given an empty pattern and empty text panicked in debug builds (
usizeunderflow of the backward CIGAR write offset; release builds wrapped and happened to be right).cigar_buffer_lenadds one slot to the C-sized2·(|P|+|T|)buffer at all three sizing sites (FIXED_BUGS 15).test_empty_sequences_cigarcovers edit/affine, high/med/low, end-to-end/ends-free and BiWFA; it fails without the fix.Results
Instructions retired on
long.seq(300 × 2 kb), CIGAR / score-only. I used instruction counts because the machine was loaded for part of this. Wall time is best of 5, interleaved, at load ~3.-5,4,0,8, ends-free 0.1 ×4-1,6,2,4,12,1, ends-free 0.1 ×4, mslong.seqthe first end found is usually near-optimal already. On pairs with random flanks and whole-length free ends, corrected mode is still +15–55% (up to +160% on short pairs) over C mode. In those cases C stops at a wrong, Known issue (C parity): ends-free with whole-length free ends and match < 0 returns the no-overlap alignment #38-style first hit, so the extra search is what makes the result optimal.Verification
#37/#38cases included);long.seq;random_long_against_oracle: 300 pairs up to about 200 bp with flanks, checked against the DP oracle in all memory modes. It fails if the pruning band is one diagonal too narrow.banded_static_pending_seeds: fails without the 14c fix.trim_nulledunit test.cargo test --releaseand clippy are clean. The new code is rustfmt-formatted.main, threecorrected_endsfreetests hit Debug panic (subtract overflow) in backtrace when both sequences are empty #41 in debug).wfa_utest.sh60/60.Fixes #41
🤖 Generated with Claude Code