Rotation merge on the GPU reports a merge without fulls instead of crashing
When the GPU 3D combine made no full reflection (no rocking event captured whole enough - e.g. a sweep exposed 0.2 deg out of every 0.6 deg, or a lattice that does not describe the frames), the GPU scale-fulls step was skipped and the host scale-fulls loop ran instead. That loop slices the per-frame fulls CSR that only the host combine builds, so it read empty vectors and the process died on SIGSEGV in RunArm. The host loop now runs only on fulls the host combined; with no fulls the merge ends in the existing "nothing to merge" error, as the CPU path already did. Runs that make fulls are unchanged (merged and unmerged MTZ data bit-identical on two in-house sweeps). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01HVeDQqN9qRD57vnShzTC37
This commit is contained in:
1 parent
314e502733
commit
4cb911d675
2 files changed
+18
-1
No files matched your search
@@ -7527,7 +7527,9 @@ RotationScaleMerge::Result RotationScaleMerge::RunArm(bool scale_partials, bool
|
||||
BuildFullsGroupCSR(n_groups);
|
||||
|
||||
// --- 4. Scale the fulls (XDS order, Unity model). ---
|
||||
if (scale_fulls && !scaled_fulls_on_gpu) {
|
||||
// On the fulls the host combined: the per-frame CSR this loop slices is built by Combine(). Fulls
|
||||
// combined on the GPU were scaled there - unless there were none, and then there is nothing to scale.
|
||||
if (scale_fulls && !combined_on_gpu) {
|
||||
// On a working copy of the fulls, as the partials' loop (ScalingRef and ScalingFit in the header):
|
||||
// full_index[q] is the full at position q, in the group CSR's order and then the fulls in no group.
|
||||
const int nf = static_cast<int>(fulls.size());
|
||||
|
||||
@@ -229,3 +229,18 @@ TEST_CASE("RotationScaleMergeSegments_NoSegmentsIsTheEngineAsBefore", "[Rotation
|
||||
else if (get_gpu_description().find("RTX 5080") != std::string::npos)
|
||||
CHECK(hash == 6594155396455850264ULL);
|
||||
}
|
||||
|
||||
// A sweep in which no rocking event is captured whole enough to make a full - as in one exposed 0.2 deg out
|
||||
// of every 0.6 deg, where each reflection is caught on one frame and only in part. On the GPU the combine
|
||||
// returned no fulls, the scale-fulls step then fell through to the host loop, which slices a per-frame CSR
|
||||
// that only the host combine builds, and the process died on SIGSEGV instead of reporting the empty merge.
|
||||
TEST_CASE("RotationScaleMerge_NoFullsIsAnErrorNotACrash", "[RotationScale]") {
|
||||
const std::vector<SweepSpec> sweeps{{60, 1.0, 0.0}};
|
||||
auto data = MakeSweeps(sweeps, 17);
|
||||
auto x = SyntheticExperiment(false);
|
||||
// More than any rocking event can capture: the combine makes no full.
|
||||
ScalingSettings s = x.GetScalingSettings();
|
||||
s.MinCapturedFraction(1000.0);
|
||||
x.ImportScalingSettings(s);
|
||||
CHECK_THROWS_AS(Merge(data, x, {}), JFJochException);
|
||||
}
|
||||
Reference in new issue
Block a user