diff --git a/rugnux/Rugnux.cpp b/rugnux/Rugnux.cpp index 205ca1ea..3a6b46ea 100644 --- a/rugnux/Rugnux.cpp +++ b/rugnux/Rugnux.cpp @@ -506,6 +506,18 @@ ProcessResult Rugnux::RunPipeline(RugnuxObserver *observer, bool write_output, b // validation set; re-finding is expensive on the --redo-rotation-spots path). Accessed only // from single-threaded sections (the scheme feed and the validation loop), so no locking. std::map> spot_cache; + // One analysis engine for the whole first pass. Constructing it allocates a CUDA stream and a + // full set of GPU buffers (preprocessing, spot finding, azimuthal integration, Bragg + // integration) - far more work than analysing a frame - so building it per image made + // --redo-rotation-spots pay for hundreds of them, serially. Only needed when spots have to be + // found; this section is single-threaded, so one engine is enough. + std::unique_ptr analysis; + std::unique_ptr profile; + if (!reuse_spots) { + analysis = std::make_unique(experiment_, mapping, pixel_mask_, *indexer, + /*enable_fused_adaptive_gpu=*/true); + profile = std::make_unique(mapping); + } auto get_spots = [&](int ordinal) -> const std::vector & { auto it = spot_cache.find(ordinal); if (it != spot_cache.end()) @@ -519,16 +531,13 @@ ProcessResult Rugnux::RunPipeline(RugnuxObserver *observer, bool write_output, b DataMessage m{}; m.number = ordinal; m.original_number = image_idx; - MXAnalysisWithoutFPGA analysis(experiment_, mapping, pixel_mask_, *indexer, - /*enable_fused_adaptive_gpu=*/true); - AzimuthalIntegrationProfile profile(mapping); auto first_pass = config_.spot_finding; first_pass.indexing = false; first_pass.quick_integration = false; m.image = img->image; if (dataset->efficiency.size() > image_idx) m.image_collection_efficiency = dataset->efficiency[image_idx]; - analysis.Analyze(m, profile, first_pass); + analysis->Analyze(m, *profile, first_pass); spots = std::move(m.spots); } } catch (const std::exception &e) {