Stills geometry refinement: stop sampling once there are enough strong frames
Build Packages / build:rpm (ubuntu2404) (push) Successful in 11m18s
Build Packages / build:rpm (ubuntu2204) (push) Successful in 12m12s
Build Packages / Generate python client (push) Successful in 15s
Build Packages / build:rpm (rocky8_nocuda) (push) Successful in 10m55s
Build Packages / build:rpm (rocky9) (push) Successful in 12m56s
Build Packages / Create release (push) Skipped
Build Packages / Build documentation (push) Successful in 50s
Build Packages / XDS test (durin plugin) (push) Successful in 8m2s
Build Packages / build:rpm (ubuntu2204_nocuda) (push) Successful in 11m0s
Build Packages / XDS test (JFJoch plugin) (push) Successful in 7m12s
Build Packages / build:rpm (ubuntu2404_nocuda) (push) Successful in 10m23s
Build Packages / build:rpm (rocky9_nocuda) (push) Successful in 11m35s
Build Packages / DIALS test (push) Successful in 12m50s
Build Packages / XDS test (neggia plugin) (push) Successful in 6m16s
Build Packages / build:rpm (rocky8_sls9) (push) Successful in 11m11s
Build Packages / build:rpm (rocky9_sls9) (push) Successful in 11m52s
Build Packages / build:rpm (rocky8) (push) Successful in 11m24s
Build Packages / build:viewer-tgz:cpu (push) Successful in 6m43s
Build Packages / build:viewer-tgz:cuda (push) Successful in 7m44s
Build Packages / Unit tests (push) Successful in 1h2m10s
Build Packages / build:windows:nocuda (push) Canceled after 0s
Build Packages / build:windows:cuda (push) Canceled after 0s
Build Packages / build:rpm (ubuntu2404) (push) Successful in 11m18s
Build Packages / build:rpm (ubuntu2204) (push) Successful in 12m12s
Build Packages / Generate python client (push) Successful in 15s
Build Packages / build:rpm (rocky8_nocuda) (push) Successful in 10m55s
Build Packages / build:rpm (rocky9) (push) Successful in 12m56s
Build Packages / Create release (push) Skipped
Build Packages / Build documentation (push) Successful in 50s
Build Packages / XDS test (durin plugin) (push) Successful in 8m2s
Build Packages / build:rpm (ubuntu2204_nocuda) (push) Successful in 11m0s
Build Packages / XDS test (JFJoch plugin) (push) Successful in 7m12s
Build Packages / build:rpm (ubuntu2404_nocuda) (push) Successful in 10m23s
Build Packages / build:rpm (rocky9_nocuda) (push) Successful in 11m35s
Build Packages / DIALS test (push) Successful in 12m50s
Build Packages / XDS test (neggia plugin) (push) Successful in 6m16s
Build Packages / build:rpm (rocky8_sls9) (push) Successful in 11m11s
Build Packages / build:rpm (rocky9_sls9) (push) Successful in 11m52s
Build Packages / build:rpm (rocky8) (push) Successful in 11m24s
Build Packages / build:viewer-tgz:cpu (push) Successful in 6m43s
Build Packages / build:viewer-tgz:cuda (push) Successful in 7m44s
Build Packages / Unit tests (push) Successful in 1h2m10s
Build Packages / build:windows:nocuda (push) Canceled after 0s
Build Packages / build:windows:cuda (push) Canceled after 0s
The first pass sampled min(n, max(refine_frames * 50, 8000)) images to keep the 200 strongest, so any serial run of 10000 frames or fewer indexed every frame TWICE - and 99.3% of the pass was that sampling, the bundle adjust itself taking 0.24 s. The budget is sized for a low-hit-rate dataset; on data that indexes well almost all of it was wasted. Stop once four times the bundle size has been found, which still leaves the "strongest N" selection a real pool and still spans the run, because the sample is equally spaced. On a lysozyme jet dataset that is 1500 frames examined instead of 4000, the same 200 bundled, and the same refined geometry - beam and distance to the pixel, cell to 0.01 A. Warm cache: the pass drops 33 s -> 9.1 s and the whole run 65 s -> 35 s, with CC1/2 and R-meas unchanged inside replicate noise. Stills only - rotation has its own two-pass and returns from this function early. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
+20
-4
@@ -117,9 +117,21 @@ void Rugnux::RefineStillsGeometry(int start_image, int end_image, int images_to_
|
||||
pass_settings.indexing = true;
|
||||
pass_settings.quick_integration = false;
|
||||
|
||||
// A frame is worth bundling only if it indexed this many spots; the bundle then takes the
|
||||
// refine_frames strongest of those.
|
||||
constexpr int MIN_STRONG_SPOTS = 20;
|
||||
// Stop sampling once there are comfortably more strong frames than the bundle will use, instead of
|
||||
// draining the whole budget. The budget is sized for a low-hit-rate dataset (refine_frames * 50, at
|
||||
// least 8000), so on data that indexes well it meant re-indexing the ENTIRE run to keep 200 frames -
|
||||
// 99% of this pass was sampling. Four times the bundle leaves the "strongest N" selection a real
|
||||
// pool to choose from; the frames are equally spaced, so an early stop still spans the run.
|
||||
const int strong_target = refine_frames * 4;
|
||||
|
||||
std::vector<GeomRefineFrame> frames;
|
||||
std::mutex frames_mutex;
|
||||
std::atomic<int> next_i = 0;
|
||||
std::atomic<int> strong_found = 0;
|
||||
std::atomic<int> examined = 0;
|
||||
|
||||
auto worker = [&]() {
|
||||
pin_gpu(); // round-robin per worker thread; must precede engine construction
|
||||
@@ -127,9 +139,10 @@ void Rugnux::RefineStillsGeometry(int start_image, int end_image, int images_to_
|
||||
/*enable_fused_adaptive_gpu=*/true);
|
||||
AzimuthalIntegrationProfile profile(mapping);
|
||||
|
||||
while (!cancelled_) {
|
||||
while (!cancelled_ && strong_found.load(std::memory_order_relaxed) < strong_target) {
|
||||
const int idx = next_i.fetch_add(1);
|
||||
if (idx >= static_cast<int>(sample.size())) break;
|
||||
examined.fetch_add(1, std::memory_order_relaxed);
|
||||
const int ordinal = sample[idx];
|
||||
const int image_idx = start_image + ordinal * config_.stride;
|
||||
|
||||
@@ -164,6 +177,8 @@ void Rugnux::RefineStillsGeometry(int start_image, int end_image, int images_to_
|
||||
f.spots.push_back(GeomRefineSpot{s.x, s.y,
|
||||
static_cast<int32_t>(s.h), static_cast<int32_t>(s.k), static_cast<int32_t>(s.l)});
|
||||
if (f.spots.size() >= 6) {
|
||||
if (static_cast<int>(f.spots.size()) >= MIN_STRONG_SPOTS)
|
||||
strong_found.fetch_add(1, std::memory_order_relaxed);
|
||||
const std::unique_lock ul(frames_mutex);
|
||||
frames.push_back(std::move(f));
|
||||
}
|
||||
@@ -182,7 +197,6 @@ void Rugnux::RefineStillsGeometry(int start_image, int end_image, int images_to_
|
||||
|
||||
// Keep the strongest frames (most indexed spots) for the bundle - the true cell indexes many
|
||||
// spots per frame, and orientation diversity comes for free from independent serial stills.
|
||||
constexpr int MIN_STRONG_SPOTS = 20;
|
||||
std::vector<GeomRefineFrame> strong;
|
||||
for (auto &f : frames)
|
||||
if (static_cast<int>(f.spots.size()) >= MIN_STRONG_SPOTS)
|
||||
@@ -192,8 +206,10 @@ void Rugnux::RefineStillsGeometry(int start_image, int end_image, int images_to_
|
||||
if (static_cast<int>(strong.size()) > refine_frames)
|
||||
strong.resize(refine_frames);
|
||||
|
||||
logger.Info("Geometry refinement: indexed {} of {} sampled frames, bundling {} strong frames (>= {} spots)",
|
||||
frames.size(), sample.size(), strong.size(), MIN_STRONG_SPOTS);
|
||||
logger.Info("Geometry refinement: indexed {} of {} sampled frames (budget {}), bundling {} strong "
|
||||
"frames (>= {} spots)",
|
||||
frames.size(), std::min<int>(examined.load(), static_cast<int>(sample.size())),
|
||||
sample.size(), strong.size(), MIN_STRONG_SPOTS);
|
||||
|
||||
GeometryRefinerSettings gr_settings;
|
||||
gr_settings.crystal_system = experiment_.GetCrystalSystem();
|
||||
|
||||
Reference in New Issue
Block a user