Skip to content

Add a test fixture that pins the UDT operator execution path - #592

Open
eriknw wants to merge 3 commits into
11-udt-record-leaf-countfrom
12-udt-dual-path-harness
Open

eriknw wants to merge 3 commits into
11-udt-record-leaf-countfrom
12-udt-dual-path-harness

Conversation

@eriknw

@eriknw eriknw commented Aug 4, 2026 •

Copy link
Copy Markdown
Member

Each auto-lifted UDT operator carries both a JIT C definition and a Numba
cfunc, and SuiteSparse chooses between them per call depending on whether a C
compiler is available. A result measured on one path is not evidence about
the other, so a machine with a compiler and a machine without run different
code, and a single-path test reports on whichever the runner happened to get.

udt_op_path parametrizes over both and pins jit_c_control for the
duration of the test. Two details there are load-bearing:

  • It sets the control rather than reading whatever is in effect. SuiteSparse
    demotes on to load after a failed compile, and a demoted control routes
    to the cfunc silently, so a jit cell would run the cfunc and pass.
  • It re-reads the control before restoring it and fails the test when it was
    demoted mid-test. No assertion inside the test can see that happen.

_jit_can_compile memoizes whether a usable compiler exists. It deliberately
does not consult jit_c_control, which is the per-test state the fixture
owns; folding the two together is what let a demoted control go unnoticed.

This adds no production code and no test cells. A parametrized fixture
creates cells only for tests that request it, and nothing requests it yet, so
the suite count is unchanged. It lands on its own so that each commit which
goes on to consume it carries only its own change in operator semantics.

_jit_can_compile asks _enable_jit_for_udt(), the call the UDT auto-lift path makes, which does one real compile per process. Importing graphblas.ss no longer probes the compiler (#630 now sits below this PR), so reading jit_c_control == 'on' as the probe's answer skipped the jit cells whenever nothing had enabled the JIT first.


Stack created with GitHub Stacks CLI • Give Feedback 💬

@eriknw
eriknw marked this pull request as ready for review August 4, 2026 16:07
@eriknw
eriknw force-pushed the 12-udt-dual-path-harness branch 2 times, most recently from f226963 to 4a76f9e Compare August 5, 2026 00:06
@eriknw
eriknw force-pushed the 12-udt-dual-path-harness branch from 4a76f9e to 50e6f33 Compare August 5, 2026 03:18
@eriknw
eriknw force-pushed the 12-udt-dual-path-harness branch from 50e6f33 to 575d24e Compare August 5, 2026 17:44
@eriknw
eriknw force-pushed the 12-udt-dual-path-harness branch from 575d24e to 7241dac Compare August 5, 2026 18:03
@eriknw
eriknw force-pushed the 12-udt-dual-path-harness branch from 7241dac to d3e8959 Compare August 5, 2026 18:05
@eriknw
eriknw force-pushed the 12-udt-dual-path-harness branch from d3e8959 to 6e582a3 Compare August 6, 2026 07:59
@eriknw
eriknw force-pushed the 12-udt-dual-path-harness branch from 6e582a3 to 72f6462 Compare August 6, 2026 15:39
@eriknw
eriknw force-pushed the 12-udt-dual-path-harness branch from 72f6462 to 8f797a7 Compare August 6, 2026 15:41
@eriknw
eriknw force-pushed the 12-udt-dual-path-harness branch 2 times, most recently from 39529a9 to 4a8f82f Compare August 6, 2026 20:41
@eriknw
eriknw force-pushed the 12-udt-dual-path-harness branch from 4a8f82f to 9ca1b59 Compare August 7, 2026 02:48
@eriknw
eriknw force-pushed the 12-udt-dual-path-harness branch from 9ca1b59 to d436a59 Compare August 7, 2026 05:09
@eriknw
eriknw force-pushed the 12-udt-dual-path-harness branch from d436a59 to be64cbc Compare August 26, 2026 17:30
@eriknw
eriknw force-pushed the 12-udt-dual-path-harness branch 2 times, most recently from 70aea20 to 7bb5368 Compare September 18, 2026 03:46
@eriknw
eriknw force-pushed the 12-udt-dual-path-harness branch from 7bb5368 to 6fb13a0 Compare September 18, 2026 17:34
@eriknw
eriknw force-pushed the 12-udt-dual-path-harness branch from 6fb13a0 to b62039e Compare September 18, 2026 17:39
@eriknw
eriknw force-pushed the 12-udt-dual-path-harness branch from b62039e to 8524eec Compare September 23, 2026 16:22
@eriknw
eriknw removed this pull request from stack #627 September 23, 2026 18:18
@eriknw
eriknw force-pushed the 12-udt-dual-path-harness branch from 8524eec to 8e9dd0d Compare September 23, 2026 18:19
@eriknw
eriknw added this pull request to stack #634 September 23, 2026 18:19
@eriknw
eriknw force-pushed the 12-udt-dual-path-harness branch from 8e9dd0d to aedd50d Compare September 24, 2026 20:06
@eriknw
eriknw force-pushed the 12-udt-dual-path-harness branch 2 times, most recently from 0672951 to ddcb7b2 Compare September 25, 2026 03:33
@eriknw
eriknw force-pushed the 12-udt-dual-path-harness branch 2 times, most recently from 5c10d71 to 2e422db Compare September 26, 2026 05:23
Each auto-lifted UDT operator carries both a JIT C definition and a Numba
cfunc, and SuiteSparse chooses between them per call depending on whether a C
compiler is available. A result measured on one path is not evidence about
the other, so a machine with a compiler and a machine without run different
code, and a single-path test reports on whichever the runner happened to get.

`udt_op_path` parametrizes over both and pins `jit_c_control` for the
duration of the test. Two details there are load-bearing:

- It sets the control rather than reading whatever is in effect. SuiteSparse
  demotes `on` to `load` after a failed compile, and a demoted control routes
  to the cfunc silently, so a `jit` cell would run the cfunc and pass.
- It re-reads the control before restoring it and fails the test when it was
  demoted mid-test. No assertion inside the test can see that happen.

`_jit_can_compile` memoizes whether a usable compiler exists. It deliberately
does not consult `jit_c_control`, which is the per-test state the fixture
owns; folding the two together is what let a demoted control go unnoticed.

This adds no production code and no test cells. A parametrized fixture
creates cells only for tests that request it, and nothing requests it yet, so
the suite count is unchanged. It lands on its own so that each commit which
goes on to consume it carries only its own change in operator semantics.
The gate read jit_c_control == 'on' as the success flag of the JIT probe
that importing graphblas.ss used to run. "Stop `gb.ss` import from turning
the SuiteSparse JIT on" (#630) now sits below this branch and took that
probe out of the import, so what the gate saw depended on whether anything
had enabled the JIT before the fixture first asked. test_ssjit.py does so
when it is collected. Without it, as when test_op.py runs on its own, the
control still reads SuiteSparse's default 'run', and on a machine with a
working compiler the fixture's first consumer (next branch up) skipped its
jit case as "JIT compilation not available" and ran only the cfunc.

_enable_jit_for_udt is the call the UDT auto-lift path makes, and it does a
real compile once per process, so the gate asks it instead and no longer
depends on collection order. This change was part of #630 while that PR sat
above this one.
@eriknw
eriknw force-pushed the 12-udt-dual-path-harness branch from 2e422db to 2d6467e Compare September 26, 2026 05:25
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.

1 participant