diff --git a/docs/CPU_DATA_ANALYSIS_INDEXING.md b/docs/CPU_DATA_ANALYSIS_INDEXING.md index 919e1c5d9..f600a7951 100644 --- a/docs/CPU_DATA_ANALYSIS_INDEXING.md +++ b/docs/CPU_DATA_ANALYSIS_INDEXING.md @@ -230,15 +230,20 @@ also runs (rotation only, and not when a cell was given — `-C` already lowers and its answer is adopted only when it is an integer sub-cell of the standing one and ties or beats it on the validation frames. Everywhere else the standard pass's answer stands. -**A near tie is decided early and checked again late.** The first pass decides on validation frames -from the start of the sweep, so it can act at once - also while a collection is still being written. -Where one of its decisions was a near tie that later frames could tip (the lattice, the indexing -path, the beam centre, the spot-finding settings), the pass is run again once every frame is in, on a -copy of the run taken as it began and deciding on the rest of the sweep too, and only where that -re-check ends elsewhere is the whole run made again with every near tie decided late; a run that found -no lattice after carrying a near tie is made again likewise. The answer is therefore the one deciding -late throughout gives, at the cost of the re-checks (measured: a median of 0.9 s on the sets that had -one). +**A near tie is decided on every frame - from the start offline, late on a live run.** A run on a +stored file has the whole sweep from the start, so its first pass decides each near tie that later +frames could tip (the lattice, the indexing path, the beam centre, the spot-finding settings) on +validation frames from the whole sweep at once, with nothing to check again. A live run - one following +a collection that is still being written (`rugnux `, or `--simulate-live` on a +stored file) - cannot wait for frames that do not exist yet: its first pass decides on validation +frames from the start of the sweep, so it can act at once. Where one of those decisions was a near tie, +the pass is run again once every frame is in, on a copy of the run taken as it began and deciding on +the rest of the sweep too, and only where that re-check ends elsewhere is the whole run made again with +every near tie decided late; a run that found no lattice after carrying a near tie is made again +likewise. Both give the answer that deciding late throughout gives; the live run pays for it with the +re-checks (measured: a median of 0.9 s on the sets that had one). The checks taken on the +pre-pass frames - the geometry walk's refits, the metric-symmetry arm and the pre-pass spot-crowding count - stay on those frames +in both modes, and their near ties are re-checked once every frame is in on both. **A first pass that ends with no usable lattice tries a leaner, shallower one.** A crystal sitting in a crystalline powder floods the pass with spots that are not its own — measured, 2112 spots a frame diff --git a/image_analysis/scale_merge/RotationScaleMergeGPU.cu b/image_analysis/scale_merge/RotationScaleMergeGPU.cu index 4315e4b35..a4d52a8d7 100644 --- a/image_analysis/scale_merge/RotationScaleMergeGPU.cu +++ b/image_analysis/scale_merge/RotationScaleMergeGPU.cu @@ -1186,10 +1186,12 @@ struct RotationScaleMergeGPU::Impl { // // The failed allocation is handled here, so its error must not stay behind as this thread's last // error: the next kernel launch's cudaGetLastError() would report it over work that went fine. + // + // Plain Synchronous, not ALLOC: this function waits for the work beside itself, with its own limit. template CudaDevicePtr Alloc(size_t n) const { try { - return CudaDevicePtr(n, ALLOC); + return CudaDevicePtr(n, CudaAlloc::Synchronous); } catch (const JFJochException &) { cuda_throw_if_context_lost(); // not memory: waiting would only hide the real error cuda_clear_error(); @@ -1197,7 +1199,7 @@ struct RotationScaleMergeGPU::Impl { if (!wait_for_gpu_work_beside(GPU_BUSY_TIMEOUT)) ThrowGPUBusy(n_obs); try { - return CudaDevicePtr(n, ALLOC); + return CudaDevicePtr(n, CudaAlloc::Synchronous); } catch (const JFJochException &) { ThrowOutOfGPUMemory(n_obs, n * sizeof(T)); } diff --git a/image_analysis/structure_refinement/MolecularReplacement.cpp b/image_analysis/structure_refinement/MolecularReplacement.cpp index 5cb3a53fc..ff20de6cf 100644 --- a/image_analysis/structure_refinement/MolecularReplacement.cpp +++ b/image_analysis/structure_refinement/MolecularReplacement.cpp @@ -324,7 +324,7 @@ public: points = sf->Reflections(); bytes = sf->DeviceBytes() + ModelScaleGPU::DeviceBytes(points) + 2 * points * sizeof(std::complex); quarter = sf->DeviceTotalMemory() / 4; - } catch (const JFJochException &) { + } catch (const std::exception &) { cuda_clear_error(); sf.reset(); } @@ -352,7 +352,7 @@ public: engine->fmask = CudaDevicePtr>(points); engine->sf = std::move(sf); set_gpu(device); - } catch (const JFJochException &) { + } catch (const std::exception &) { engine.reset(); cuda_clear_error(); }