Skip to content

Commit e0bea0c

Browse files
merge/resolve/fix
2 parents 7155fd1 + 5876145 commit e0bea0c

59 files changed

Lines changed: 2576 additions & 235 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/workflows/build-wheel.yml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ jobs:
3030
- "3.11"
3131
- "3.12"
3232
- "3.13"
33+
- "3.13t"
3334
name: py${{ matrix.python-version }}
3435
runs-on: ${{ (inputs.host-platform == 'linux-64' && 'linux-amd64-cpu8') ||
3536
(inputs.host-platform == 'linux-aarch64' && 'linux-arm64-cpu8') ||
@@ -116,6 +117,7 @@ jobs:
116117
CIBW_REPAIR_WHEEL_COMMAND_WINDOWS: "delvewheel repair --namespace-pkg cuda -w {dest_dir} {wheel}"
117118
CIBW_ENVIRONMENT: >
118119
CUDA_PYTHON_PARALLEL_LEVEL=${{ env.CUDA_PYTHON_PARALLEL_LEVEL }}
120+
CIBW_ENABLE: "cpython-freethreading"
119121
with:
120122
package-dir: ./cuda_core/
121123
output-dir: ${{ env.CUDA_CORE_ARTIFACTS_DIR }}
@@ -163,6 +165,7 @@ jobs:
163165
CUDA_PYTHON_PARALLEL_LEVEL=${{ env.CUDA_PYTHON_PARALLEL_LEVEL }}
164166
CIBW_BEFORE_BUILD_WINDOWS: "pip install delvewheel"
165167
CIBW_REPAIR_WHEEL_COMMAND_WINDOWS: "delvewheel repair --namespace-pkg cuda -w {dest_dir} {wheel}"
168+
CIBW_ENABLE: "cpython-freethreading"
166169
with:
167170
package-dir: ./cuda_bindings/
168171
output-dir: ${{ env.CUDA_BINDINGS_ARTIFACTS_DIR }}
@@ -223,6 +226,10 @@ jobs:
223226
# workaround for actions/runner-images#12377 (the cached 3.13.4 is buggy on Windows)
224227
python-version: ${{ matrix.python-version == '3.13' && '3.13.5' || matrix.python-version }}
225228

229+
- name: verify free-threaded build
230+
if: endsWith(matrix.python-verison, 't')
231+
run: python -c 'import sys; assert not sys._is_gil_enabled()'
232+
226233
- name: Set up Python include paths
227234
run: |
228235
if [[ "${{ inputs.host-platform }}" == linux* ]]; then

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ cuda_bindings/cuda/bindings/_bindings/cyruntime_ptds.pxd
2727
cuda_bindings/cuda/bindings/_bindings/cyruntime_ptds.pyx
2828
cuda_bindings/cuda/bindings/_bindings/cynvrtc.pxd
2929
cuda_bindings/cuda/bindings/_bindings/cynvrtc.pyx
30+
cuda_bindings/cuda/bindings/_internal/cufile.pyx
3031
cuda_bindings/cuda/bindings/_internal/nvjitlink.pyx
3132
cuda_bindings/cuda/bindings/_internal/nvvm.pyx
3233
cuda_bindings/cuda/bindings/_lib/utils.pxd

ci/test-matrix.json

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
{ "ARCH": "amd64", "PY_VER": "3.12", "CUDA_VER": "13.0.1", "LOCAL_CTK": "0", "GPU": "l4", "DRIVER": "latest" },
1515
{ "ARCH": "amd64", "PY_VER": "3.13", "CUDA_VER": "12.9.1", "LOCAL_CTK": "0", "GPU": "l4", "DRIVER": "latest" },
1616
{ "ARCH": "amd64", "PY_VER": "3.13", "CUDA_VER": "13.0.1", "LOCAL_CTK": "1", "GPU": "l4", "DRIVER": "latest" },
17+
{ "ARCH": "amd64", "PY_VER": "3.13t", "CUDA_VER": "13.0.1", "LOCAL_CTK": "1", "GPU": "l4", "DRIVER": "latest" },
1718
{ "ARCH": "arm64", "PY_VER": "3.9", "CUDA_VER": "12.9.1", "LOCAL_CTK": "0", "GPU": "a100", "DRIVER": "latest" },
1819
{ "ARCH": "arm64", "PY_VER": "3.9", "CUDA_VER": "13.0.1", "LOCAL_CTK": "1", "GPU": "a100", "DRIVER": "latest" },
1920
{ "ARCH": "arm64", "PY_VER": "3.10", "CUDA_VER": "12.9.1", "LOCAL_CTK": "1", "GPU": "a100", "DRIVER": "latest" },
@@ -23,7 +24,8 @@
2324
{ "ARCH": "arm64", "PY_VER": "3.12", "CUDA_VER": "12.9.1", "LOCAL_CTK": "1", "GPU": "a100", "DRIVER": "latest" },
2425
{ "ARCH": "arm64", "PY_VER": "3.12", "CUDA_VER": "13.0.1", "LOCAL_CTK": "0", "GPU": "a100", "DRIVER": "latest" },
2526
{ "ARCH": "arm64", "PY_VER": "3.13", "CUDA_VER": "12.9.1", "LOCAL_CTK": "0", "GPU": "a100", "DRIVER": "latest" },
26-
{ "ARCH": "arm64", "PY_VER": "3.13", "CUDA_VER": "13.0.1", "LOCAL_CTK": "1", "GPU": "a100", "DRIVER": "latest" }
27+
{ "ARCH": "arm64", "PY_VER": "3.13", "CUDA_VER": "13.0.1", "LOCAL_CTK": "1", "GPU": "a100", "DRIVER": "latest" },
28+
{ "ARCH": "arm64", "PY_VER": "3.13t", "CUDA_VER": "13.0.1", "LOCAL_CTK": "1", "GPU": "a100", "DRIVER": "latest" }
2729
],
2830
"nightly": [
2931
{ "ARCH": "amd64", "PY_VER": "3.9", "CUDA_VER": "11.8.0", "LOCAL_CTK": "0", "GPU": "l4", "DRIVER": "earliest" },
@@ -51,6 +53,11 @@
5153
{ "ARCH": "amd64", "PY_VER": "3.13", "CUDA_VER": "12.0.1", "LOCAL_CTK": "1", "GPU": "l4", "DRIVER": "latest" },
5254
{ "ARCH": "amd64", "PY_VER": "3.13", "CUDA_VER": "12.9.1", "LOCAL_CTK": "0", "GPU": "l4", "DRIVER": "latest" },
5355
{ "ARCH": "amd64", "PY_VER": "3.13", "CUDA_VER": "12.9.1", "LOCAL_CTK": "1", "GPU": "l4", "DRIVER": "latest" },
56+
{ "ARCH": "amd64", "PY_VER": "3.13t", "CUDA_VER": "11.8.0", "LOCAL_CTK": "0", "GPU": "l4", "DRIVER": "earliest" },
57+
{ "ARCH": "amd64", "PY_VER": "3.13t", "CUDA_VER": "11.8.0", "LOCAL_CTK": "1", "GPU": "l4", "DRIVER": "latest" },
58+
{ "ARCH": "amd64", "PY_VER": "3.13t", "CUDA_VER": "12.0.1", "LOCAL_CTK": "1", "GPU": "l4", "DRIVER": "latest" },
59+
{ "ARCH": "amd64", "PY_VER": "3.13t", "CUDA_VER": "12.9.1", "LOCAL_CTK": "0", "GPU": "l4", "DRIVER": "latest" },
60+
{ "ARCH": "amd64", "PY_VER": "3.13t", "CUDA_VER": "12.9.1", "LOCAL_CTK": "1", "GPU": "l4", "DRIVER": "latest" },
5461
{ "ARCH": "arm64", "PY_VER": "3.9", "CUDA_VER": "11.8.0", "LOCAL_CTK": "0", "GPU": "a100", "DRIVER": "earliest" },
5562
{ "ARCH": "arm64", "PY_VER": "3.9", "CUDA_VER": "11.8.0", "LOCAL_CTK": "1", "GPU": "a100", "DRIVER": "latest" },
5663
{ "ARCH": "arm64", "PY_VER": "3.9", "CUDA_VER": "12.0.1", "LOCAL_CTK": "1", "GPU": "a100", "DRIVER": "latest" },
@@ -88,13 +95,17 @@
8895
{ "ARCH": "amd64", "PY_VER": "3.12", "CUDA_VER": "12.9.1", "LOCAL_CTK": "0", "GPU": "l4", "DRIVER": "latest" },
8996
{ "ARCH": "amd64", "PY_VER": "3.12", "CUDA_VER": "12.9.1", "LOCAL_CTK": "1", "GPU": "t4", "DRIVER": "latest" },
9097
{ "ARCH": "amd64", "PY_VER": "3.13", "CUDA_VER": "13.0.1", "LOCAL_CTK": "0", "GPU": "t4", "DRIVER": "latest" },
91-
{ "ARCH": "amd64", "PY_VER": "3.13", "CUDA_VER": "13.0.1", "LOCAL_CTK": "1", "GPU": "l4", "DRIVER": "latest" }
98+
{ "ARCH": "amd64", "PY_VER": "3.13", "CUDA_VER": "13.0.1", "LOCAL_CTK": "1", "GPU": "l4", "DRIVER": "latest" },
99+
{ "ARCH": "amd64", "PY_VER": "3.13t", "CUDA_VER": "13.0.1", "LOCAL_CTK": "0", "GPU": "t4", "DRIVER": "latest" },
100+
{ "ARCH": "amd64", "PY_VER": "3.13t", "CUDA_VER": "13.0.1", "LOCAL_CTK": "1", "GPU": "l4", "DRIVER": "latest" }
92101
],
93102
"nightly": [
94103
{ "ARCH": "amd64", "PY_VER": "3.12", "CUDA_VER": "11.8.0", "LOCAL_CTK": "0", "GPU": "l4", "DRIVER": "latest" },
95104
{ "ARCH": "amd64", "PY_VER": "3.12", "CUDA_VER": "11.8.0", "LOCAL_CTK": "1", "GPU": "t4", "DRIVER": "latest" },
96105
{ "ARCH": "amd64", "PY_VER": "3.12", "CUDA_VER": "12.9.1", "LOCAL_CTK": "0", "GPU": "t4", "DRIVER": "latest" },
97-
{ "ARCH": "amd64", "PY_VER": "3.12", "CUDA_VER": "12.9.1", "LOCAL_CTK": "1", "GPU": "l4", "DRIVER": "latest" }
106+
{ "ARCH": "amd64", "PY_VER": "3.12", "CUDA_VER": "12.9.1", "LOCAL_CTK": "1", "GPU": "l4", "DRIVER": "latest" },
107+
{ "ARCH": "amd64", "PY_VER": "3.13t", "CUDA_VER": "13.0.1", "LOCAL_CTK": "0", "GPU": "t4", "DRIVER": "latest" },
108+
{ "ARCH": "amd64", "PY_VER": "3.13t", "CUDA_VER": "13.0.1", "LOCAL_CTK": "1", "GPU": "l4", "DRIVER": "latest" }
98109
]
99110
}
100111
}

ci/tools/run-tests

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,10 @@ if [[ "${test_module}" == "pathfinder" ]]; then
3535
"LD:${CUDA_PATHFINDER_TEST_LOAD_NVIDIA_DYNAMIC_LIB_STRICTNESS} " \
3636
"FH:${CUDA_PATHFINDER_TEST_FIND_NVIDIA_HEADERS_STRICTNESS}"
3737
pwd
38-
pytest -ra -s -v tests/
38+
pytest -ra -s -v tests/ |& tee /tmp/pathfinder_test_log.txt
39+
# Fail if no "INFO test_" lines are found; capture line count otherwise
40+
line_count=$(grep '^INFO test_' /tmp/pathfinder_test_log.txt | wc -l)
41+
echo "Number of \"INFO test_\" lines: $line_count"
3942
popd
4043
elif [[ "${test_module}" == "bindings" ]]; then
4144
pushd "${CUDA_BINDINGS_ARTIFACTS_DIR}"
@@ -77,12 +80,18 @@ elif [[ "${test_module}" == "core" ]]; then
7780
echo "Installing core wheel"
7881
pwd
7982
ls
83+
84+
FREE_THREADING=""
85+
if python -c 'import sys; assert not sys._is_gil_enabled()' 2> /dev/null; then
86+
FREE_THREADING+="-ft"
87+
fi
88+
8089
if [[ "${LOCAL_CTK}" == 1 ]]; then
8190
# We already installed cuda-bindings, and all CTK components exist locally,
8291
# so just install the test dependencies.
83-
pip install $(ls *.whl)["test-cu${TEST_CUDA_MAJOR}"]
92+
pip install $(ls *.whl)["test-cu${TEST_CUDA_MAJOR}${FREE_THREADING}"]
8493
else
85-
pip install $(ls *.whl)["cu${TEST_CUDA_MAJOR}","test-cu${TEST_CUDA_MAJOR}"]
94+
pip install $(ls *.whl)["cu${TEST_CUDA_MAJOR}","test-cu${TEST_CUDA_MAJOR}${FREE_THREADING}"]
8695
fi
8796
popd
8897
pushd ./cuda_core

