Refinement: the weight trials' own slots made while the placement runs

Bitwise. MakeOwnSlot copies the model as it was before the topology and reads only what the placement does not
change (cell, reflections, the engine's kind, the B ceiling), so the slots are now built on their threads right
after the start score, beside the rigid-body and group-B placement, and joined where they were built before
(also where the placement throws). The "slots" stage goes from 0.23 s to 0 on 9yl4; the placement is not
slowed (0.59 -> 0.60 s). Refined CIF md5 unchanged on 5reo, 5f6m, 9yl4, 7d98, 5f6m MD start (GPU) and 6o2h
(CPU); side by side = one at a time. Wall: 5reo 1.46-1.53 -> 1.54, 5f6m 2.26 -> 2.21, 9yl4 7.03 -> 6.83, 7d98
3.65 -> 3.56, 5f6m MD start 4.20 -> 4.15 s.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015CeEGgpKdfkCTJb3YNMJcu
(cherry picked from commit 0752a921a4293d4213894e3242c4ef36d8ce2a05)
This commit is contained in:
leonarski_f committed 2026-10-26 09:16:34 +01:00
1 parent 1f8b5b1986
commit f34d2f4cca
1 file changed
+31 -21
@@ -1272,6 +1272,35 @@ RefinementResult RefineModel(const gemmi::Structure &placed, const std::vector<M
return result;
}
// The trials run side by side, as many at a time as the longest set of them has and the cards take engines:
// on the main model and engine, and on copies with engines of their own; each with a share of the threads. The
// copies are made while the placement runs: they start from the model as it was before the topology was made
// and take nothing from the main context that the placement changes.
int wanted = static_cast<int>(std::max({settings.weight_ladder.size() * settings.adp_ladder.size(),
settings.final_ladder.size(), size_t{3}}));
if (settings.max_trials_at_once > 0)
wanted = std::min(wanted, static_cast<int>(settings.max_trials_at_once));
const std::vector<int> devices = settings.restrained ? OwnSlotDevices(ctx, wanted - 1, settings) : std::vector<int>();
const size_t slot_threads = std::max<size_t>(1, settings.nthreads / (devices.size() + 1));
std::vector<std::unique_ptr<OwnSlot>> own(devices.size());
std::vector<std::thread> slot_builders;
// joined before the slots are taken, or here where the placement throws
struct JoinAll {
std::vector<std::thread> &threads;
~JoinAll() {
for (std::thread &t : threads)
if (t.joinable())
t.join();
}
} join_slot_builders{slot_builders};
for (size_t k = 0; k < devices.size(); k++)
slot_builders.emplace_back([&, k]() {
#ifdef JFJOCH_USE_CUDA
const ScopedGpuPin pin(devices[k] >= 0 ? devices[k] : get_gpu());
#endif
own[k] = MakeOwnSlot(before_topology, ctx, devices[k], slot_threads, settings);
});
RefinePlacement(ctx, settings.group_b, result);
if (restrained)
PlaceRiders(ctx, topo);
@@ -1317,28 +1346,9 @@ RefinementResult RefineModel(const gemmi::Structure &placed, const std::vector<M
const std::vector<gemmi::Position> pos0 = ctx.Positions();
const std::vector<double> b0 = ctx.B();
// The trials run side by side, as many at a time as the longest set of them has and the cards take engines:
// on the main model and engine, and on copies with engines of their own; each with a share of the threads.
std::optional<RefinementStage> slot_stage("slots");
int wanted = static_cast<int>(std::max({settings.weight_ladder.size() * settings.adp_ladder.size(),
settings.final_ladder.size(), size_t{3}}));
if (settings.max_trials_at_once > 0)
wanted = std::min(wanted, static_cast<int>(settings.max_trials_at_once));
const std::vector<int> devices = OwnSlotDevices(ctx, wanted - 1, settings);
const size_t slot_threads = std::max<size_t>(1, settings.nthreads / (devices.size() + 1));
std::vector<std::unique_ptr<OwnSlot>> own(devices.size());
{
std::vector<std::thread> threads;
for (size_t k = 0; k < devices.size(); k++)
threads.emplace_back([&, k]() {
#ifdef JFJOCH_USE_CUDA
const ScopedGpuPin pin(devices[k] >= 0 ? devices[k] : get_gpu());
#endif
own[k] = MakeOwnSlot(before_topology, ctx, devices[k], slot_threads, settings);
});
for (std::thread &t : threads)
t.join();
}
for (std::thread &t : slot_builders)
t.join();
const size_t main_threads = ctx.nthreads;
ctx.nthreads = slot_threads;
std::vector<TrialSlot> trial_slots{{&ctx, &topo}};