CPU profile fit: the Gaussian's cells in a loop that vectorises, output unchanged
Building each reflection's Gaussian profile was a third of the CPU pass B's samples (cytochrome C), one scalar BraggExp per cell. BraggExp branched to its two ends before the arithmetic, and the branches - with GCC's -ftrapping-math, which forbids running float arithmetic on a path that does not need it - kept every loop over it scalar. It now tells the ends apart on the bits of x, an integer comparison, runs the same arithmetic on x (or on 0 out of range) and masks the result: the same bits for every float but NaN, checked over all 2^32 inputs against the old function, scalar and vectorised. The cells are filled a row at a time and summed afterwards in the same order, so the loop vectorises (8 lanes, AVX2) and the profile is unchanged. BraggScale2 chooses its operands instead of a branch; scaling by 1 is exact. The Metal kernel shares the header and gets the same arithmetic. cytochrome C --no-gpu: p.hkl and MTZ data identical; user cycles -7% against the previous commit on the same (loaded, load 16-32) machine. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
81b81ec683
commit
aca2b2fdc3
2 files changed
+30
-14
No files matched your search
@@ -486,13 +486,14 @@ BraggFitOut BraggIntegrationEngineCPU::FitProfile(const Sampler &img, const Owne
|
||||
prefetch_row(img.address(static_cast<size_t>(y) * W + gx0),
|
||||
img.address(static_cast<size_t>(y) * W + gx1));
|
||||
cells.resize(static_cast<size_t>(Gf) * Gf);
|
||||
// The cells a row at a time, a loop that vectorises; then their sum, in the same order.
|
||||
for (int dy = -Rf; dy <= Rf; ++dy) {
|
||||
float *row = cells.data() + static_cast<size_t>(dy + Rf) * Gf;
|
||||
for (int dx = -Rf; dx <= Rf; ++dx)
|
||||
row[dx + Rf] = BraggGaussian(dx, dy, s.fx, s.fy, s.ux, s.uy, s.inv_2s2r, s.inv_2s2t);
|
||||
}
|
||||
float gs = 0.0f;
|
||||
for (int dy = -Rf; dy <= Rf; ++dy)
|
||||
for (int dx = -Rf; dx <= Rf; ++dx) {
|
||||
const float g = BraggGaussian(dx, dy, s.fx, s.fy, s.ux, s.uy, s.inv_2s2r, s.inv_2s2t);
|
||||
cells[(dy + Rf) * Gf + (dx + Rf)] = g;
|
||||
gs += g;
|
||||
}
|
||||
for (const float g : cells) gs += g;
|
||||
const float inv_gs = 1.0f / gs;
|
||||
for (float &p : cells) p *= inv_gs;
|
||||
P = cells.data();
|
||||
|
||||
Reference in new issue
Block a user