You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Browse filesBrowse the repository at this point in the historyBrowse files
authored and
Jammy2211
committed
sibson: cut DelaunayNN kernel launches — gated candidate unroll, single concatenated pass, chunk as memory guard
Phase A of #532. On the A100 (post-#531) the DelaunayNN params->H prefix
costs 144.8 ms unbatched / 24.4 ms per call at vmap 16 against Delaunay's
7.2 / 5.1 ms. The compiled HLO issues 1,244 kernel launches per 256-query
chunk over 95 chunks (~118k launches at ~1.1 us each): the cost is a launch
floor, not arithmetic, so this cuts launches instead of flops.
- _cavity_triangle_indexes_jax: the 3-trip candidate-edge fori_loop is
unrolled at trace time when _sibson_unroll_candidates() is true --
PYAUTO_SIBSON_UNROLL_CANDIDATES ("1"/"0") wins, otherwise
jax.default_backend() != "cpu". Unrolling removes ~28% of the launches
per chunk (1,244 -> 892) on accelerators; on CPU there is no launch cost
to remove and the rolled loop measures ~8-9% faster, so CPU stays rolled.
Both paths are bit-identical (same add_candidate calls, edges 0,1,2, same
insertion order).
- jax_delaunay_nn: the data grid and the 4N split-cross points are located
and interpolated in ONE concatenated pass (walk once, Sibson once), sliced
at n_query -- the pattern jax_delaunay already uses for its walk. The
circumcircles depend only on the frozen simplex table, so they are hoisted
and handed in through a new optional circumcircles= kwarg on
sibson_mappings_weights_from_tables (default None recomputes as before;
jax_sibson and scipy_delaunay_nn are unchanged).
- SIBSON_QUERY_CHUNK (default still 256) is overridable at import via
PYAUTO_SIBSON_QUERY_CHUNK, validated as a positive int, and picked up by
DelaunayNN.query_chunk -- so the chunk can be swept on device without
editing source. Documented as a memory guard on the (C, 3, 2) per-cavity
intermediates, explicitly not a speed knob: it multiplies a latency-bound
program.
- Docstrings on the loop structure, the launch-count reasoning and the
single-pass invariant.
Bit-identity: all 16 jax_delaunay_nn outputs (data and split halves) match a
frozen main reference after each step, on the gated path and with the env
override forced to 1 and to 0. Chunk invariance proven at 64 / 256 / 1024
through both the kwarg and the env var.
Tests: pytest test_autoarray -q -> 1456 passed; 4 new NumPy-only tests
(circumcircles-kwarg parity, fixed-seed scipy_delaunay_nn regression, env
parsing valid/invalid for both variables, unroll-gate override). black
clean. Locally: jax_assertions/delaunay_nn.py exit 0 (relative_l2 9.88e-05,
corr 0.9986, max_cavity 11, max_neighbors 13, flip continuity + gradients
green) and delaunay_nn_caps.py exit 0. CPU no-regression: interleaved
in-process paired A/B, control vs feature ratio 0.993 with the gate (0.927
with the unroll forced on).
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01B5HT8dp7sWc9qDhZp6moGr
0 commit comments