@@ -345,6 +345,57 @@ 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+ # Disable the C backend (cxx=""). Its single-phase-init C extensions (e.g.
365+ # lazylinker_ext) re-enable the GIL on a free-threaded build; with no C
366+ # compiler PyTensor uses the free-threading-safe numba/Python backend.
367+ PYTENSOR_FLAGS : cxx=
368+ # Intentionally leave PYTHON_GIL unset. Setting it to 0 would force the GIL
369+ # off and hide a dependency that fails to support free-threading; leaving it
370+ # unset lets such a dependency re-enable the GIL, which the conftest
371+ # pytest_sessionfinish hook asserts against.
372+ defaults :
373+ run :
374+ shell : bash -leo pipefail {0}
375+ steps :
376+ - uses : actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
377+ with :
378+ persist-credentials : false
379+ - uses : actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0
380+ with :
381+ python-version : " 3.14t"
382+ - name : Install pymc and test dependencies
383+ run : |
384+ python -m pip install --upgrade pip
385+ # Install from PyPI (free-threaded wheels), not conda-forge. numba is
386+ # included as the free-threading-safe PyTensor backend.
387+ pip install -e . numba pytest pytest-cov
388+ # Free-threaded sampling needs the (still unreleased) PyTensor
389+ # free-threading support (pymc-devs/pytensor#2286); track its branch
390+ # until it is released.
391+ pip install "pytensor @ git+https://github.com/ricardoV94/pytensor@free_threaded"
392+ python --version
393+ python -c "import sys, sysconfig; print('Py_GIL_DISABLED =', sysconfig.get_config_var('Py_GIL_DISABLED'), '| gil_enabled =', sys._is_gil_enabled())"
394+ pip list
395+ - name : Run tests
396+ run : |
397+ python -m pytest -vv --durations=25 $TEST_SUBSET
398+
348399 float32 :
349400 needs : changes
350401 if : ${{ needs.changes.outputs.changes == 'true' }}
@@ -395,13 +446,14 @@ jobs:
395446 all_tests :
396447 if : ${{ always() }}
397448 runs-on : ubuntu-latest
398- needs : [changes, ubuntu, windows, macos, alternative_backends, float32]
449+ needs : [changes, ubuntu, windows, macos, alternative_backends, free_threading, float32]
399450 steps :
400451 - name : Check build matrix status
401452 if : ${{ needs.changes.outputs.changes == 'true' &&
402453 ( needs.ubuntu.result != 'success' ||
403454 needs.windows.result != 'success' ||
404455 needs.macos.result != 'success' ||
405456 needs.alternative_backends.result != 'success' ||
457+ needs.free_threading.result != 'success' ||
406458 needs.float32.result != 'success' ) }}
407459 run : exit 1
0 commit comments