Skip to content

refactor: qhull-only Delaunay callback, exact JAX visibility-walk point location#368

Merged
Jammy2211 merged 1 commit into
mainfrom
feature/delaunay-qhull-callback
Jul 9, 2026
Merged

refactor: qhull-only Delaunay callback, exact JAX visibility-walk point location#368
Jammy2211 merged 1 commit into
mainfrom
feature/delaunay-qhull-callback

Conversation

@Jammy2211

Copy link
Copy Markdown
Collaborator

Summary

Shrinks the JAX-path Delaunay pure_callback to qhull-only and moves point location, dual areas and split points inside the JIT program. The old callback did 40-320 ms of host-serial work per likelihood evaluation (scaling with over-sampling), serialized per vmap lane (vmap_method="sequential") — the measured reason the A100 Delaunay cell runs at 106.8 ms/lane vs rectangular's 32.9 ms (autolens_profiling results/notes/sparse_vs_dense_inversion_path.md). Expected effect: Delaunay vmap lane → ~40-50 ms (rectangular parity); to be re-profiled on the A100 when RAL returns.

Point location is the same visibility-walk algorithm find_simplex itself uses, via qhull's tri.neighbors, as a masked fixed-trip lax.fori_loop chunked over query points — exact by construction. The planned 2-ring locator was implemented first and rejected by the parity gate (Δlog-evidence −0.77 on the production config; only ~31% of the relocated source-plane grid is inside the mesh hull and caustic geometry defeats ring-coverage arguments) — see the issue thread for the investigation.

Known trade-off: single-thread CPU JAX-path per-eval is ~20% slower than the old callback (CPU-JAX runs the walk slower than scipy's C). GPU/vmap is the target of this refactor; the eager numpy path is byte-identical.

API Changes

None — internal changes only. jax_delaunay / jax_delaunay_matern signatures and return contracts (shapes, dtypes, -1 padding conventions) are unchanged; the numpy/scipy path (scipy_delaunay, scipy_delaunay_matern) is byte-identical.
See full details below.

Test Plan

  • Full suite in the task worktree: 873 passed
  • New numpy-only unit tests (test_delaunay_walk.py): walk locator vs scipy.find_simplex on uniform + adaptive (blob/ring) meshes; outside-hull rows equal the KDTree nearest-vertex assignment exactly; fp edge ties must still contain the query; vertex/edge-midpoint degeneracies; adjacency tables vs the triangulation
  • Production-scale parity gate (HST, 1500-vertex Hilbert/Delaunay, MGE-60 lens, ConstantSplit): full-pipeline JIT − eager = 5.4e-9 (old JAX path: 5.2e-9); pinned log-evidence 29110.92085793 holds; mapping identity vs find_simplex on the real border-relocated grids: 100.0000%
  • Phase 2 (follow-up PR, library-first gate): permanent parity suite in autolens_workspace_test incl. a near-caustic configuration
  • A100 re-profile (autolens_profiling runtime sweep) when RAL is back

Validation checklist (--auto run)

  • Effective level: supervised (header: supervised, cap: refactor → safe); ship sign-off + Heart YELLOW reason-set acknowledged by the human in-session 2026-07-09
  • Plan: on the issue (refactor: qhull-only Delaunay callback, JAX point location #367), locator design amended mid-run (2-ring → visibility walk) with the parity evidence documented on the issue before ship
  • Gate: tests 873 passed · smoke pending (targeted delaunay smoke recommended post-merge; cluster scripts are no_run-parked) · review-faculty verdict posted to the issue after PR-open · Heart YELLOW within launch ack
  • Human: plan sound in hindsight?
  • Human: diff matches plan (no scope creep)?
  • Human: merge, amend, or reject — then log the outcome
Full API Changes (for automation & release notes)

Removed

  • None from the public surface. (Internal-only: the interim helpers of this branch's first iteration never shipped.)

Added (module-internal helpers, not exported via autoarray.__init__)

  • inversion.mesh.interpolator.delaunay.scipy_delaunay_tri_only(points_np) — qhull-only host callback returning simplices_padded, simplex_neighbors, vertex_simplex
  • inversion.mesh.interpolator.delaunay.pix_indexes_delaunay_walk_from(query_points, points, simplices_padded, simplex_neighbors, vertex_simplex, xp) — exact visibility-walk point locator (NumPy/JAX)
  • Module constants DELAUNAY_LOCATE_CHUNK, DELAUNAY_WALK_STEPS

Changed Behaviour

  • jax_delaunay / jax_delaunay_matern: identical return contract; the mappings are now computed in-JIT via the visibility walk instead of on the host. Measured identical to find_simplex on production grids (100.0000%); the only theoretical divergence is fp ties on shared edges, which are interpolation-identical.

Migration

  • None required.

🤖 Generated with Claude Code

… point location

The JAX-path pure_callback previously ran the full scipy_delaunay
pipeline on the host every likelihood evaluation (qhull triangulation +
find_simplex on the data and split grids + numpy assembly) - 40-320 ms
of host-serial work that scales with over-sampling and serializes per
vmap lane. The callback now returns only the qhull triangulation and
its adjacency arrays (tri.neighbors plus one incident simplex per
vertex); point location, dual areas and split points run inside the
JIT program, on GPU and batched across vmap lanes in production.

Point location uses the same visibility-walk algorithm find_simplex
itself uses (nearest-vertex start, step through the neighbor opposite
the most negative barycentric weight, hull exit -> nearest-vertex
fallback), as a masked fixed-trip lax.fori_loop chunked over query
points. Mappings are exact: 100.000% identity vs find_simplex on
production HST grids; full-pipeline JIT log-evidence matches eager to
5.4e-9 (previous JAX path: 5.2e-9), pinned value 29110.92085793 holds.

The numpy/scipy path is byte-identical and the jax_delaunay /
jax_delaunay_matern return contracts (shapes, dtypes, -1 padding) are
unchanged, so no downstream edits are required.

PyAutoArray#367 (phase 1 of 2; phase 2 adds the autolens_workspace_test
parity suite).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@Jammy2211

Copy link
Copy Markdown
Collaborator Author

Phase 2 parity-guard PR (merge after this one): PyAutoLabs/autolens_workspace_test#155

@Jammy2211 Jammy2211 merged commit 89a5fbd into main Jul 9, 2026
4 checks passed
@Jammy2211 Jammy2211 deleted the feature/delaunay-qhull-callback branch July 9, 2026 14:21
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

pending-release PR queued for the next release build

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant