Push zpwxxpnpktps #67

Merged
coissac merged 46 commits from push-zpwxxpnpktps into main 2026-08-17 09:41:42 +00:00
4 changed files with 104 additions and 127 deletions
Showing only changes of commit 0e2e3b5bae - Show all commits
+13 -13
View File
@@ -1,5 +1,3 @@
use rayon::prelude::*;
use obikpartitionner::KmerPartition;
use obisys::progress_bar;
@@ -74,24 +72,26 @@ impl KmerIndex {
let layer_dirs = self.sibling_layer_dirs()?;
let pb = progress_bar("snp_pseudo_alignment", layer_dirs.len() as u64, "layers");
// `Vec<Vec<u8>>` per layer, one entry (column) per variable family;
// `par_iter().map(...).collect()` on this indexed source preserves
// input order, so concatenating the results below in order gives a
// single deterministic column order across the whole index.
let partials: Vec<Vec<Vec<u8>>> = layer_dirs
.par_iter()
.map(|layer_dir| -> OKIResult<Vec<Vec<u8>>> {
// One layer at a time, not `par_iter()` over layers — same
// rationale as `build_sibling_annex`: running many layers'
// `scan_layer_families` concurrently would each group their own
// lookups by partition internally, but interleave those sweeps
// across layers at the OS level, scattering page-cache access over
// every partition at once again and defeating the whole point of
// the grouping. `Vec<Vec<u8>>` per layer, one entry (column) per
// variable family, appended in layer order for a single
// deterministic column order across the whole index.
let mut partials: Vec<Vec<Vec<u8>>> = Vec::with_capacity(layer_dirs.len());
for layer_dir in &layer_dirs {
let families = scan_layer_families(layer_dir, n_parts, n_genomes, with_counts, k, &cache)?;
let columns = families
.into_iter()
.filter(|f| f.mask.family_size() >= 2) // monomorphic family — no signal, skip
.map(|f| f.genome_mask.iter().map(|&m| iupac_code(m)).collect())
.collect();
partials.push(columns);
pb.inc(1);
Ok(columns)
})
.collect::<OKIResult<Vec<_>>>()?;
}
pb.finish_and_clear();
let mut sequences: Vec<Vec<u8>> = vec![Vec::new(); n_genomes];
+7 -7
View File
@@ -1,5 +1,4 @@
use ndarray::Array2;
use rayon::prelude::*;
use obikpartitionner::KmerPartition;
use obisys::progress_bar;
@@ -77,9 +76,11 @@ impl KmerIndex {
let layer_dirs = self.sibling_layer_dirs()?;
let pb = progress_bar("cardinality_tally", layer_dirs.len() as u64, "layers");
let partials: Vec<[[u64; 5]; 5]> = layer_dirs
.par_iter()
.map(|layer_dir| -> OKIResult<[[u64; 5]; 5]> {
// One layer at a time — see `snp_pseudo_alignment`'s comment for why
// `par_iter()` over layers would defeat `scan_layer_families`'s
// partition-grouped locality.
let mut partials: Vec<[[u64; 5]; 5]> = Vec::with_capacity(layer_dirs.len());
for layer_dir in &layer_dirs {
let families = scan_layer_families(layer_dir, n_parts, n_genomes, with_counts, k, &cache)?;
let mut counts = [[0u64; 5]; 5];
@@ -112,10 +113,9 @@ impl KmerIndex {
}
}
partials.push(counts);
pb.inc(1);
Ok(counts)
})
.collect::<OKIResult<Vec<_>>>()?;
}
pb.finish_and_clear();
let mut total = [[0u64; 5]; 5];
+13 -14
View File
@@ -1,5 +1,4 @@
use ndarray::Array2;
use rayon::prelude::*;
use obikpartitionner::KmerPartition;
use obisys::progress_bar;
@@ -50,8 +49,11 @@ impl KmerIndex {
/// should only reflect genuine SNP-adjacent agreement, not the
/// genome-wide invariant background, need it (see
/// [`base_pair_tally`](Self::base_pair_tally)'s `same` field). Layers
/// are processed in parallel (rayon); each gets its own accumulator
/// from `zero()`, combined pairwise via `combine`.
/// are processed one at a time, not in parallel — see
/// `snp_pseudo_alignment`'s comment for why `par_iter()` over layers
/// would defeat `scan_layer_families`'s partition-grouped locality;
/// each layer gets its own accumulator from `zero()`, combined
/// pairwise via `combine`.
fn scan_family_pairs<Acc, F, C>(
&self,
label: &str,
@@ -81,11 +83,13 @@ impl KmerIndex {
let layer_dirs = self.sibling_layer_dirs()?;
let pb = progress_bar(label, layer_dirs.len() as u64, "layers");
let partials: Vec<Acc> = layer_dirs
.par_iter()
.map(|layer_dir| -> OKIResult<Acc> {
let mut acc = zero();
// One layer at a time — see `snp_pseudo_alignment`'s comment for why
// `par_iter()` over layers would defeat `scan_layer_families`'s
// partition-grouped locality.
let mut total = zero();
for layer_dir in &layer_dirs {
let families = scan_layer_families(layer_dir, n_parts, n_genomes, with_counts, k, &cache)?;
let mut acc = zero();
for family in &families {
let variable = family.mask.family_size() >= 2;
@@ -109,16 +113,11 @@ impl KmerIndex {
}
}
total = combine(total, acc);
pb.inc(1);
Ok(acc)
})
.collect::<OKIResult<Vec<_>>>()?;
}
pb.finish_and_clear();
let mut total = zero();
for partial in partials {
total = combine(total, partial);
}
Ok(total)
}
+5 -27
View File
@@ -1,5 +1,3 @@
use rayon::prelude::*;
use obikpartitionner::KmerPartition;
use obisys::progress_bar;
@@ -58,18 +56,15 @@ impl KmerIndex {
let cache = PartitionCache::build(&partition, n_parts, with_counts)?;
let layer_dirs = self.sibling_layer_dirs()?;
// One layer's worth of work, parallelised across layers with Rayon
// — independent, read-only, each producing its own partial tally
// merged at the end.
// One layer at a time, not parallelised across layers — see
// `snp_pseudo_alignment`'s comment for why `par_iter()` over layers
// would defeat `scan_layer_families`'s partition-grouped locality.
let pb = progress_bar("sibling_annex_stats", layer_dirs.len() as u64, "layers");
let partials: Vec<SiblingAnnexStats> = layer_dirs
.par_iter()
.map(|layer_dir| -> OKIResult<SiblingAnnexStats> {
let mut stats = SiblingAnnexStats {
per_genome: vec![[0u64; 4]; n_genomes],
..Default::default()
};
for layer_dir in &layer_dirs {
let families = scan_layer_families(layer_dir, n_parts, n_genomes, with_counts, k, &cache)?;
for family in &families {
// "Genome g represents this family" means g carries
@@ -83,27 +78,10 @@ impl KmerIndex {
}
}
}
pb.inc(1);
Ok(stats)
})
.collect::<OKIResult<Vec<_>>>()?;
}
pb.finish_and_clear();
let mut stats = SiblingAnnexStats {
per_genome: vec![[0u64; 4]; n_genomes],
..Default::default()
};
for part in partials {
for s in 0..4 {
stats.counts[s] += part.counts[s];
}
for g in 0..n_genomes {
for s in 0..4 {
stats.per_genome[g][s] += part.per_genome[g][s];
}
}
}
Ok(stats)
}
}