diff --git a/image_analysis/structure_refinement/Refinement.cpp b/image_analysis/structure_refinement/Refinement.cpp index 5d532a825..8a26c7d26 100644 --- a/image_analysis/structure_refinement/Refinement.cpp +++ b/image_analysis/structure_refinement/Refinement.cpp @@ -1272,6 +1272,35 @@ RefinementResult RefineModel(const gemmi::Structure &placed, const std::vector(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(settings.max_trials_at_once)); + const std::vector devices = settings.restrained ? OwnSlotDevices(ctx, wanted - 1, settings) : std::vector(); + const size_t slot_threads = std::max(1, settings.nthreads / (devices.size() + 1)); + std::vector> own(devices.size()); + std::vector slot_builders; + // joined before the slots are taken, or here where the placement throws + struct JoinAll { + std::vector &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 pos0 = ctx.Positions(); const std::vector 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 slot_stage("slots"); - int wanted = static_cast(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(settings.max_trials_at_once)); - const std::vector devices = OwnSlotDevices(ctx, wanted - 1, settings); - const size_t slot_threads = std::max(1, settings.nthreads / (devices.size() + 1)); - std::vector> own(devices.size()); - { - std::vector 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 trial_slots{{&ctx, &topo}};