Repository navigation
perf: symmetric row-restricted direct_conv curvature kernel (serial numba, large extents) #635
Copy link
Copy link
Closed
Description
Overview
At 512×512 (Aris SPT2319-55: 91k masked pixels, extent 341²) the serial numba curvature_direct_conv kernel is 96–98% of a NumPy interferometer likelihood call. F is symmetric: after sorting source columns by y, each column only needs the extent rows spanned by later-ranked columns, and each row only needs the mask's x-range. On a quiet RAL core the prototype was 1.76× / 1.74× / 1.66× faster at S = 1,428 / 2,540 / 5,712, single-threaded (RAL 411833, PyAutoPulse#62). It reproduces the library's upper triangle exactly. Serial is the target, because Aris parallelises at the Nautilus level.
Plan
- Add a serial symmetric direct_conv kernel and its set-up function beside the existing kernel, which stays as the fallback. The existing parallel path is unchanged.
- Turn it on automatically from a geometry work fraction (≤ 0.5 → on; 0.42 on Aris 512, 0.60 on Aris 125). One config value is the kill switch, and users don't need to set anything.
- Give the feat: route interferometer numba vs FFT curvature by a cost model #632 cost model one correction factor for the cheaper kernel, so routing picks direct_conv where it now wins.
- Tests on several geometries: exact upper triangle, unchanged log likelihood, gate behaviour, routing.
- Witness: a RAL quiet-core rerun of library branch against main (≥1.6× at 2,540 and 5,712), plus one real Aris dataset log likelihood matching main to round-off.
- Write-up phase (autolens_profiling note + PyAutoPulse Knowledge/decision record), stated as data-driven decision rules for autolens_assistant to apply.
- Tier: glance — merge mode: auto-merge on green if the Witness passes, post-merge summary (a Heart RED override ship stops at PR-open → human /prm).
Detailed implementation plan
Affected Repositories
- PyAutoArray (primary); then autolens_profiling + PyAutoPulse (write-up phase)
Branch Survey
| Repository | Current Branch | Dirty? |
|---|---|---|
| ./array/PyAutoArray | main | clean |
Suggested branch: feature/direct-conv-symmetric
Implementation Steps
autoarray/inversion/inversion/interferometer_numba/inversion_interferometer_numba_util.pysymmetric_restriction_inputs_from(iy, ix, cscptr, csc_row, ny, nx, pix_pixels): a vectorised version of the prototype'sprep. It computes the column order by centroid y (stable) andrank, thenylo_suffix(the suffix minimum of each column's y-min in rank order). It also builds the per-row maskxlo/xhi, pixels grouped by row (pix_by_row_ptr,pix_by_row), andwork_fraction = Σ nnz_col·Σ_{y≥ylo} width(y) / (nnz·ny·nx).curvature_direct_conv_symmetric(...)(@numba_util.jit()): the prototypekCin library style, followed by a mirror pass.DIRECT_CONV_SYMMETRIC_MAX_WORK_FRACTIONdefault, and the κ factor incurvature_route_seconds_from(t_dc ·= min(1, κ·f)when the symmetric kernel would run). κ is fitted from the RAL quiet-core ratios and the 125 points, and the fit table is documented in the constants block as feat: route interferometer numba vs FFT curvature by a cost model #632 did.
autoarray/inversion/inversion/interferometer_numba/sparse.py::curvature_matrix_diag: with serial numba andf ≤ threshold, use the symmetric kernel. The parallel path keeps the full kernel.autoarray/config/general.yaml: addinterferometer_direct_conv_symmetric_max_work_fraction: 0.5(0 = off), with a comment.- Routing call site (factory /
curvature_route_seconds_fromcaller): pass the work fraction when it is cheaply available. If it isn't available there, compute it from the mapper's triplets only on the NumPy single-mapper path. - Tests (
test_autoarray/inversion/inversion/interferometer/test_curvature_direct_conv_symmetric.py):- upper triangle
==the library kernel and the whole matrix to 1e-14, on square, circular and offset masks, Delaunay-like and rectangular-like triplets, with empty columns - the work fraction on a known geometry
- the gate's on, off (0) and threshold behaviour
- the routing flip
- an
InversionInterferometerSparseNumbaend-to-end log likelihood unchanged
- upper triangle
- Witness: the RAL
ral-partition single-thread A/B (private checkouts of the branch and main, plus PyAutoNerves), and one real Aris dataset log likelihood. Then the PyAutoArray/Galaxy/Lens suites, interferometer smoke tests,/review, and/ship_library. - Write-up phase: an autolens_profiling
results/notes/interferometer_direct_conv_symmetric_aris_2026_10.md(decision rule + tables), the campaign wiki pointer, and the PyAutoPulsetasks/interferometer_large_mask_aris.mdKnowledge entry +decisions/direct-conv-symmetric-gate.md.
Key Files
autoarray/inversion/inversion/interferometer_numba/inversion_interferometer_numba_util.py: kernels and cost modelautoarray/inversion/inversion/interferometer_numba/sparse.py: kernel selectionautoarray/config/general.yaml: settings
Metadata
Metadata
Assignees
Labels
No labels
Activity
Jammy2211 commentedon Oct 16, 2026
Checkpoint 2026-10-16 (session 13efb443, paused by the human; resume from here)
State: uncommitted, on worktree
~/Code/PyAutoLabs-wt/direct-conv-symmetric/PyAutoArray(branchfeature/direct-conv-symmetric, basee59d5fa9). Nothing is pushed and there is no PR. Scripts, patches and logs are in~/Code/PyAutoLabs-wt/direct-conv-symmetric/l2_scratch/, outside git.Done
curvature_direct_conv_symmetricwith a branch-free ranked-CSC gather (v2).curvature_direct_conv.interferometer_direct_conv_symmetric_max_work_fraction; non-finite weights fall back to the full kernel.t_dc ×= min(1, κf)with κ = 1.32, and the factory routes on f.real_space_mask_fromrefactor.nullconfig value now means the default, and the mask is resolved only on NumPy.Real Aris data finding (
l2_realdata.py,wf_orderings.py, laptop)Human decision (2026-10-16): rank columns by ascending ymin and raise the default gate from 0.5 to 0.7. The model says the kernel wins while κf < 1 (f < 0.76).
In flight at pause: v3 implementation of that decision, uncommitted. It may have finished in the worktree after the pause; a v3 patch is written to the scratchpad, so look in
l2_scratchand rungit diff.Next on resume
git diff, the new test file, the interferometer_numba, factory and settings tests, the full suite, and black./mnt/ral/jnightin/scratch/aris_l2_20261016/:aris_data/PyAutoArray_l2(apply the v3 patch)Run
l2_realdata.py --n-pixels 512 --mesh-step 8 --repeats 2 [--nufft-chunk-size 1000000]onral, serial. Gate: ≥ 1.3× on the curvature step and a matching log likelihood (round-off). Re-confirm the synthetic witness with ymin order too./ship_library, and PR. Tier is glance, but a RED override stops at PR-open.direct-conv-symmetric-gate. Include the multiple-imaging and tall-column insight.Jammy2211 commentedon Oct 17, 2026
Library PR created: #636 (resumed 2026-10-17)
v3 confirmed. Columns are ranked by ascending
yminand the default gate is 0.7, as the human decided on 2026-10-16. Two fixes went into v3:test__numba_inversion__curvature_matrix_and_data_vector_evaluated_once_per_likelihooddid not count the symmetric kernel. Its geometry now passes the 0.7 gate, so the test counts either kernel once.Suites: PyAutoArray 2086 passed / 4 xfailed; PyAutoGalaxy 1357; PyAutoLens 832 / 1 xfailed. Smoke: 165/165 passed (the autocti environments have no GSL headers on the laptop, unrelated).
RAL real-data witness: PASS (euclid-ral-compute-1,
ral, exclusive, 1 thread, load ≤ 1, compile excluded, min of 2 repeats)Heart: canonical
pyauto-heart readinessis STALE (score 85,red_reasons: [], "release validation incomplete: no rehearsal for current source"). STALE passes for development, so no RED override was used.Jobs: 412490 (synthetic + real step 8), 412491 (FFT arm), 412492 (steps 6 and 4), 412493 (log-det control). Outputs are in
/mnt/ral/jnightin/scratch/aris_l2_20261016/and copied tol2_scratch/.Next: the write-up (autolens_profiling results note + campaign journal). Merge stays with the human (
/prm).Jammy2211 commentedon Oct 17, 2026
Shipped
Merged 2026-10-17: library #636 (symmetric row-restricted
curvature_direct_conv_symmetrickernel, ascending-yminranking, gateinterferometer_direct_conv_symmetric_max_work_fraction= 0.7, κf route cost model; serial numba only) then write-up PyAutoLabs/autolens_profiling#425 (decision rule + RAL real-data Aris witness 1.49×/1.53×/1.58×, log L to round-off).Pending release: PyAutoArray#636 ships with the next PyAutoArray release. Campaign PyAutoLabs/PyAutoPulse#62 (lever L2). Human decision 2026-10-17: interferometer CPU work is closed.