-N defaults to every hardware thread and the per-image loop spawned one worker for each of them.
Every worker submits its own kernels to a card, and a card runs out of room to accept them long
before it runs out of work to do: measured on two GPUs, the loop's own time falls from 10.76 s at
four workers to 9.69 s at sixteen and then climbs back to 10.49 s at forty-eight. Forty-eight
workers is slower than eight. The same shape appears on a small detector, with the turn further out
because a frame is a smaller piece of work.
So cap the loop at eight workers per card when -N was left alone. Per card, because that is what the
queue depth belongs to; eight, because that is where the curve turns on the hardware this was
measured on. Everything outside the loop - the merge, the surfaces, post-refinement - still gets the
whole machine, because none of it is waiting on a card.
An explicit -N is obeyed exactly as given, and the cap says so in the log when it fires. A previous
attempt at this overrode an explicit -N and applied to the azimuthal and calibration modes as well,
which is why it was refused; this one is only about the default.
It matters most where it cannot be measured here. A two-card production node with 192 threads runs
ninety-six workers per card against a curve that turns at eight, while this box at -N 48 across four
cards sits at twelve and looks fine. Even so, on four cards the battery goes 6m28s -> 6m10s, with
every crystal's space group, reflection count and R_meas identical to the run before it - the cap
changes no arithmetic at all.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011n8riB6X59oRjkrSHzNPAU