conftest.py

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
# SPDX-FileCopyrightText: Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
2+
# SPDX-License-Identifier: Apache-2.0
3+
4+
import os
5+
import pytest
6+
7+
8+
def pytest_collection_modifyitems(config, items):
9+
cuda_home = os.environ.get("CUDA_HOME")
10+
for item in items:
11+
nodeid = item.nodeid.replace("\\", "/")
12+
13+
# Package markers by path
14+
if (
15+
nodeid.startswith("cuda_pathfinder/tests/")
16+
or "/cuda_pathfinder/tests/" in nodeid
17+
):
18+
item.add_marker(pytest.mark.pathfinder)
19+
if (
20+
nodeid.startswith("cuda_bindings/tests/")
21+
or "/cuda_bindings/tests/" in nodeid
22+
):
23+
item.add_marker(pytest.mark.bindings)
24+
if nodeid.startswith("cuda_core/tests/") or "/cuda_core/tests/" in nodeid:
25+
item.add_marker(pytest.mark.core)
26+
27+
# Smoke tests
28+
if nodeid.startswith("tests/integration/") or "/tests/integration/" in nodeid:
29+
item.add_marker(pytest.mark.smoke)
30+
31+
# Cython tests (any tests/cython subtree)
32+
if (
33+
"/tests/cython/" in nodeid
34+
or nodeid.endswith("/tests/cython")
35+
or ("/cython/" in nodeid and "/tests/" in nodeid)
36+
):
37+
item.add_marker(pytest.mark.cython)
38+
39+
# Gate core cython tests on CUDA_HOME
40+
if "core" in item.keywords and not cuda_home:
41+
item.add_marker(
42+
pytest.mark.skip(
43+
reason="CUDA_HOME not set; skipping core cython tests"
44+
)
45+
)

