Parallelism changes who runs a WorkUnit and when it finishes. It does not change the plan, within-unit hit stream, or the ordinal order observed by the emitter.
WHAT GOES IN: Planned reference bins and work units, the worker count, and the class of every device the run uses. WHAT HAPPENS: On matching dedicated devices, count quotas give each worker whole bins first, then contiguous query slices; otherwise the longest bins go to the currently lightest worker. Ties break deterministically. WHAT COMES OUT: One ordered list of visits per worker, each a reference bin and a slice of its query bins. INVARIANT: Every WorkUnit has exactly one owner; a bin split across workers costs an extra reference build, never a different unit.
Readable journey
H.1 — Assign whole bins or unit slices
- what goes in
- Planned reference bins and work units, the worker count, and the class of every device the run uses.
- what happens
- On matching dedicated devices, count quotas give each worker whole bins first, then contiguous query slices; otherwise the longest bins go to the currently lightest worker. Ties break deterministically.
- what comes out
- One ordered list of visits per worker, each a reference bin and a slice of its query bins.
- invariant
- Every WorkUnit has exactly one owner; a bin split across workers costs an extra reference build, never a different unit.
- Plan → Partition policy: bins, units, device classes
- Partition policy → Worker 0: bin + query-slice visits
- Partition policy → Worker 1: bin + query-slice visits
H.2 — Build reference-scoped state once per visit
- what goes in
- One worker's next visit: a reference bin and its records, or that bin's arrays in an `hspZ index`.
- what happens
- The worker packs the bin and builds its stable SeedTable, or loads both from the index, then creates an Engine and uploads reference-scoped buffers.
- what comes out
- One initialized GPU engine ready for every query bin of the visit.
- invariant
- Builds plus index loads, engine creations, and reference uploads each equal the visit count, which is the bin count under whole-bin ownership.
- Worker → Bin packer: next visit's reference bin
- Bin packer → SeedTable: packed reference bases
- SeedTable → GPU Engine: stable index + positions
- GPU Engine → Worker: reference-ready engine
H.3 — Reuse the engine across query work
- what goes in
- One reference-ready Engine and the visit's query bins (every planned query bin under whole-bin ownership).
- what happens
- Each query bin is packed, reverse-complemented, split into intervals and batches, then run on both requested strands.
- what comes out
- One completed Pass for each reference-bin × query-bin WorkUnit.
- invariant
- WorkUnits execute in the plan's query-bin order within each visit; with `--query-list`, jobs follow list order inside each bin.
- Query bins → Interval batches: pack + forward/reverse intervals
- Interval batches → GPU Engine: ordered seed batches
- GPU Engine → UnitOutput: plus/minus accepted HSPs
H.4 — Overlap only order-neutral work
- what goes in
- The current GPU batch and the next query-seed or reference-bin preparation.
- what happens
- Seed upload and the next visit's reference build or index load can overlap current kernels; host dependencies still synchronize at count boundaries.
- what comes out
- Less exposed host/copy time without changing the batch sequence.
- invariant
- Overlap never reorders MAX_HITS chunks, survivor compaction, or returned HSP vectors.
- Current GPU batch → Next seed upload: overlap independent DMA
- Current GPU batch → Next reference build or load: overlap independent CPU work
- Current GPU batch → Required host boundary: block sums or survivor counts
- Required host boundary → Current GPU batch: ordered continuation
H.5 — Replay results by ordinal
- what goes in
- UnitOutputs arriving from workers in arbitrary completion order.
- what happens
- The coordinator buffers results by WorkUnit ordinal and releases only the next expected unit to the emitter (one per job with `--query-list`); a duplicate or out-of-plan unit is an error.
- what comes out
- Deterministic partition history, filenames, tar entry order, and output bytes.
- invariant
- GPU completion order is never observable in the emitted segment set.
- Worker 1 → Ordinal buffer: unit 3 completes
- Worker 0 → Ordinal buffer: unit 2 completes
- Ordinal buffer → Emitter: release unit 2
- Ordinal buffer → Emitter: release unit 3