[WIP] Parallel linclust - #1124
Draft
bbuschkaemper wants to merge 20 commits into
Draft
Conversation
Signed-off-by: Björn Buschkämper <bjoern.buschkaemper@gmail.com>
Signed-off-by: Björn Buschkämper <bjoern.buschkaemper@gmail.com>
Signed-off-by: Björn Buschkämper <bjoern.buschkaemper@gmail.com>
Signed-off-by: Björn Buschkämper <bjoern.buschkaemper@gmail.com>
Signed-off-by: Björn Buschkämper <bjoern.buschkaemper@gmail.com>
Signed-off-by: Björn Buschkämper <bjoern.buschkaemper@gmail.com>
Signed-off-by: Björn Buschkämper <bjoern.buschkaemper@gmail.com>
Signed-off-by: Björn Buschkämper <bjoern.buschkaemper@gmail.com>
Signed-off-by: Björn Buschkämper <bjoern.buschkaemper@gmail.com>
Signed-off-by: Björn Buschkämper <bjoern.buschkaemper@gmail.com>
Signed-off-by: Björn Buschkämper <bjoern.buschkaemper@gmail.com>
Signed-off-by: Björn Buschkämper <bjoern.buschkaemper@gmail.com>
Signed-off-by: Björn Buschkämper <bjoern.buschkaemper@gmail.com>
Signed-off-by: Björn Buschkämper <bjoern.buschkaemper@gmail.com>
Signed-off-by: Björn Buschkämper <bjoern.buschkaemper@gmail.com>
Signed-off-by: Björn Buschkämper <bjoern.buschkaemper@gmail.com>
Signed-off-by: Björn Buschkämper <bjoern.buschkaemper@gmail.com>
…es). Signed-off-by: Björn Buschkämper <bjoern.buschkaemper@gmail.com>
…location during translate keys. Signed-off-by: Björn Buschkämper <bjoern.buschkaemper@gmail.com>
Signed-off-by: Björn Buschkämper <bjoern.buschkaemper@gmail.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.
WIP
TL;DR
This is a work-in-progress parallelization of the linclust algorithm using a multi-node setup with a clustered filesystem (e.g. GPFS, Lustre) without requiring cross-node communication (e.g. MPI) to address limitations when trying to cluster >1e11 sequences on a single node.
Shared-filesystem parallel linclust
Base problem
To cluster 1e11–1e12 sequences on nodes with <2 TB RAM and <1 PB of scratch we run into an issue; several structures are sized by key space or by the whole database:
seqkey_to_len[dbKeySize],countTable,repSequence(kmermatcher.cpp)DBReader::Index[]assignedCluster[dbSize](Align2clust.cpp:445)mergeclusters'std::list<size_t>[N](mergeclusters.cpp:28)Plus a time cost: when the k-mer array does not fit,
kmermatchersplits and re-extracts everyk-mer per split - roughly 68 full extractions at 1e12.
Basic idea
Replace splitting with one scan plus a shuffle, and partition k-mer space rather than sequence
space. The partition of a k-mer is the low bits of the
hashUInt64score kmermatcher alreadycomputes - a pure function of the k-mer - so every occurrence of a k-mer lands in the same
partition, and a partition can be grouped in isolation. The division is lossless, not
approximate, which is what sequence-space sharding cannot offer.
Coordination is files only. Every worker of a stage runs a byte-identical command line;
identity comes from a
fetch_addon a counter file. There is no rank argument and nonode-to-node communication, so a stage maps onto a Slurm array job and workers may join late, die,
or be restarted. Mutual exclusion uses POSIX
fcntl(F_SETLKW)whole-file locks, chosendeliberately over
flock, which is node-local on GPFS and Lustre.Pipeline
Nine new commands driven by one workflow script:
Design decisions
1. Length-ranked dense keys.
createdbparallelemits sequences longest-first, sokey == global length rank. This removes
SORT_BY_LENGTHand its side arrays, lets a companionindex address an entry by key with no resident
.index, and makes stock'slongest-first greedy identical to ascending key order. The clustering collapses to a single
left-to-right sweep needing 2 bits per key instead of 8 bytes: 25 GB at 1e11 against 800 GB.
2. The alignment is keyed by representative range, not by k-mer partition. We implemented the
obvious fused design first and measured it: a k-mer partition's pairs are scattered over the whole
key space, so one partition needed 1.61 GB of sequences but read 83.9 GB - 52× amplification,
essentially the whole database per partition. Bucketing surviving edges by representative key
gives each align worker a contiguous slice (measured 1.15×). Two properties fall out for free:
cross-partition duplicate pairs are removed before aligning, and stock's global
per-
(pair, diagonal)score accumulation is reproduced exactly rather than approximated.3. Sizing is derived, not configured.
--scratch-budgetis the only new scale knob; theextraction wave count and partition count follow from it and
--split-memory-limit. A wavere-extracts every k-mer but keeps only its slice of partition space, so peak scratch is the whole
shuffle divided by the wave count.
Verification
Against stock run on the same database:
semantic difference in
(pair, diagonal)accumulation;1 TB budget;
kill-and-resume;
its own.
Limitations
--cov-mode 1or2only. Symmetric coverage modes make linclust selectSET_COVERplusthe count-table rounds; we implement neither, so the command refuses them.
alignparallelrejects nucleotides.createdb --shuffle 0, where it is exact.createdb's default32-way shuffle changes which of several equal-length sequences wins a tie, and
createdbparalleldoes not reproduce it.representative<TAB>memberin accessions, not a cluster DB - a per-key index isa state no single node can hold at this scale.
NULLparameters and guardedbranches in
kmermatcher.{cpp,h}, andparsePrecisionLibde-duplicated intoMatcher.cpp.Both checked behaviour-preserving -
lincluston 1M sequences produces aclusters.tsvbyte-identical to a reference binary built from the base commit. Separately,
Parameters.cpprelaxes
checkIfDatabaseIsValidso amkdirrace is tolerated when the directory alreadyexists; this affects every command with a directory output validator and fixes a real
Slurm-array race.