Skip to content

perf: reuse delay matrices across FreqResponsePointwise omega points - #170

Merged
jamestjsp merged 1 commit into
jamestjsp:mainfrom
jamestjat:feat/pointwise-workspace-reuse
Aug 26, 2026
Merged

perf: reuse delay matrices across FreqResponsePointwise omega points#170
jamestjsp merged 1 commit into
jamestjsp:mainfrom
jamestjat:feat/pointwise-workspace-reuse

Conversation

@jamestjat

Copy link
Copy Markdown
Contributor

Summary

FreqResponsePointwise (v1.4.0, #169) rebuilt the effective I/O delay matrix inside applyIODelayAtS on every omega point — one []float64 plus one mat.Dense header per point, so sweep allocations scaled linearly with len(omega) (2 allocs/point on delayed systems). This hoists the delay matrices out of the sweep loop:

  • delaySS := effectiveIODelayMatrix(sys, p, m, true) computed once before the loop for the state-space path
  • the transfer-function-fallback variant (includeDelayMatrix=false) computed lazily alongside the fallback TF itself, only if a solve ever fails
  • the per-point arithmetic (applyIODelayMatrixAtS) is completely unchanged

Bit-identity

The delay matrices are pure functions of the System, which is not mutated across the sweep — computing them once yields byte-identical floats to computing them per point. The same solves run in the same order; only the allocation source moved. All existing TestFreqResponsePointwise_* bit-identity pins pass unchanged (byte-exact vs single-point FreqResponse).

Numbers

testing.AllocsPerRun, 2-state SISO with input delay:

sweep points allocs before allocs after
10 23 5
100 203 5
1000 2003 5

New regression test TestFreqResponsePointwise_AllocsAmortizeAcrossSweepLengths pins that sweep allocations no longer grow with sweep length.

Downstream

On adoption (version bump in APC.Exp.AspenAPC-Go), this removes the monorepo's benchgate alloc exemption for CalculateTuning/path=simplex_pid (the CM2QFO REMOVE-after note in scripts/benchgate/gate.awk): local A/B with a replace shows the tuning-sweep rows return to the pre-v1.4.0 allocation band with sec/op flat.

🤖 Generated with Claude Code

The pointwise sweep rebuilt the effective I/O delay matrix inside
applyIODelayAtS on every omega point (a []float64 plus a mat.Dense
header), making sweep allocations scale linearly with len(omega):
2 allocations per point on delayed systems. The matrices are pure
functions of the System, which is not mutated across the sweep, so
they are now computed once before the loop (the transfer-function
fallback variant lazily, alongside the fallback TF itself) and passed
to the unchanged applyIODelayMatrixAtS per-point arithmetic.

Bit-identity holds: the same solves run in the same order and every
per-point float operation is unchanged — only the allocation source
of the delay matrix moved outside the loop. The existing
TestFreqResponsePointwise_* pins stay byte-exact, and a new
regression test asserts allocations per sweep no longer grow with
sweep length (5 per sweep at 10 and at 1000 points, down from
23 and 2003).

Co-Authored-By: Claude Mythos 5 <noreply@anthropic.com>
@jamestjsp
jamestjsp merged commit fdda4f1 into jamestjsp:main Aug 26, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants