diff --git a/image_analysis/scale_merge/AnisotropyAnalysis.cpp b/image_analysis/scale_merge/AnisotropyAnalysis.cpp index 77c4b2758..18d4adfd7 100644 --- a/image_analysis/scale_merge/AnisotropyAnalysis.cpp +++ b/image_analysis/scale_merge/AnisotropyAnalysis.cpp @@ -2,6 +2,7 @@ // SPDX-License-Identifier: GPL-3.0-only #include "AnisotropyAnalysis.h" +#include "../../common/ParallelFor.h" #include #include @@ -1029,7 +1030,8 @@ namespace { std::vector ScaledObservations(const std::vector &outcomes, bool rotation, const gemmi::SpaceGroup *space_group, - float wedge_deg, double min_partiality) { + float wedge_deg, double min_partiality, + size_t nthreads) { // Per-image scale, indexed the way the outcomes are. std::vector g(outcomes.size(), 0.0); for (size_t i = 0; i < outcomes.size(); ++i) @@ -1105,20 +1107,27 @@ std::vector ScaledObservations(const std::vector parts; - // Reserve what the sample holds rather than letting the vector grow: the growth chain copies a few - // hundred megabytes on a large sweep. - parts.reserve(std::min(n_parts, MAX_SAMPLE_PARTS)); - for (size_t i = 0; i < outcomes.size(); ++i) { + // Each image's sample on its own thread, then joined in image order - the same parts in the same + // order as one loop over the images. + std::vector> image_parts(outcomes.size()); + ParallelFor(static_cast(outcomes.size()), nthreads, [&](int i) { if (!(g[i] > 0.0)) - continue; + return; for (const auto &r : outcomes[i].reflections) { if (!usable(r)) continue; if ((MixKey(asu_key(r.h, r.k, r.l).pack()) & sample_mask) != 0) continue; - parts.push_back({r.h, r.k, r.l, r.image_number, &r, i}); + image_parts[i].push_back({r.h, r.k, r.l, r.image_number, &r, static_cast(i)}); } + }); + std::vector parts; + // Reserve what the sample holds rather than letting the vector grow: the growth chain copies a few + // hundred megabytes on a large sweep. + parts.reserve(std::min(n_parts, MAX_SAMPLE_PARTS)); + for (auto &v : image_parts) { + parts.insert(parts.end(), v.begin(), v.end()); + std::vector().swap(v); } std::sort(parts.begin(), parts.end(), [](const Part &a, const Part &b) { return std::tie(a.h, a.k, a.l, a.image_number) < std::tie(b.h, b.k, b.l, b.image_number); diff --git a/image_analysis/scale_merge/AnisotropyAnalysis.h b/image_analysis/scale_merge/AnisotropyAnalysis.h index 742202d8c..61f5573ca 100644 --- a/image_analysis/scale_merge/AnisotropyAnalysis.h +++ b/image_analysis/scale_merge/AnisotropyAnalysis.h @@ -150,7 +150,8 @@ std::vector ScaledObservations(const std::vectorGetIntegrationOutcome(), experiment_.IsRotationIndexing(), twin_sg, experiment_.GetGoniometer() - ? experiment_.GetGoniometer()->GetWedge_deg() : 0.0f), + ? experiment_.GetGoniometer()->GetWedge_deg() : 0.0f, + 0.5, config_.nthreads), *result.consensus_cell, twin_sg, aniso_run); stats_text << AnisotropyToText(sm.statistics.anisotropy) << "\n"; }