MR and model validation on the CPU: workers bounded by their bytes, not the thread count

- The CPU translation function runs as many rotations at once as the host worker pool holds (8 B per
  grid point each, 550 MiB on a 400 A cell; 33 at once at 32 threads was 18 GiB), at most nthreads.
  Counted, not reserved: the rotations run on ParallelFor's pool, whose workers must not wait on memory.
- Null replicates (model validation's and MR's) whose structure factors are made on the CPU reserve
  32 B per point of their grid (ModelGridPoints) against the pool before they start, so the nine
  replicates, and nulls run side by side, hold at most the pool between them.
Every replicate and rotation computes what it did and is stored by index: no result depends on how
many run at once.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PXc1zD1yxHqaR1DGdCTHL4
This commit is contained in:
leonarski_fandClaude Opus 5.5 committed 2026-10-17 09:31:05 +02:00
1 parent 64a87cdf52
commit 43e836573d
5 files changed
+48 -3

No files matched your search

@@ -317,3 +317,10 @@ void PutMaskOnGrid(gemmi::Grid<float> &grid, const gemmi::Model &model, const st
if (shrink_has_offsets)
masker.shrink(grid);
}
size_t ModelGridPoints(const gemmi::UnitCell &cell, const gemmi::SpaceGroup *sg, double d_min, double rate) {
const double spacing = d_min / (2 * rate);
const std::array<int, 3> m = gemmi::good_grid_size({{cell.a / spacing, cell.b / spacing, cell.c / spacing}},
gemmi::GridSizeRounding::Up, sg);
return static_cast<size_t>(m[0]) * static_cast<size_t>(m[1]) * static_cast<size_t>(m[2]);
}