cuda_bindings/cuda/bindings/_bindings/cydriver.pxd.in

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2239,6 +2239,11 @@ cdef CUresult _cuCheckpointProcessLock(int pid, CUcheckpointLockArgs* args) exce
22392239
cdef CUresult _cuCheckpointProcessCheckpoint(int pid, CUcheckpointCheckpointArgs* args) except ?CUDA_ERROR_NOT_FOUND nogil
22402240
{{endif}}
22412241

2242+
{{if 'cuCheckpointProcessRestore' in found_functions}}
2243+
2244+
cdef CUresult _cuCheckpointProcessRestore(int pid, CUcheckpointRestoreArgs* args) except ?CUDA_ERROR_NOT_FOUND nogil
2245+
{{endif}}
2246+
22422247
{{if 'cuCheckpointProcessUnlock' in found_functions}}
22432248

22442249
cdef CUresult _cuCheckpointProcessUnlock(int pid, CUcheckpointUnlockArgs* args) except ?CUDA_ERROR_NOT_FOUND nogil

cuda_bindings/cuda/bindings/_bindings/cydriver.pyx.in

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -463,6 +463,7 @@ cdef bint __cuPythonInit = False
463463
{{if 'cuCheckpointProcessGetState' in found_functions}}cdef void *__cuCheckpointProcessGetState = NULL{{endif}}
464464
{{if 'cuCheckpointProcessLock' in found_functions}}cdef void *__cuCheckpointProcessLock = NULL{{endif}}
465465
{{if 'cuCheckpointProcessCheckpoint' in found_functions}}cdef void *__cuCheckpointProcessCheckpoint = NULL{{endif}}
466+
{{if 'cuCheckpointProcessRestore' in found_functions}}cdef void *__cuCheckpointProcessRestore = NULL{{endif}}
466467
{{if 'cuCheckpointProcessUnlock' in found_functions}}cdef void *__cuCheckpointProcessUnlock = NULL{{endif}}
467468
{{if 'cuProfilerStart' in found_functions}}cdef void *__cuProfilerStart = NULL{{endif}}
468469
{{if 'cuProfilerStop' in found_functions}}cdef void *__cuProfilerStop = NULL{{endif}}
@@ -2667,6 +2668,10 @@ cdef int _cuPythonInit() except -1 nogil:
26672668
global __cuCheckpointProcessCheckpoint
26682669
_F_cuGetProcAddress_v2('cuCheckpointProcessCheckpoint', &__cuCheckpointProcessCheckpoint, 12080, CU_GET_PROC_ADDRESS_DEFAULT, NULL)
26692670
{{endif}}
2671+
{{if 'cuCheckpointProcessRestore' in found_functions}}
2672+
global __cuCheckpointProcessRestore
2673+
_F_cuGetProcAddress_v2('cuCheckpointProcessRestore', &__cuCheckpointProcessRestore, 12080, CU_GET_PROC_ADDRESS_DEFAULT, NULL)
2674+
{{endif}}
26702675
{{if 'cuCheckpointProcessUnlock' in found_functions}}
26712676
global __cuCheckpointProcessUnlock
26722677
_F_cuGetProcAddress_v2('cuCheckpointProcessUnlock', &__cuCheckpointProcessUnlock, 12080, CU_GET_PROC_ADDRESS_DEFAULT, NULL)
@@ -4895,6 +4900,10 @@ cdef int _cuPythonInit() except -1 nogil:
48954900
global __cuCheckpointProcessCheckpoint
48964901
__cuCheckpointProcessCheckpoint = windll.GetProcAddress(handle, 'cuCheckpointProcessCheckpoint')
48974902
{{endif}}
4903+
{{if 'cuCheckpointProcessRestore' in found_functions}}
4904+
global __cuCheckpointProcessRestore
4905+
__cuCheckpointProcessRestore = windll.GetProcAddress(handle, 'cuCheckpointProcessRestore')
4906+
{{endif}}
48984907
{{if 'cuCheckpointProcessUnlock' in found_functions}}
48994908
global __cuCheckpointProcessUnlock
49004909
__cuCheckpointProcessUnlock = windll.GetProcAddress(handle, 'cuCheckpointProcessUnlock')
@@ -7120,6 +7129,10 @@ cdef int _cuPythonInit() except -1 nogil:
71207129
global __cuCheckpointProcessCheckpoint
71217130
__cuCheckpointProcessCheckpoint = dlfcn.dlsym(handle, 'cuCheckpointProcessCheckpoint')
71227131
{{endif}}
7132+
{{if 'cuCheckpointProcessRestore' in found_functions}}
7133+
global __cuCheckpointProcessRestore
7134+
__cuCheckpointProcessRestore = dlfcn.dlsym(handle, 'cuCheckpointProcessRestore')
7135+
{{endif}}
71237136
{{if 'cuCheckpointProcessUnlock' in found_functions}}
71247137
global __cuCheckpointProcessUnlock
71257138
__cuCheckpointProcessUnlock = dlfcn.dlsym(handle, 'cuCheckpointProcessUnlock')
@@ -12583,6 +12596,18 @@ cdef CUresult _cuCheckpointProcessCheckpoint(int pid, CUcheckpointCheckpointArgs
1258312596
return err
1258412597
{{endif}}
1258512598

12599+
{{if 'cuCheckpointProcessRestore' in found_functions}}
12600+
12601+
cdef CUresult _cuCheckpointProcessRestore(int pid, CUcheckpointRestoreArgs* args) except ?CUDA_ERROR_NOT_FOUND nogil:
12602+
global __cuCheckpointProcessRestore
12603+
cuPythonInit()
12604+
if __cuCheckpointProcessRestore == NULL:
12605+
with gil:
12606+
raise RuntimeError('Function "cuCheckpointProcessRestore" not found')
12607+
err = (<CUresult (*)(int, CUcheckpointRestoreArgs*) except ?CUDA_ERROR_NOT_FOUND nogil> __cuCheckpointProcessRestore)(pid, args)
12608+
return err
12609+
{{endif}}
12610+
1258612611
{{if 'cuCheckpointProcessUnlock' in found_functions}}
1258712612

1258812613
cdef CUresult _cuCheckpointProcessUnlock(int pid, CUcheckpointUnlockArgs* args) except ?CUDA_ERROR_NOT_FOUND nogil:
@@ -15986,6 +16011,13 @@ cpdef dict _inspect_function_pointers():
1598616011
data["__cuCheckpointProcessCheckpoint"] = <intptr_t>0
1598716012
{{endif}}
1598816013

16014+
{{if 'cuCheckpointProcessRestore' in found_functions}}
16015+
global __cuCheckpointProcessRestore
16016+
data["__cuCheckpointProcessRestore"] = <intptr_t>__cuCheckpointProcessRestore
16017+
{{else}}
16018+
data["__cuCheckpointProcessRestore"] = <intptr_t>0
16019+
{{endif}}
16020+
1598916021
{{if 'cuCheckpointProcessUnlock' in found_functions}}
1599016022
global __cuCheckpointProcessUnlock
1599116023
data["__cuCheckpointProcessUnlock"] = <intptr_t>__cuCheckpointProcessUnlock

0 commit comments

Comments
 (0)