Avoid copying logk for the normal systematic type - #152
Open
davidwalter2 wants to merge 1 commit into
Open
Conversation
For systematic_type == normal the param-model factor rnorm_init was
absorbed into logk at construction, which allocates a second full-size
copy of the [nbins, nproc, nsyst] tensor and, in sparse mode, rebuilds
the CSR matrix.
rnorm_init carries no systematic index, so it factors out of the
contraction over systematics:
sum_s (rnorm_init[b,p] * logk[b,p,s]) * theta[s]
== rnorm_init[b,p] * sum_s logk[b,p,s] * theta[s]
Keep logk aliased to the indata tensor and apply the factor to the
[nbins, nproc] contraction result instead. This is exactly equivalent,
costs one elementwise multiply on a tensor a factor nsyst smaller, and
leaves the hot path strictly linear in theta. In sparse mode the factor
is gathered onto the [norm_nnz] layout the CSR contraction returns.
Verified against the unpatched code with tests/make_tensor.py for
dense+normal and sparse+normal (with --expectSignal 2.5, so the scaling
is non-trivial): agreement at the 1e-11 level, consistent with the
change in summation order. The log_normal path is bit-identical.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AMhAVnF8rjPLuhftU8gTVm
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
For
systematic_type == "normal",_init_logk_scaledabsorbed the param-model factorrnorm_initintologkat construction time. That allocates a second full-size copy of the[nbins, nproc, nsyst]tensor and, in sparse mode, rebuilds the CSR matrix.rnorm_initcarries no systematic index, so it factors straight out of the contraction over systematics:This keeps
logk/logk_csraliased to the indata tensors and applies the factor to the[nbins, nproc]contraction result instead of the[nbins, nproc, nsyst]input.Only the
normalsystematic type is affected;log_normalalready carried the scaling multiplicatively and takes the same early return as before.Measured effect
The scaling now runs once per loss/HVP evaluation instead of once over the full tensor at construction, so it is worth checking that this does not cost more than it saves. Measured on a 10000-bin x 2048-systematic
normal-type model (logk= 819 MB), with--minimizerMaxiterpinned so both versions do matched work:logktensor -- i.e. the copy is gone.The per-call cost is one elementwise multiply on
[nbins, nproc], a factornsystsmaller than the matmul it follows, and it lands on data already in cache.The saving scales with the tensor: for a 100k-bin x 8192-systematic model the avoided copy is ~33 GB. In sparse mode the win is structural rather than just an allocation -- the old path rebuilt the CSR matrix via
CSRSparseMatrix(...), which is replaced by a one-timegather_ndonto the[norm_nnz]layout the CSR contraction already returns.rnorm_initremains a constant evaluated atxparamdefault, so the loss stays strictly linear in theta and derivatives are unchanged.Validation
Compared against unpatched
mainusingtests/make_tensor.py, running the fit with both and comparing fitted parameter values and variances:Run with
--expectSignal sig 2.5so thatrnorm_init != 1and the scaling is genuinely exercised -- with the defaultexpectSignal=1the factor is exactly 1.0 and both orderings agree trivially. The residual differences are consistent with the change in summation order (summing then scaling instead of scaling then summing); the new ordering performs one multiply per(bin, proc)rather thannsystof them.🤖 Generated with Claude Code