Skip to content

perf(index): parallelize the SA-to-BWT pipeline with OpenMP - #8

Draft
nh13 wants to merge 2 commits into
masterfrom
feat/index-threads-v2
Draft

perf(index): parallelize the SA-to-BWT pipeline with OpenMP#8
nh13 wants to merge 2 commits into
masterfrom
feat/index-threads-v2

Conversation

@nh13

@nh13 nh13 commented Jun 25, 2026

Copy link
Copy Markdown
Owner

Rebuilt from lh3/minibwa#8, which Heng closed unmerged on 2026-06-15.
Heng's closing rationale: "No homebrew-specific code. No openmp except in libsais."
Recreated as a draft in this fork (nh13/minibwa) for continued development.


This is the parallel SA→BWT index build from lh3#8, rebuilt on top of current master rather than recreated as-is. The original branch couldn't be cleanly re-applied (it conflicted with dc58b55, which had since landed the 32-bit suffix array, and it carried macOS/Homebrew build glue that is no longer needed).

What changed vs. the original lh3#8

  • Kept the OpenMP parallel pipeline — the actual value of the PR. Heng declined OpenMP outside libsais upstream; that constraint does not apply on this fork, so the parallelism stays.
  • Dropped the macOS/Homebrew libomp autodetection in the Makefile and the build-macos CI job. Current master's existing omp probe already defines -DLIBSAIS_OPENMP and adds -fopenmp to every object (including index.o/bwt.o) when the compiler supports it, so no build-system changes are needed.
  • Reconciled the 32-bit suffix array with dc58b55 (already on master) instead of re-introducing the branch's own copy — mb_bwt_libsais now uses master's use_int32 logic.
  • Dropped the separate mb_bwt_libsais_serial fast-path; the single parallel-structured path handles n_thread <= 1 (and the no-OpenMP build) correctly, keeping the 32-bit SA in all cases.

Pipeline

Parallel seq fill → libsais → free seq[] → fused SSA sampling + BWT inversion (reads bases via l2b so seq[] is freed first) → byte-pack the wide SA to one byte per BWT char → mb_bwt_init_from_inverted_sa (new), which builds the rank dict via a 3-phase parallel scan: per-thread local counts → serial prefix-sum → per-thread offset fixup.

Validation (bit-identical gate)

Output is byte-identical to the serial mb_bwt_init_from_raw path for every thread count. Verified against a golden index captured from pre-change master:

  • index over default / --meth / -u 6 / -l variants — .l2b and .mbw hashes match.
  • genbwt -t {1,2,4,8} on chrM and a 2 Mbp synthetic reference (~15.6k 128-bp blocks, exercising the parallel prefix-sum) — every thread count byte-identical to -t1 and to the golden .mbw.
  • Tested both a no-OpenMP build (new code path executes serially) and an OpenMP build (real multithreading).

Does not touch the ksw2 SW kernels, so the differential kernel gate does not apply.

Note: the parallel speedup itself (the original PR measured ~3× from 1→16 threads on hg38) was not re-benchmarked here — local validation focused on correctness and cross-thread determinism. A fresh large-reference benchmark would need hg38-scale input.

Parallelize the post-libsais index build: parallel seq fill, fused SSA
sampling + BWT inversion (reads bases via l2b so seq[] frees early),
byte-packed compaction of the wide suffix array, and a new
mb_bwt_init_from_inverted_sa that builds the rank dict via a 3-phase
parallel scan (per-thread local counts, serial prefix-sum, per-thread
offset fixup). OpenMP is gated on LIBSAIS_OPENMP, which the existing
Makefile probe already defines when the compiler supports -fopenmp, so
no build-system changes are needed.

Output is byte-identical to the serial mb_bwt_init_from_raw path for any
thread count; validated bit-identical against the pre-change index over
default/--meth/-u/-l variants and genbwt -t {1,2,4,8} on chrM and a
2 Mbp synthetic reference.
libminibwa.a now contains OpenMP code from the parallel SA-to-BWT pipeline, so
the api-test example programs must link the OpenMP runtime. Without this,
`make -C api-test` fails at link time wherever OpenMP is actually enabled --
Linux with gcc -- while passing on macOS, where the probe finds no libomp and
the pragmas compile to nothing.

Mirrors the parent Makefile's detection so the setting matches the library that
was built.
@nh13 nh13 added the feature review vehicle for a manifest feature; never a merge vehicle label Aug 3, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

feature review vehicle for a manifest feature; never a merge vehicle

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant