@@ -345,6 +345,52 @@ jobs:
345345 name : Alternative backends py${{ matrix.python-version }} linker=${{ matrix.linker }}
346346 fail_ci_if_error : false
347347
348+ free_threading :
349+ needs : changes
350+ if : ${{ needs.changes.outputs.changes == 'true' }}
351+ strategy :
352+ matrix :
353+ # A small, sampling-focused subset that exercises the thread-based parallel
354+ # sampling path used on free-threaded (no-GIL) builds. The GIL-stays-disabled
355+ # check is a pytest_sessionfinish hook in tests/conftest.py.
356+ test-subset :
357+ - |
358+ tests/sampling/test_parallel.py
359+ tests/step_methods/test_compound.py
360+ fail-fast : false
361+ runs-on : ubuntu-latest
362+ env :
363+ TEST_SUBSET : ${{ matrix.test-subset }}
364+ # Intentionally leave PYTHON_GIL unset. Setting it to 0 would force the GIL
365+ # off and hide a dependency that fails to support free-threading; leaving it
366+ # unset lets such a dependency re-enable the GIL, which the conftest
367+ # pytest_sessionfinish hook asserts against.
368+ defaults :
369+ run :
370+ shell : bash -leo pipefail {0}
371+ steps :
372+ - uses : actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
373+ with :
374+ persist-credentials : false
375+ - uses : actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0
376+ with :
377+ python-version : " 3.14t"
378+ - name : Install pymc and test dependencies
379+ run : |
380+ python -m pip install --upgrade pip
381+ # Install from PyPI (free-threaded wheels), not conda-forge. numba is
382+ # included as the free-threading-safe PyTensor backend.
383+ pip install -e . numba pytest pytest-cov
384+ # Free-threaded sampling needs the (still unreleased) PyTensor
385+ # free-threading support; track its branch until it is released.
386+ pip install "pytensor @ git+https://github.com/pymc-devs/pytensor@free_threaded"
387+ python --version
388+ python -c "import sys, sysconfig; print('Py_GIL_DISABLED =', sysconfig.get_config_var('Py_GIL_DISABLED'), '| gil_enabled =', sys._is_gil_enabled())"
389+ pip list
390+ - name : Run tests
391+ run : |
392+ python -m pytest -vv --durations=25 $TEST_SUBSET
393+
348394 float32 :
349395 needs : changes
350396 if : ${{ needs.changes.outputs.changes == 'true' }}
@@ -395,13 +441,14 @@ jobs:
395441 all_tests :
396442 if : ${{ always() }}
397443 runs-on : ubuntu-latest
398- needs : [changes, ubuntu, windows, macos, alternative_backends, float32]
444+ needs : [changes, ubuntu, windows, macos, alternative_backends, free_threading, float32]
399445 steps :
400446 - name : Check build matrix status
401447 if : ${{ needs.changes.outputs.changes == 'true' &&
402448 ( needs.ubuntu.result != 'success' ||
403449 needs.windows.result != 'success' ||
404450 needs.macos.result != 'success' ||
405451 needs.alternative_backends.result != 'success' ||
452+ needs.free_threading.result != 'success' ||
406453 needs.float32.result != 'success' ) }}
407454 run : exit 1
0 commit comments