Refinement: trial slots counted with their scale pool and both restraint sets; on the CPU no more than -N

GPU: a slot was packed onto a card by its engine's bytes alone. The per-slot estimate now adds
the slot's ModelScaleGPUPool with the robust fit's buffers (ModelScaleGPUPool::DeviceBytes(n, 1,
true)), and RefinementGPUEngine::DeviceBytes counts the two restraint sets SetRestraints() holds,
not one. The 80%-of-card budget is unchanged, so where these do not fit fewer slots are packed
instead of an allocation failing inside a running trial.

CPU: OwnSlotDevices made a slot per wanted trial whatever the thread count, so -N 1 ran six trial
threads with six models, topologies and engines in memory. The main slot and those beside it are
now at most -N. Side by side equals sequential, so no result changes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015CeEGgpKdfkCTJb3YNMJcu
(cherry picked from commit 3c04c01158266c267f8e5ffaaaa98d6d8fd2a747)
This commit is contained in:
leonarski_f committed 2026-10-26 15:38:58 +01:00
1 parent ac58921445
commit 257bf2fe2b
2 files changed
+13 -9

No files matched your search

@@ -1013,29 +1013,32 @@ std::unique_ptr<OwnSlot> MakeOwnSlot(const gemmi::Structure &before_topology, co
}
// The devices of the slots beside the main one, `wanted` of them at most: the GPUs in turn from the main
// engine's, each taking engines while they fit in its budget. -1 for each one on the CPU.
// engine's, each taking engines while they fit in its budget. -1 for each one on the CPU, where the main one and
// those beside it are no more than the threads.
std::vector<int> OwnSlotDevices(const Context &main, int wanted, const RefinementSettings &settings) {
#ifdef JFJOCH_USE_CUDA
if (main.engine->OnGPU()) {
const int n = get_gpu_count();
// a slot's engine and its scale pool, the robust fit's buffers included
const size_t slot_bytes = main.engine_bytes + ModelScaleGPUPool::DeviceBytes(main.refl.Size(), 1, true);
std::vector<size_t> used(n, 0);
used[main.device] = main.engine_bytes;
used[main.device] = slot_bytes;
std::vector<int> devices;
for (int k = 1; k <= wanted; k++) {
const int d = (main.device + k) % n;
const size_t usable = get_gpu_total_memory(d) / 5 * 4;
const size_t budget = usable > settings.gpu_resident_bytes ? usable - settings.gpu_resident_bytes : 0;
if (used[d] + main.engine_bytes <= budget) {
used[d] += main.engine_bytes;
if (used[d] + slot_bytes <= budget) {
used[d] += slot_bytes;
devices.push_back(d);
}
}
return devices;
}
#else
(void) settings;
#endif
return std::vector<int>(std::max(wanted, 0), -1);
// on the CPU, no more trials at once than threads: each slot is a model, a topology and an engine of its own
const int beside = std::min(wanted, static_cast<int>(settings.nthreads) - 1);
return std::vector<int>(std::max(beside, 0), -1);
}
// One weight trial: `cycles` macro-cycles from pos0 and b0, of the positions at X-ray weight w and, where adp_w is