Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
213 commits
Select commit Hold shift + click to select a range
badab88
docs(spec): Phase 2 rust migration — genotype assembly + variant gath…
d-laub Jun 24, 2026
cf94947
docs(plan): Phase 2 rust migration implementation plan
d-laub Jun 24, 2026
c3e48b6
test(parity): tuple-aware kernel parity helper for Phase 2 kernels
d-laub Jun 24, 2026
2fedcb2
perf(genotypes): port get_diffs_sparse numba->rust (parity-gated)
d-laub Jun 24, 2026
e31a1dc
perf(genotypes): port choose_exonic_variants numba->rust (parity-gated)
d-laub Jun 24, 2026
5928012
refactor(genotypes): delete dead filter_af kernel + its dead test (su…
d-laub Jun 24, 2026
a95f4f8
perf(variants): port _gather_v_idxs(+_ss) numba->rust as gather_rows …
d-laub Jun 24, 2026
04f9537
perf(variants): port _gather_alleles numba->rust (parity-gated)
d-laub Jun 24, 2026
dac8a40
fix(variants): gather_rows must preserve data dtype (dosage/custom fi…
d-laub Jun 24, 2026
d8f62a8
perf(variants): port _compact_keep numba->rust (i32/f32, dtype-preser…
d-laub Jun 24, 2026
96e4bd8
perf(variants): port _fill_empty_scalar + _fill_empty_fixed numba->ru…
d-laub Jun 24, 2026
1f18908
perf(variants): port _fill_empty_seq numba->rust (u8/i32, dtype-prese…
d-laub Jun 24, 2026
8ea3683
test(parity): variants-mode dataset backstop (spy-guarded, byte-ident…
d-laub Jun 24, 2026
edb5432
fix(test): update stale _gather_v_idxs_ss import after Task 5 rename;…
d-laub Jun 24, 2026
ca16083
docs(roadmap): Phase 2 parity-verified; switch to persistent rust-mig…
d-laub Jun 24, 2026
f9f58f6
test(parity): narrow AF-backstop except to KeyError (fail loudly on r…
d-laub Jun 24, 2026
ed1f5cb
docs(spec): Phase 3 reconstruction + track realignment design
d-laub Jun 24, 2026
057f546
docs(plan): Phase 3 reconstruction + track realignment implementation…
d-laub Jun 24, 2026
fb88357
perf(reference): port padded_slice numba->rust core (cargo-tested)
d-laub Jun 24, 2026
d0026cb
perf(reference): port get_reference numba->rust (parity, default rust)
d-laub Jun 24, 2026
378b0f6
fix(reference): revert padded_slice leniency — mirror numba's loud fa…
d-laub Jun 24, 2026
cbd9a84
test(parity): reference-mode + spliced dataset backstop (spy-guarded)
d-laub Jun 24, 2026
0908e66
test(parity): add rust-spy-wiring guard + silence no-op with_tracks w…
d-laub Jun 24, 2026
055ca44
perf(reconstruct): port reconstruct_haplotype_from_sparse core (cargo…
d-laub Jun 24, 2026
0bc0a44
test(reconstruct): cover allele_start_idx==v_len, skip-variant, and k…
d-laub Jun 24, 2026
5db0cce
perf(reconstruct): port reconstruct_haplotypes_from_sparse batch (par…
d-laub Jun 24, 2026
f04bba0
fix(reconstruct): clamp writable_ref when ref_idx past contig end; sk…
d-laub Jun 24, 2026
8a6573e
fix(reconstruct): strengthen SAFETY comments; rename batch test to ma…
d-laub Jun 24, 2026
e49d7c2
fix(reconstruct): guard non-annotated parity test against numba Syste…
d-laub Jun 24, 2026
7bade06
test(parity): haplotypes + annotated-haps dataset backstop (spy-guarded)
d-laub Jun 24, 2026
759aae3
perf(tracks): port xorshift64/hash4 PRNG (direct numba parity)
d-laub Jun 24, 2026
d4d2832
perf(tracks): port apply_insertion_fill (4 strategies) core (cargo-te…
d-laub Jun 24, 2026
8222ef0
docs(tracks): correct REPEAT_5P_NORM precision comment (numba divides…
d-laub Jun 24, 2026
61be95f
perf(tracks): port shift_and_realign_tracks_sparse (parity, default r…
d-laub Jun 24, 2026
070ec6e
fix(tracks): clamp writable_ref when deletion extends past track end
d-laub Jun 24, 2026
ccda82f
test(tracks): raise shift_and_realign parity to 500 examples (harden …
d-laub Jun 24, 2026
e50b1e5
perf(intervals): port tracks_to_intervals RLE numba->rust (parity, de…
d-laub Jun 24, 2026
707f0e8
test(parity): tracks-realign dataset backstop across fill strategies …
d-laub Jun 25, 2026
bceab5b
docs(phase-3): getitem glue audit for haps/tracks fusion
d-laub Jun 25, 2026
8922afa
perf(reconstruct): fused haplotypes __getitem__ kernel (dataset parit…
d-laub Jun 25, 2026
a3c7481
test(reconstruct): add fixed-length fused-haps parity coverage; DRY _…
d-laub Jun 25, 2026
663b344
perf(tracks): fused tracks __getitem__ kernel (dataset parity; throug…
d-laub Jun 25, 2026
f975db0
docs(roadmap): Phase 3 complete — reconstruction+tracks ported, fused…
d-laub Jun 25, 2026
96df43a
style: ruff format + lint fixes (Phase 3 close-out)
d-laub Jun 25, 2026
38c5758
test(parity): exclude numba-undefined under-write domain from reconst…
d-laub Jun 25, 2026
c433314
test(bench): fix captured_realign_tracks fixture after Task 14 fused-…
d-laub Jun 25, 2026
12b56bb
docs(roadmap): link Phase 3 PR #245
d-laub Jun 25, 2026
8afcf98
Merge pull request #245 from mcvickerlab/phase-3-reconstruction
d-laub Jun 25, 2026
58b79b8
docs(spec): Phase 3 close-out — main merge, missing-kernel ports, seq…
d-laub Jun 25, 2026
fea1dde
docs(plan): Phase 3 close-out implementation plan
d-laub Jun 25, 2026
6d6c2a1
Merge remote-tracking branch 'origin/main' into phase-3-reconstruction
d-laub Jun 25, 2026
d62ef84
test(parity): lift obsolete #242 xfails after main clip-fix merge
d-laub Jun 25, 2026
0a73bfa
perf(reference): route Reference.fetch through rust get_reference; dr…
d-laub Jun 25, 2026
b321cb1
perf(reconstruct): fused annotated-haps __getitem__ kernel (dataset p…
d-laub Jun 25, 2026
cf24360
perf(reconstruct): fused spliced-haps __getitem__ kernel (dataset par…
d-laub Jun 25, 2026
cbbb720
build(seqpro): bump to 0.20.0; adopt to_numpy(validate=False) on unif…
d-laub Jun 25, 2026
3fae664
style: ruff format parity test files
d-laub Jun 25, 2026
f9d13b6
docs(roadmap): Phase 3 close-out — honest item status, decisions log
d-laub Jun 25, 2026
6af2dbb
docs: correct intervals_to_tracks stub contract (#242) and annotated-…
d-laub Jun 25, 2026
d4afbff
docs(roadmap): re-measure Phase 3 throughput (close-out) + py-spy opt…
d-laub Jun 25, 2026
ab8454a
docs(roadmap): correct optimization targets — track-interval AoS copy…
d-laub Jun 25, 2026
100ee7b
Merge pull request #246 from mcvickerlab/phase-3-reconstruction
d-laub Jun 25, 2026
bd9f1ff
docs(spec): zero-copy, scale-safe rust read path (gvl format 2.0)
d-laub Jun 25, 2026
4188d42
feat(format)!: store track intervals as struct-of-arrays (gvl 2.0)
d-laub Jun 25, 2026
224d227
feat(open): gate dataset open on format_version major
d-laub Jun 25, 2026
edaef34
feat(migrate): add gvl.migrate for 1.x AoS -> 2.0 SoA
d-laub Jun 25, 2026
99403c6
test(format): migrate remaining integration track tests to SoA
d-laub Jun 25, 2026
c780d93
feat(ffi): zero-copy boundary guard for sample-scale memmaps
d-laub Jun 25, 2026
001f65f
test(ffi): cover combined haps+tracks path in scale-guard
d-laub Jun 25, 2026
6c2863b
perf(haps): cache FFI-ready sub-linear per-variant arrays
d-laub Jun 25, 2026
1b3e355
perf(ffi): skip zero-init of fully-overwritten fused output buffers
d-laub Jun 25, 2026
5b46151
docs: document gvl.migrate + format 2.0 SoA; record throughput
d-laub Jun 25, 2026
e36c487
test(bench): de-noise e2e benchmarks + profile next read-path targets
d-laub Jun 25, 2026
24b6655
build(profiling): switch profile-{haps,tracks,variants} tasks to perf
d-laub Jun 25, 2026
8edb86f
Merge pull request #247 from mcvickerlab/zero-copy-scale-safe-readpath
d-laub Jun 25, 2026
cbe38af
docs(spec): Target 5 tracks-only intervals slice optimization
d-laub Jun 25, 2026
a13db46
docs(spec): target-7 variant-windows rust assembly design
d-laub Jun 26, 2026
dca40b9
docs(spec): Target 6 kernel reverse-complement design
d-laub Jun 26, 2026
685d453
docs(spec): Target 6 kernel reverse-complement design
d-laub Jun 26, 2026
a6a34b0
perf(intervals): paint tracks via raw contiguous slice
d-laub Jun 26, 2026
40e6850
docs(plan): target-7 variant-windows rust assembly implementation plan
d-laub Jun 26, 2026
56c7499
docs(plan): Target 6 kernel-RC implementation plan + spec correction
d-laub Jun 26, 2026
bed29fd
feat(variants): add tokenize/slice_flanks/assemble_alt_window cores
d-laub Jun 26, 2026
cd06bc9
feat(rust): in-place reverse/reverse-complement primitives for read path
d-laub Jun 26, 2026
ca7a0e9
feat(variants): add fetch_windows reference-read helper
d-laub Jun 26, 2026
7b013ff
feat(rust): optional in-kernel RC for get_reference
d-laub Jun 26, 2026
5a7efb0
fix(variants): drop unused ArrayView2 import
d-laub Jun 26, 2026
75024fc
feat(rust): optional in-kernel RC for reconstruct_haplotypes_fused
d-laub Jun 26, 2026
e505a4d
feat(variants): assemble_variants_mode (alt/ref bytes + flank tokens)
d-laub Jun 26, 2026
c0f0c91
feat(variants): assemble_windows_mode (token windows + bare alleles)
d-laub Jun 26, 2026
14bfac7
feat(rust): optional in-kernel reverse for track realign kernel
d-laub Jun 26, 2026
1b84058
docs(roadmap): tick Target 5, record tracks-only ratio
d-laub Jun 26, 2026
a48027c
feat(rust): optional in-kernel RC for annotated haplotype kernel
d-laub Jun 26, 2026
d1fd409
feat(ffi): assemble_variant_buffers_{u8,i32} pyfunctions
d-laub Jun 26, 2026
e6d94d7
docs(roadmap): fill Target 5 PR link (#248)
d-laub Jun 26, 2026
985120d
feat(rust): optional in-kernel RC for spliced haplotype kernel
d-laub Jun 26, 2026
eb63980
Merge pull request #248 from mcvickerlab/opt/target-5-intervals-slice
d-laub Jun 26, 2026
55cceb5
feat(py): assemble_variant_buffers numba oracle, rust shim, and dict …
d-laub Jun 26, 2026
e7123c2
test(parity): strand=-1 fixtures + non-vacuity RC assertions
d-laub Jun 26, 2026
b5cca0a
perf(variants): route windows/variants assembly through one rust call
d-laub Jun 26, 2026
d69e802
test(parity): add strand=-1 spliced fixtures + palindrome self-check
d-laub Jun 26, 2026
90a9d01
test(parity): assemble_variant_buffers mode matrix + live-path spy
d-laub Jun 26, 2026
62f35cb
feat: fold strand RC into rust kernels; numba post-pass retained as o…
d-laub Jun 26, 2026
bd957b7
test(flat): assert one assemble_variant_buffers call for both-window …
d-laub Jun 26, 2026
02497cf
feat(rust): debug_assert to_rc mask length in kernel RC blocks
d-laub Jun 26, 2026
25c32b7
docs(roadmap): record Target 6 RC fold results; gate rayon on 5+6+7
d-laub Jun 26, 2026
0497f48
test(parity): cover realigned-track negative-strand RC; drop dead _ac…
d-laub Jun 26, 2026
53e3a07
docs(roadmap): set Target 6 PR link (#249)
d-laub Jun 26, 2026
e9037f9
docs(roadmap): target 7 done — variant-windows rust assembly, re-meas…
d-laub Jun 26, 2026
3dfa483
Merge remote-tracking branch 'origin/rust-migration' into opt/target-…
d-laub Jun 26, 2026
ab45015
Merge pull request #249 from mcvickerlab/opt/target-6-kernel-rc
d-laub Jun 26, 2026
4e8eb45
docs: add target-5 plan
d-laub Jun 26, 2026
dbb43cb
docs(plan): target-7 variant-windows rust assembly implementation plan
d-laub Jun 26, 2026
4ca09c7
docs(roadmap): link target 7 PR #250
d-laub Jun 26, 2026
234f383
Merge rust-migration into opt/target-7-windows-rust-assembly
d-laub Jun 26, 2026
5ed5429
Merge pull request #250 from mcvickerlab/opt/target-7-windows-rust-as…
d-laub Jun 26, 2026
e0dda18
docs(plan): round-3 instruction-level kernel tuning design
d-laub Jun 26, 2026
7d0f7a4
docs: spec for churn-free rust variant-allele RC
d-laub Jun 26, 2026
b3af9d2
docs: implementation plan for churn-free rust variant-allele RC
d-laub Jun 26, 2026
456db06
build(rust): add [profile.profiling] for perf call-graph attribution
d-laub Jun 26, 2026
d19b6ba
docs(roadmap): round-3 profiling baseline + aggregate target list
d-laub Jun 26, 2026
32612c4
perf(rust): tune intervals_to_tracks — 480→283 instrs, 0.628→0.624 ru…
d-laub Jun 26, 2026
199b603
feat(rust): rc_alleles_inplace core for variant-allele RC
d-laub Jun 26, 2026
856b07c
perf(rust): tune tokenize — 16→4 hot instr/elem, 0.55→0.43 rust÷numba
d-laub Jun 26, 2026
c5f32f6
feat(rust): rc_alleles PyO3 wrapper + registration
d-laub Jun 26, 2026
e6208ee
feat: register rc_alleles dispatch (rust default, seqpro reference)
d-laub Jun 26, 2026
abfe9b4
perf(rust): tune shift_and_realign_tracks_sparse — 550→605 lines (3 d…
d-laub Jun 26, 2026
3f6b468
refactor: route variant-allele RC through dispatched rc_alleles kernel
d-laub Jun 26, 2026
06ef6ff
refactor: drop unreachable spliced variant-RC guard
d-laub Jun 26, 2026
2390b2d
perf(rust): tune slice_flanks — 389→429 total instrs (hot-path: byte-…
d-laub Jun 26, 2026
ab58c46
test(parity): e2e neg-strand variants RC + custom-dummy, rc_alleles l…
d-laub Jun 26, 2026
bca7b96
perf(rust): tune assemble_alt_window — 518→727 asm lines (memcpy-expa…
d-laub Jun 26, 2026
ccb946e
docs(roadmap): variant-allele RC folded onto gvl rust kernel (Target …
d-laub Jun 26, 2026
6c7ae28
perf(rust): tune rc_flat_rows_inplace — 212→283 instrs (vectorized), …
d-laub Jun 26, 2026
fe18c4f
perf(rust): tune reconstruct_haplotypes_from_sparse — 2839→1279 instr…
d-laub Jun 26, 2026
5ab8170
Merge pull request #251 from mcvickerlab/rust-variant-rc-fold
d-laub Jun 26, 2026
d124427
docs(spec): Phase 4 close-out — write/update gate + roadmap reconcile
d-laub Jun 26, 2026
3f45c92
docs(plan): Phase 4 close-out implementation plan
d-laub Jun 26, 2026
1128851
docs(roadmap): record round-3 instruction-level tuning results
d-laub Jun 26, 2026
3242702
docs(roadmap): link round-3 PR #252
d-laub Jun 26, 2026
00310c2
Merge pull request #252 from mcvickerlab/opt/round3-instruction-tuning
d-laub Jun 26, 2026
23e8968
docs(spec): rc_alleles_inplace instruction-level tuning design
d-laub Jun 26, 2026
ccff6af
refactor(write): delete dead legacy track path + splits_sum_le_value
d-laub Jun 26, 2026
32132c9
test(bench): realistic chr22_geuv write/update perf driver
d-laub Jun 26, 2026
18b554f
refactor(rust): extract reverse::rc_row shared helper
d-laub Jun 26, 2026
2ca94c9
perf(rust): fuse rc_alleles_inplace — 186→308 instrs (rc_row inlined)…
d-laub Jun 26, 2026
f92e386
fix(test): add __init__.py to disambiguate test_write collision; ruff…
d-laub Jun 26, 2026
e2a6318
docs(bench): record Phase 4 Carter write/update perf + RSS
d-laub Jun 26, 2026
ce3a97d
docs(roadmap): Phase 4 close-out — write path numba-free, gate captur…
d-laub Jun 26, 2026
bef38f5
docs(roadmap): fill Phase 4 close-out PR link (#253)
d-laub Jun 26, 2026
3b39df1
Merge remote-tracking branch 'origin/rust-migration' into phase-4-clo…
d-laub Jun 26, 2026
a8debf8
docs(roadmap): record rc_alleles_inplace instruction tuning (Target 6…
d-laub Jun 26, 2026
29a5815
Merge pull request #253 from mcvickerlab/phase-4-close-out
d-laub Jun 26, 2026
267e08e
Merge pull request #254 from mcvickerlab/opt/rc-alleles-instruction-t…
d-laub Jun 26, 2026
17f6621
docs: plans
d-laub Jun 26, 2026
4c0cc0b
docs: Phase 5 design (consolidation, numba deletion, rayon, final ben…
d-laub Jun 26, 2026
5afb910
docs: Phase 5 implementation plan (PR1 W1 fully specified; PR2-6 outl…
d-laub Jun 26, 2026
6a50668
test(reconstruct): pin correct full-tail-pad on ref overshoot (failing)
d-laub Jun 26, 2026
2ff618f
fix(reconstruct): pad full tail when ref exhausted, not from index 0
d-laub Jun 26, 2026
7fb3fd6
fix(reconstruct,tracks): pad full tail in numba trailing-fill on ref …
d-laub Jun 26, 2026
6dfe555
test(parity): un-exclude ref-overshoot sub-domain now both kernels pa…
d-laub Jun 26, 2026
f90af86
style: ruff format test_reconstruct_trailing_fill
d-laub Jun 26, 2026
e404e4c
docs(roadmap): record trailing-fill overshoot fix (Phase 5 W1)
d-laub Jun 26, 2026
7327983
docs: link overshoot issue #255; document maturin-rebuild-before-pyte…
d-laub Jun 26, 2026
4646810
Merge pull request #256 from mcvickerlab/phase-5-w1
d-laub Jun 26, 2026
a084a17
docs: Phase 5 W2 plan (reduced scope — #242 already fixed; add max_ji…
d-laub Jun 26, 2026
5d3aa7d
test(parity): cover max_jitter>0 intervals_to_tracks end-to-end (numb…
d-laub Jun 26, 2026
a614820
docs(parity,roadmap): correct stale #242 landmine comments; record W2…
d-laub Jun 26, 2026
8ca0d81
docs(plan): Phase 5 W3 — fuse annotated+spliced reconstruction (bite-…
d-laub Jun 26, 2026
bd21d4e
feat(rust): fuse annotated+spliced haplotype reconstruction into one …
d-laub Jun 26, 2026
7268d1e
docs(roadmap): record annotated+spliced fusion; all 4 reconstruction …
d-laub Jun 26, 2026
8bff090
docs(roadmap): backfill Phase 5 W3 PR number (#258)
d-laub Jun 27, 2026
0503ca7
docs(bench): Phase 5 W4 — final single-thread numba-vs-rust A/B; gate…
d-laub Jun 27, 2026
c37edad
docs(roadmap): backfill Phase 5 W4 PR number (#259)
d-laub Jun 27, 2026
a35f1ed
Merge pull request #257 from phase-5-w2
d-laub Jun 27, 2026
3172337
Merge pull request #258 from phase-5-w3
d-laub Jun 27, 2026
efb87ea
Merge pull request #259 from phase-5-w4
d-laub Jun 27, 2026
f048b53
docs(plan): Phase 5 W5 — consolidation (snapshot + delete numba + ray…
d-laub Jun 27, 2026
494ede6
test(parity): golden snapshot/replay infrastructure (Phase 5 W5)
d-laub Jun 27, 2026
058b7a1
test(parity): freeze kernel-level golden fixtures (Phase 5 W5)
d-laub Jun 27, 2026
e31075c
test(parity): replay kernel-level parity against frozen goldens (Phas…
d-laub Jun 27, 2026
6033984
docs(plan): W5 B3 — replace (not delete) 4 numba dtype-fallbacks with…
d-laub Jun 27, 2026
b8f52c2
test(parity): A4 — replay dataset-level parity against frozen goldens…
d-laub Jun 27, 2026
f7b3c72
docs(plan): W5 B1 — rewrite make_kernel_spy to monkeypatch direct rus…
d-laub Jun 27, 2026
2513aa2
test(parity): freeze PRNG/rc_alleles/assemble goldens; Stage-A snapsh…
d-laub Jun 27, 2026
29a2a4e
docs(plan): W5 B1 — delete dead _harness.py + test_harness_tuple.py w…
d-laub Jun 27, 2026
2ee677a
refactor(dispatch): B1 — replace all get() call sites with direct rus…
d-laub Jun 27, 2026
8133cd2
fix(test): restore generate_goldens regeneration; clean dead GVL_BACK…
d-laub Jun 27, 2026
f85ae47
refactor(backend): B2 — collapse backend-conditional branches; delete…
d-laub Jun 27, 2026
5b386e5
fix(test): drop stale _recon_mod.intervals_to_tracks spy (B2 removed …
d-laub Jun 27, 2026
fb4b1a9
refactor: delete numba kernels; numpy fallbacks for #231 dtype paths
d-laub Jun 27, 2026
70a3f8a
fix(threads): remove conditional numba import; update thread tests fo…
d-laub Jun 27, 2026
06c0963
docs: correct W5 roadmap count (686/35/2) + seqpro-numba caveat; rela…
d-laub Jun 27, 2026
98f3ee5
feat: delete numba backend — rust-only read path (Phase 5 W5)
d-laub Jun 27, 2026
dd7c2ef
fix(env): keep conda numba pin (seqpro needs working libllvmlite); gu…
d-laub Jun 27, 2026
4cde9b9
feat(rayon): parallelize reconstruct_haplotypes_from_sparse with rayo…
d-laub Jun 27, 2026
099f9c7
docs: W5 resume handoff (Stage C / C1 landed)
d-laub Jun 27, 2026
52650f3
fix(rayon): debug_assert offset monotonicity in C1 carve; correct tes…
d-laub Jun 27, 2026
edf0141
feat(rayon): parallelize shift_and_realign_tracks_sparse and tracks_t…
d-laub Jun 27, 2026
aaa4c31
feat(rayon): parallelize get_diffs_sparse + intervals_to_tracks (C3)
d-laub Jun 27, 2026
baffeb3
docs(roadmap): finalize W5 entry (snapshot+delete+rayon); skip fused-…
d-laub Jun 27, 2026
4d88cd9
docs(parity): warn that golden regen must run on a numba-present chec…
d-laub Jun 27, 2026
f4501de
docs(roadmap): backfill W5 PR #260; scope seqpro numba-removal as out…
d-laub Jun 27, 2026
b7d2c00
Merge pull request #260 from mcvickerlab/phase-5-w5
d-laub Jun 27, 2026
3933f1e
docs(spec): Phase 5 rust-migration wrap-up design (W6 + audit + stand…
d-laub Jun 27, 2026
3c4cf29
docs(plan): Phase 5 rust-migration wrap-up implementation plan
d-laub Jun 27, 2026
0932374
docs(roadmap): Phase 5 W6 thin-shim audit — classify remaining PyO3 s…
d-laub Jun 27, 2026
ac052f7
docs(roadmap): verify crate is cargo-testable standalone (Phase 5)
d-laub Jun 27, 2026
0968a0f
docs(roadmap): seqpro-core is already a released crates.io dep (corre…
d-laub Jun 27, 2026
6611540
docs(roadmap): Phase 5 W6 perf re-baseline — rayon serial-vs-multithr…
d-laub Jun 27, 2026
e47d128
docs(roadmap): clarify W6 perf byte-math batch composition; soften bo…
d-laub Jun 27, 2026
60ccd12
docs(roadmap): finalize Phase 5 W6 — set status marker + gate results
d-laub Jun 27, 2026
182393b
Merge pull request #261 from mcvickerlab/phase-5-w6-wrapup
d-laub Jun 27, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -183,3 +183,4 @@ dmypy.json
tests/benchmarks/profiling/*.speedscope.json
tests/benchmarks/profiling/*.memray.bin
tests/benchmarks/profiling/*.flamegraph.html
tests/benchmarks/profiling/*.perf.data
4 changes: 3 additions & 1 deletion CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -168,7 +168,9 @@ pixi run -e dev typecheck
pixi run -e docs doc
```

The build system uses Maturin (Rust + Python). Rust code is compiled automatically when running tests via pixi.
The build system uses Maturin (Rust + Python).

**IMPORTANT — rebuild Rust before testing Rust changes:** `pixi run -e dev pytest` (and `pixi run -e dev test`) do **not** rebuild the Rust extension. After editing anything in `src/`, run `pixi run -e dev maturin develop --release` first, or pytest silently imports the *stale* compiled extension — parity/integration tests then pass or fail against the old binary, not your change. (`cargo test`/`cargo-test` compile from source and are unaffected; this only bites the Python tests that import the extension.)

**Before pushing a change that renames/removes a public symbol or touches shared code, run the full tree** (`pixi run -e dev pytest tests -q`, or the full `pixi run -e dev test`). Scoped runs like `pytest tests/dataset` skip `tests/unit/` (e.g. `tests/unit/dataset/test_build_reconstructor.py`), so a stale reference there fails only in CI.

Expand Down
8 changes: 8 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -29,3 +29,11 @@ features = ["abi3-py310"]

[dev-dependencies]
rstest = "0.26.1"

# Perf call-graph attribution only (`perf report --children`). Inherits release
# codegen and adds line tables + frame pointers. NEVER the gate artifact — all
# throughput/asm gate numbers come from the plain `--release` build.
[profile.profiling]
inherits = "release"
debug = "line-tables-only"
force-frame-pointers = true
326 changes: 326 additions & 0 deletions docs/handoffs/2026-06-25-phase5-getitem-optimization.md

Large diffs are not rendered by default.

78 changes: 78 additions & 0 deletions docs/handoffs/2026-06-27-rust-migration-w5.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
# Handoff — Rust Migration Phase 5 W5 (consolidation PR)

**Written:** 2026-06-27, mid-execution. **Branch:** `phase-5-w5` (off `rust-migration @ efb87ea`, in the MAIN repo, not a worktree).
**Current point:** Stage C (rayon) task **C1 just landed (`4cde9b9`)**; controller-verify + review of C1 is the immediate next step.

## What W5 is

The consolidation PR of the rust migration. One PR (`phase-5-w5` → `rust-migration`), three staged commit-boundaries:
- **Stage A — snapshot** (DONE): froze the numba-oracle parity suites to committed `.npz` goldens; rewrote all parity tests to assert `rust == golden` (importing rust callables directly, never `_dispatch`).
- **Stage B — delete numba** (DONE): removed dispatch layer, backend conditionals, all `@njit`, deps.
- **Stage C — rayon** (IN PROGRESS): add `parallel:bool` batch parallelism to read kernels, gated `serial==parallel==golden`.

## The 3 user decisions (binding)

1. Goldens = **frozen seeded-sample `.npz`** (deterministic hypothesis draw, frozen inputs+outputs).
2. **One PR, staged commits** (not split PRs).
3. Rayon gating = **`parallel:bool` + `RAYON_NUM_THREADS`**, copying the `get_reference` idiom (`src/reference/mod.rs:82-106`: `split_at_mut` chain → `Vec<&mut [_]>` → `into_par_iter`). Serial branch is the byte-identity reference. **Never put raw `*mut` in a rayon closure (not `Send`) — carve `&mut [_]` slices.**
4. (2026-06-27) **seqpro transitively imports numba** → B4 guard RELAXED to "genvarloader's OWN code is numba-free" (source scan); a seqpro follow-up tracks the eager import.

## How to work this (subagent-driven-development)

- **The authoritative records:** the plan `docs/superpowers/plans/2026-06-26-rust-migration-phase-5-w5.md` and the durable ledger `.superpowers/sdd/progress.md` (read this FIRST on resume — it has the blow-by-blow, every commit, every Minor finding, all pending items). Task briefs/reports live in `.superpowers/sdd/task-<ID>-{brief,report}.md`.
- **Per task:** extract brief → dispatch a **Sonnet** implementer (global CLAUDE.md mandates Sonnet for impl) → generate review package → dispatch a **Sonnet** task-reviewer (spec + quality verdicts) → fix Critical/Important → mark complete in the ledger.
- **Brief extraction** (the SDD `task-brief` script only matches numeric `Task N`; our IDs are A1/B1/C1):
```bash
PLAN=docs/superpowers/plans/2026-06-26-rust-migration-phase-5-w5.md
DIR=.superpowers/sdd
awk '/^### Task C2:/ {grab=1} grab && /^### Task C3:/ {exit} grab {print}' "$PLAN" > "$DIR/task-C2-brief.md"
```
- **Review package:** `/carter/users/dlaub/.claude/plugins/cache/claude-plugins-official/superpowers/6.0.3/skills/subagent-driven-development/scripts/review-package BASE HEAD` (BASE = commit before the implementer ran; current next BASE = `4cde9b9`).

## ⚠️ THE LOAD-BEARING LESSON

**Subagent self-reported test/env results are UNRELIABLE — the controller MUST re-run every load-bearing gate.** This stage, 3 of 4 B-stage reports didn't hold up: B2 claimed "686 passed" hiding a real failure; B3 claimed "clean import passed" (false — seqpro pulls numba); B4 claimed "687 passed" but had silently BROKEN the env (removed conda numba pin → broken PyPI llvmlite → `import genvarloader` failed at collection). Each was caught by the controller re-running the gate. **Keep doing this for C1/C2/C3.** Gates take ~4 min (run `run_in_background: true`; foreground sleeps are blocked).

Standing gate command (after any `src/` edit, MUST `maturin develop --release` first or pytest imports the stale `.so`):
```bash
pixi run -e dev maturin develop --release && \
pixi run -e dev pytest tests/parity tests/dataset tests/unit -q --basetemp=$(pwd)/.pytest_tmp
```
Healthy full-tree baseline: **687 passed, 35 skipped, 2 xfailed** (the +1 over 686 is the B4 import-guard). All pytest needs `--basetemp=$(pwd)/.pytest_tmp` (os.link Errno 18 on Carter).

## Commit log (phase-5-w5)

A: `494ede6`(A1) `058b7a1`(A2) `e31075c`(A3) `b8f52c2`(A4) `2513aa2`(A5) + plan amends `6033984`/`f7b3c72`/`29a2a4e`.
B: `2ee677a`+`8133cd2`(B1) · `f85ae47`+`5b386e5`(B2) · `fb4b1a9`+`70a3f8a`+`06c0963`(B3) · `98f3ee5`+`dd7c2ef`(B4).
C: `4cde9b9`(C1 — rayon for `reconstruct_haplotypes_from_sparse`).
Plan itself committed at `f048b53`.

## RESUME MAP (do these in order)

1. **Verify + review C1 (`4cde9b9`)** — controller gate was launched at handoff time (bg task `broitb5yt`, output under the session tasks dir); confirm it's `687 passed / 35 skipped / 2 xfailed`. Then review: `review-package dd7c2ef 4cde9b9`, dispatch a Sonnet reviewer focused on: the 3-buffer `split_at_mut` chunk-carve correctness (Optional annot buffers — the `match` on the 4 presence combos), no raw `*mut` in the rayon closure, the `parallel:bool` threaded through all 5 FFI entries (`src/ffi/mod.rs:481/546/689/782/891`) + 5 Python call sites (`_genotypes.py` + 4 in `_haps.py`), and that `_golden.RUST_KERNELS["reconstruct_haplotypes_from_sparse"]`'s `parallel`-default shim didn't weaken the golden replay. C1 added `tests/parity/test_rayon_equivalence.py`.
2. **C2** — parallelize the track kernels: `shift_and_realign_tracks_sparse` (`src/tracks/mod.rs:470`, outer-query loop) and `tracks_to_intervals` (two-pass @569/@615 — parallelize each pass, keep the cumsum serial). Also thread `parallel` through `intervals_and_realign_track_fused`. Extend `test_rayon_equivalence.py`.
3. **C3** — parallelize `get_diffs_sparse` (`src/genotypes/mod.rs:27`) + `intervals_to_tracks` (`src/intervals.rs:45`). (`get_reference` is ALREADY parallel — no work.) Extend the equivalence test.
4. **C4** — finalize `docs/roadmaps/rust-migration.md` (the W5 entry exists ~line 799 but is partial; correct it to reflect snapshot+delete+rayon, Phase 5 stays 🚧 — W6/PR6 is measure-and-merge); run the full Stage-C gate (full tree + `cargo test --release` + ruff + `cargo clippy` + typecheck + serial==parallel across ALL kernels).
5. **Final whole-branch review** — dispatch the most capable model on `review-package $(git merge-base rust-migration HEAD) HEAD` (merge-base = `efb87ea`). Triage the Minor findings list in the ledger.
6. **superpowers:finishing-a-development-branch** — verify tests, then offer the 4 options. Land into `rust-migration` (NO squash, per the no-squash-merges memory).

## PENDING / must-do at finishing

- **File the seqpro issue** (user authorized): seqpro 0.20.0 eagerly imports numba (`seqpro/_numba.py`, `transforms/tmm.py`) at `import seqpro` → blocks the W6 ~3.2 GB JIT-RSS drop. **`mcvickerlab/seqpro` 404s — ASK the user for the repo** (likely `d-laub/seqpro` or personal). The roadmap currently says "filed as a seqpro follow-up" — correct that wording once actually filed.
- **Optional cleanup (final-review call):** B3 kept *plain-Python shadows* of rust kernels (decorators removed, bodies kept) because `tests/unit/` references them: `reconstruct_haplotype_from_sparse`, `_get_reference_row/_ser/_par`, `_xorshift64`/`_hash4`, `shift_and_realign_track(s)_sparse`, `_gather_v_idxs_ss_numba` (misleading `_numba` suffix). These + their unit tests are redundant with rust (validated by parity goldens) — candidate for deletion, but its own scoped decision.
- **Bench conftest staleness** (non-gated): B2 removed `reconstruct_haplotypes_from_sparse` from `_haps`; `tests/benchmarks/conftest.py:50` still targets `(_haps, "reconstruct_haplotypes_from_sparse")` — fix the capture target (now the fused kernel / `_genotypes`). Benchmarks are opt-in, don't block the gate.

## Plan amendments made during execution (all committed, in the plan file)

- B3 Step 2b: **replace (not delete) 4 numba dtype-fallbacks with numpy** — `_gather_rows`/`_compact_keep`/`_fill_empty_scalar`/`_fill_empty_fixed` in `_flat_variants.py` fall back to numba for arbitrary dtypes (custom VCF FORMAT fields, **issue #231**); these are LIVE production code. Done in B3; gated by the 4 dtype-regression tests in `test_flat_variants_parity.py`.
- B1 Step 2b: rewrote `_golden.py::make_kernel_spy` to monkeypatch the direct rust symbol (registry mutation went inert post-dispatch-deletion).
- B1 Step 2: also deleted dead `tests/parity/_harness.py` + `test_harness_tuple.py` (superseded by `_golden.py`).
- B4: relaxed import-guard to own-code source scan (seqpro decision above).

## Key locations

- Plan: `docs/superpowers/plans/2026-06-26-rust-migration-phase-5-w5.md`
- Ledger (READ FIRST): `.superpowers/sdd/progress.md`
- Goldens: `tests/parity/golden/*.npz`; infra `tests/parity/_golden.py`; regen `tests/parity/generate_goldens.py` (+ `GVL_GEN_GOLDENS=1 pytest tests/parity/test_gen_dataset_goldens.py` for dataset goldens).
- Rust read kernels: `src/reconstruct/mod.rs`, `src/tracks/mod.rs`, `src/genotypes/mod.rs`, `src/intervals.rs`, `src/reference/mod.rs` (rayon reference idiom). FFI: `src/ffi/mod.rs`.
- Master Phase-5 plan (PR5/PR6 scope): `docs/superpowers/plans/2026-06-26-rust-migration-phase-5.md`.
Loading
Loading