Repository navigation
Shuffle throughput at genome scale (#876) - #877
Merged
Merged
Conversation
…ter (#876) The scatter opened, appended to and closed a file per bucket per mate for every full buffer: ~650k open/close cycles at genome scale. The shuffle stage took 2h12m on Delta Lustre against 7 min for concatenation (how much of that is the design and how much was that night's filesystem is being measured separately). Now: - one append-only scatter log per mate, with an in-memory index of each bucket's segments, read back in fill order; - full buffers compress on a worker pool while the reader continues; - shuffled buckets go straight into the output through an in-order writer, removing the final copy; - each phase logs its elapsed time. Output is byte-identical to the previous implementation (chr21, 20x, both mates). Also fixes a deadlock in the first draft of this change, where the channel sender outlived the thread scope. Co-Authored-By: Claude <noreply@anthropic.com>
… stage (#876) One run put the shuffle at 2h12m against 6m46s for concatenation, but the shuffled run had TMPDIR on Lustre and the baseline did not, on a night of filesystem work. This runs shuffle off, the #875 shuffle and the #876 rewrite side by side (9-task array, %3, one of each per round) with TMPDIR on scratch for all, from the same config, and records the stage time, wall time, peak RSS, output sizes and an md5 per task. Co-Authored-By: Claude <noreply@anthropic.com>
…level 1 (#876) Benchmark 23620433 (256.6M pairs, Delta Lustre, TMPDIR on scratch): concatenation ~400 s; the merged shuffle 2530-2578 s; the single scatter log 4358-4479 s, of which shuffle-and-write was 3982-4090 s, from ~650k small random reads of bucket segments scattered across the log. Now each bucket has its own file again, so pass 2 reads sequentially. Files stay open when 2*K + 64 fits the soft open-file limit (read from /proc/self/limits; 256 assumed elsewhere) and are reopened per append otherwise. Appends wait their turn so segments land in fill order. An abort flag releases any waiter when another thread fails. The worker pool and the in-order writer are kept. Pass 2 decompresses a bucket whole and scans for record boundaries. Bucket files now use libdeflate level 1. Both earlier versions used CompressionLvl::fastest(), which is level 0 (stored), and wrote ~164 GB of uncompressed temp data at that scale. Output stays byte-identical to the merged shuffle (chr21 20x, both mates). shuffle_bench runs %2: three at once exceeded the scratch quota. Co-Authored-By: Claude <noreply@anthropic.com>
Collaborator
Author
Benchmark 23620433, and a v3 design (f76f9ca)Results, 256.6M pairs, Delta,
Found while reading the phase logs: bucket files used v3:
Local evidence (chr21, 20×):
The workspace suite (65 test binaries), clippy and fmt all pass. The genome-scale rerun is next, with |
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.
Closes #876 (close by hand on merge to
develop).The shuffle merged in #875 made writing the final FASTQs ~6× slower than plain concatenation at genome scale. This PR cuts that to ~2.2×, and the output stays byte-identical to #875.
Change (
fastq_shuffle.rs)2K + 64fits the soft open-file limit (read from/proc/self/limits). Otherwise each append reopens the file. Shuffle gen-reads FASTQ output by default (shuffle_fastq, #870) #875 opened, appended to and closed a file per bucket per mate for every full buffer.CompressionLvl::fastest(), which is level 0 (stored), so it wrote ~164 GB of uncompressed temp data at this scale. The bug is still ondevelopuntil this merges.shuffle scatter: …,shuffle and write: …).Evidence at genome scale:
shuffle_bench23673810256.6M pairs (T2T-CHM13 at 21×), 64 CPUs,
TMPDIRon Lustre scratch, three rounds. Each round runs one task per condition. All 9 tasks COMPLETED with exit 0.develop58eba13)d486c0023b96) and the same sizes for both mates in all six runs.Evidence (local)
ulimit -n 48and drives 512 paired buckets through the reopen path;tests/fastq_shuffle_output.rs).-D warningsand fmt pass.Also here
scripts/delta/shuffle_bench.sbatch, the replicated benchmark above (%2, because three tasks at once exceeded the scratch quota).docs-site/src/gen-reads/fastq-shuffling.mdnow gives the genome-scale cost.Not verified
/usr/bin/timeread a constant 13.7 GB for every condition, and sacct MaxRSS is noisy (59–112 GB across all conditions). Neither isolates the shuffle.🤖 Generated with Claude Code