PROTOTYPE (owner decision): ffbidx stills index each frame with one call on all spots

Changes results - not for merging without the owner's approval.

The 30/80/all seed escalation exists for the de-novo search, which a flooded frame's full spot list
derails. ffbidx fits a known cell with a trimmed score that already discounts off-lattice spots, so
for it the escalation only multiplied calls: up to three per searched list, ~2.2 per indexed frame
with a fixed min-pix 2. The ffbidx path is GPU-bound (nsys: card 98.5% busy, ffbidx kernels 86%), so
calls are the loop rate. Stills only: rotation never resolves to ffbidx.

Measured on top of the one-search min-pix scheme (parent), two full 24960-frame serial runs, P41212
merge (box loaded by other agents, load 13-17):
  run A: 1130 -> 1532 frames/s; obs 5.30M -> 5.47M; I/sig 13.02 -> 13.12; R_pim 6.46 -> 6.43%;
         CC1/2 .973 -> .976; indexing rate 56.9 -> 57.3%  (original scheme: 785 frames/s, 5.37M,
         13.09, 6.48%, .970)
  run B: 1017 -> 1488 frames/s; obs 4.89M -> 4.99M; I/sig 11.95 -> 11.94; R_pim 6.47 -> 6.42%;
         CC1/2 .970 -> .972; indexing rate 52.4 -> 52.9%  (original: 750, 4.91M, 12.00, 6.50%, .971)
Warm 6000-frame ABAB in one lock hold: 1453/1419 -> 1734/1810 frames/s, same indexing rate.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-10-14 10:49:21 +02:00
co-authored by Claude Opus 5.5
parent 804206155b
commit 64a8d82341
+8 -1
View File
@@ -212,10 +212,17 @@ IndexAndRefine::IndexingOutcome IndexAndRefine::DetermineLatticeAndSymmetry(Data
// hypothesis against the file's geometry - which is why a centre once scored 42/60 as a trial and
// 5/60 when the same value was given on the command line.
const DiffractionGeometry geom = experiment.GetDiffractionGeometry();
// ffbidx fits a known cell with a trimmed score that already discounts the spots off the lattice, so
// the lean seed that rescues a de-novo search on a flooded frame buys it nothing - measured, a single
// call with every spot indexes the same frames and gives the merge more observations - while the
// escalation cost it up to three calls a frame.
const std::vector<size_t> seed_caps = experiment.GetIndexingAlgorithm() == IndexingAlgorithmEnum::FFBIDX
? std::vector<size_t>{std::numeric_limits<size_t>::max()}
: std::vector<size_t>{30, 80, std::numeric_limits<size_t>::max()};
if (frame_calls && frame_calls->lattice_found) {
indexer_result = *frame_calls->lattice_found;
any_executed = true;
} else for (size_t seed_cap : {size_t{30}, size_t{80}, std::numeric_limits<size_t>::max()}) {
} else for (size_t seed_cap : seed_caps) {
std::vector<Coord> recip;
recip.reserve(std::min<size_t>(seed_cap, msg.spots.size()));
for (const auto &i: msg.spots) {