Skip to content

Commit 3fed528

Browse files
authored
Merge branch 'main' into test/vuln-malware-onboarding
2 parents 1bd3b7d + 9b07a93 commit 3fed528

80 files changed

Lines changed: 2442 additions & 255 deletions

File tree

Some content is hidden

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

‎.github/workflows/coverage.yml‎

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -250,6 +250,14 @@ jobs:
250250
- name: Set up MSVC
251251
uses: step-security/msvc-dev-cmd@22c98154b708dbd743e6f27a933cf6ceba3305c4 # v1.13.1
252252

253+
- name: Raise the interpreter's stack reserve to 8 MiB
254+
# Importing the coverage-built cuda.bindings.driver overflows the
255+
# 2,000,000-byte main-thread stack of python-build-standalone (#3330).
256+
run: |
257+
base_py="$(.venv/Scripts/python -c 'import sys; print(sys._base_executable)')"
258+
editbin -nologo -stack:8388608 "$base_py"
259+
dumpbin -nologo -headers "$base_py" | grep -i "size of stack reserve"
260+
253261
- name: Set up mini CTK
254262
uses: ./.github/actions/fetch_ctk
255263
continue-on-error: false

‎CONTRIBUTING.md‎

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -37,21 +37,26 @@ reproducers, documentation improvements, and code changes are welcome.
3737

3838
## Coordinate before implementing
3939

40-
Review capacity is limited. If you are contributing from outside NVIDIA:
40+
Our review and CI capacities are limited. If you are contributing from outside NVIDIA:
4141

42-
- **Existing issue:** comment and wait for a maintainer to assign it to you or
42+
- **Existing issues:** comment and wait for a maintainer to assign it to you or
4343
explicitly ask you to implement it. Check existing assignments and requests
4444
to take the issue.
45-
- **New features, design changes, or CI/release infrastructure:** open an issue
46-
and agree on scope and validation before implementing.
47-
- **Small standalone bug or documentation fixes without an existing issue:**
48-
a direct PR is welcome. Explain the problem and how you checked the fix.
45+
- **New features, bug/documentation fixes, RFCs, or code updates/enhancements:** open an
46+
issue, agree on scope and validation, and wait for the assignment before implementing.
4947

50-
NVIDIA contributors may use normal team planning and self-assignment.
48+
For obvious issues, opening a one-liner issue for tracking and assignment purposes is
49+
completely fine.
50+
51+
For bug reports, please include a reproducer with a clear description for the expected
52+
versus observed behavior. Also include the CUDA driver version and the Python environment
53+
information (ex: `pip list`, `conda list`, ..., depending on how the environment was
54+
created).
5155

52-
Feel free to report a bug or send reproducers, measurements, and suggestions
53-
without an assignment. Include relevant versions and expected versus observed
54-
behavior in bug reports.
56+
Please do not send unsolicited (i.e. without prior discussion and assignment) PRs, which
57+
could be closed without notice subject to the team's triage.
58+
59+
NVIDIA contributors may use normal team planning and self-assignment.
5560

5661
Keep changes focused, understand the complete diff, and report which checks
5762
ran and any validation gaps.

‎ci/test-matrix.yml‎

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -100,12 +100,10 @@ linux:
100100
- { ARCH: 'amd64', PY_VER: '3.12', CUDA_VER: '13.4.2', LOCAL_CTK: '0', GPU: 'rtx4090', GPU_COUNT: '1', DRIVER: 'latest', FLAVOR: 'wsl' }
101101
nightly:
102102
# nightly-pytorch
103-
- { ARCH: 'amd64', PY_VER: '3.12', CUDA_VER: '12.6.3', LOCAL_CTK: '0', GPU: 'l4', GPU_COUNT: '1', DRIVER: 'latest', ENV: { MODE: 'nightly-pytorch', TORCH_VER: '2.12.1', TORCH_CUDA: 'cu126' } }
104-
- { ARCH: 'amd64', PY_VER: '3.12', CUDA_VER: '13.0.2', LOCAL_CTK: '0', GPU: 'l4', GPU_COUNT: '1', DRIVER: 'latest', ENV: { MODE: 'nightly-pytorch', TORCH_VER: '2.12.1', TORCH_CUDA: 'cu130' } }
103+
- { ARCH: 'amd64', PY_VER: '3.12', CUDA_VER: '13.2.2', LOCAL_CTK: '0', GPU: 'l4', GPU_COUNT: '1', DRIVER: 'latest', ENV: { MODE: 'nightly-pytorch', TORCH_VER: '2.15.0', TORCH_CUDA: 'cu132' } }
105104
- { ARCH: 'amd64', PY_VER: '3.12', CUDA_VER: '12.6.3', LOCAL_CTK: '0', GPU: 'l4', GPU_COUNT: '1', DRIVER: 'latest', ENV: { MODE: 'nightly-pytorch', TORCH_VER: '2.9.1', TORCH_CUDA: 'cu126' } }
106105
- { ARCH: 'amd64', PY_VER: '3.12', CUDA_VER: '13.0.2', LOCAL_CTK: '0', GPU: 'l4', GPU_COUNT: '1', DRIVER: 'latest', ENV: { MODE: 'nightly-pytorch', TORCH_VER: '2.9.1', TORCH_CUDA: 'cu130' } }
107-
- { ARCH: 'arm64', PY_VER: '3.12', CUDA_VER: '12.6.3', LOCAL_CTK: '0', GPU: 'l4', GPU_COUNT: '1', DRIVER: 'latest', ENV: { MODE: 'nightly-pytorch', TORCH_VER: '2.12.1', TORCH_CUDA: 'cu126' } }
108-
- { ARCH: 'arm64', PY_VER: '3.12', CUDA_VER: '13.0.2', LOCAL_CTK: '0', GPU: 'l4', GPU_COUNT: '1', DRIVER: 'latest', ENV: { MODE: 'nightly-pytorch', TORCH_VER: '2.12.1', TORCH_CUDA: 'cu130' } }
106+
- { ARCH: 'arm64', PY_VER: '3.12', CUDA_VER: '13.2.2', LOCAL_CTK: '0', GPU: 'l4', GPU_COUNT: '1', DRIVER: 'latest', ENV: { MODE: 'nightly-pytorch', TORCH_VER: '2.15.0', TORCH_CUDA: 'cu132' } }
109107
- { ARCH: 'arm64', PY_VER: '3.12', CUDA_VER: '12.6.3', LOCAL_CTK: '0', GPU: 'l4', GPU_COUNT: '1', DRIVER: 'latest', ENV: { MODE: 'nightly-pytorch', TORCH_VER: '2.9.1', TORCH_CUDA: 'cu126' } }
110108
- { ARCH: 'arm64', PY_VER: '3.12', CUDA_VER: '13.0.2', LOCAL_CTK: '0', GPU: 'l4', GPU_COUNT: '1', DRIVER: 'latest', ENV: { MODE: 'nightly-pytorch', TORCH_VER: '2.9.1', TORCH_CUDA: 'cu130' } }
111109
# nightly-numba-cuda
@@ -153,8 +151,7 @@ windows:
153151
- { ARCH: 'amd64', PY_VER: '3.14', CUDA_VER: '13.4.2', LOCAL_CTK: '0', GPU: 'h100', GPU_COUNT: '2', DRIVER: 'latest', DRIVER_MODE: 'MCDM' }
154152
nightly:
155153
# nightly-pytorch
156-
- { ARCH: 'amd64', PY_VER: '3.12', CUDA_VER: '12.6.3', LOCAL_CTK: '0', GPU: 'l4', GPU_COUNT: '1', DRIVER: 'latest', DRIVER_MODE: 'TCC', ENV: { MODE: 'nightly-pytorch', TORCH_VER: '2.12.1', TORCH_CUDA: 'cu126' } }
157-
- { ARCH: 'amd64', PY_VER: '3.12', CUDA_VER: '13.0.2', LOCAL_CTK: '0', GPU: 'l4', GPU_COUNT: '1', DRIVER: 'latest', DRIVER_MODE: 'TCC', ENV: { MODE: 'nightly-pytorch', TORCH_VER: '2.12.1', TORCH_CUDA: 'cu130' } }
154+
- { ARCH: 'amd64', PY_VER: '3.12', CUDA_VER: '13.2.2', LOCAL_CTK: '0', GPU: 'l4', GPU_COUNT: '1', DRIVER: 'latest', DRIVER_MODE: 'TCC', ENV: { MODE: 'nightly-pytorch', TORCH_VER: '2.15.0', TORCH_CUDA: 'cu132' } }
158155
- { ARCH: 'amd64', PY_VER: '3.12', CUDA_VER: '12.6.3', LOCAL_CTK: '0', GPU: 'l4', GPU_COUNT: '1', DRIVER: 'latest', DRIVER_MODE: 'TCC', ENV: { MODE: 'nightly-pytorch', TORCH_VER: '2.9.1', TORCH_CUDA: 'cu126' } }
159156
- { ARCH: 'amd64', PY_VER: '3.12', CUDA_VER: '13.0.2', LOCAL_CTK: '0', GPU: 'l4', GPU_COUNT: '1', DRIVER: 'latest', DRIVER_MODE: 'TCC', ENV: { MODE: 'nightly-pytorch', TORCH_VER: '2.9.1', TORCH_CUDA: 'cu130' } }
160157
# nightly-numba-cuda

‎cuda_bindings_12/pyproject.toml‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,9 @@ ignore = [
104104
exclude = ["cuda/bindings/_version.py"]
105105

106106
[tool.ruff.lint.per-file-ignores]
107+
# This config replaces ../ruff.toml for this tree, so it repeats that file's
108+
# S101 policy: asserts are rejected only in cuda_core/cuda/core.
109+
"**" = ["S101"]
107110
"setup.py" = ["F401"]
108111
"__init__.py" = ["F401"]
109112
"site-packages/_cuda_bindings_redirector.py" = ["F401"]

‎cuda_bindings_13/cuda/bindings/cudla.pyx‎

Lines changed: 49 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
# SPDX-License-Identifier: Apache-2.0
33

44
# This code was automatically generated across versions from 1.5.0 to 13.4.1. Do not modify it directly.
5-
# CYTHON-BINDINGS-GENERATED-DO-NOT-MODIFY-THIS-FILE: format=1; content-sha256=50159aaec5737fc94f227c703c6abe29874cd8022b8f545b46498e9c5862c4e6
5+
# CYTHON-BINDINGS-GENERATED-DO-NOT-MODIFY-THIS-FILE: format=1; content-sha256=92945a025bf01ceb29f21539fb32be8db41c402bec2606a8d92b79e869a0c0ed
66

77

88
# <<<< PREAMBLE CONTENT >>>>
@@ -1597,30 +1597,54 @@ class Status(_cyb_IntEnum):
15971597
"""
15981598
See `cudlaStatus`.
15991599
"""
1600-
Success = cudlaSuccess
1601-
ErrorInvalidParam = cudlaErrorInvalidParam
1602-
ErrorOutOfResources = cudlaErrorOutOfResources
1603-
ErrorCreationFailed = cudlaErrorCreationFailed
1604-
ErrorInvalidAddress = cudlaErrorInvalidAddress
1605-
ErrorOs = cudlaErrorOs
1606-
ErrorCuda = cudlaErrorCuda
1607-
ErrorUmd = cudlaErrorUmd
1608-
ErrorInvalidDevice = cudlaErrorInvalidDevice
1609-
ErrorInvalidAttribute = cudlaErrorInvalidAttribute
1610-
ErrorIncompatibleDlaSWVersion = cudlaErrorIncompatibleDlaSWVersion
1611-
ErrorMemoryRegistered = cudlaErrorMemoryRegistered
1612-
ErrorInvalidModule = cudlaErrorInvalidModule
1613-
ErrorUnsupportedOperation = cudlaErrorUnsupportedOperation
1614-
ErrorNvSci = cudlaErrorNvSci
1615-
ErrorDriverNotFound = cudlaErrorDriverNotFound
1616-
ErrorDlaErrInvalidInput = cudlaErrorDlaErrInvalidInput
1617-
ErrorDlaErrInvalidPreAction = cudlaErrorDlaErrInvalidPreAction
1618-
ErrorDlaErrNoMem = cudlaErrorDlaErrNoMem
1619-
ErrorDlaErrProcessorBusy = cudlaErrorDlaErrProcessorBusy
1620-
ErrorDlaErrTaskStatusMismatch = cudlaErrorDlaErrTaskStatusMismatch
1621-
ErrorDlaErrEngineTimeout = cudlaErrorDlaErrEngineTimeout
1622-
ErrorDlaErrDataMismatch = cudlaErrorDlaErrDataMismatch
1623-
ErrorUnknown = cudlaErrorUnknown
1600+
SUCCESS = cudlaSuccess
1601+
Success = SUCCESS # backward-compat alias
1602+
ERROR_INVALID_PARAM = cudlaErrorInvalidParam
1603+
ErrorInvalidParam = ERROR_INVALID_PARAM # backward-compat alias
1604+
ERROR_OUT_OF_RESOURCES = cudlaErrorOutOfResources
1605+
ErrorOutOfResources = ERROR_OUT_OF_RESOURCES # backward-compat alias
1606+
ERROR_CREATION_FAILED = cudlaErrorCreationFailed
1607+
ErrorCreationFailed = ERROR_CREATION_FAILED # backward-compat alias
1608+
ERROR_INVALID_ADDRESS = cudlaErrorInvalidAddress
1609+
ErrorInvalidAddress = ERROR_INVALID_ADDRESS # backward-compat alias
1610+
ERROR_OS = cudlaErrorOs
1611+
ErrorOs = ERROR_OS # backward-compat alias
1612+
ERROR_CUDA = cudlaErrorCuda
1613+
ErrorCuda = ERROR_CUDA # backward-compat alias
1614+
ERROR_UMD = cudlaErrorUmd
1615+
ErrorUmd = ERROR_UMD # backward-compat alias
1616+
ERROR_INVALID_DEVICE = cudlaErrorInvalidDevice
1617+
ErrorInvalidDevice = ERROR_INVALID_DEVICE # backward-compat alias
1618+
ERROR_INVALID_ATTRIBUTE = cudlaErrorInvalidAttribute
1619+
ErrorInvalidAttribute = ERROR_INVALID_ATTRIBUTE # backward-compat alias
1620+
ERROR_INCOMPATIBLE_DLA_SW_VERSION = cudlaErrorIncompatibleDlaSWVersion
1621+
ErrorIncompatibleDlaSWVersion = ERROR_INCOMPATIBLE_DLA_SW_VERSION # backward-compat alias
1622+
ERROR_MEMORY_REGISTERED = cudlaErrorMemoryRegistered
1623+
ErrorMemoryRegistered = ERROR_MEMORY_REGISTERED # backward-compat alias
1624+
ERROR_INVALID_MODULE = cudlaErrorInvalidModule
1625+
ErrorInvalidModule = ERROR_INVALID_MODULE # backward-compat alias
1626+
ERROR_UNSUPPORTED_OPERATION = cudlaErrorUnsupportedOperation
1627+
ErrorUnsupportedOperation = ERROR_UNSUPPORTED_OPERATION # backward-compat alias
1628+
ERROR_NV_SCI = cudlaErrorNvSci
1629+
ErrorNvSci = ERROR_NV_SCI # backward-compat alias
1630+
ERROR_DRIVER_NOT_FOUND = cudlaErrorDriverNotFound
1631+
ErrorDriverNotFound = ERROR_DRIVER_NOT_FOUND # backward-compat alias
1632+
ERROR_DLA_ERR_INVALID_INPUT = cudlaErrorDlaErrInvalidInput
1633+
ErrorDlaErrInvalidInput = ERROR_DLA_ERR_INVALID_INPUT # backward-compat alias
1634+
ERROR_DLA_ERR_INVALID_PRE_ACTION = cudlaErrorDlaErrInvalidPreAction
1635+
ErrorDlaErrInvalidPreAction = ERROR_DLA_ERR_INVALID_PRE_ACTION # backward-compat alias
1636+
ERROR_DLA_ERR_NO_MEM = cudlaErrorDlaErrNoMem
1637+
ErrorDlaErrNoMem = ERROR_DLA_ERR_NO_MEM # backward-compat alias
1638+
ERROR_DLA_ERR_PROCESSOR_BUSY = cudlaErrorDlaErrProcessorBusy
1639+
ErrorDlaErrProcessorBusy = ERROR_DLA_ERR_PROCESSOR_BUSY # backward-compat alias
1640+
ERROR_DLA_ERR_TASK_STATUS_MISMATCH = cudlaErrorDlaErrTaskStatusMismatch
1641+
ErrorDlaErrTaskStatusMismatch = ERROR_DLA_ERR_TASK_STATUS_MISMATCH # backward-compat alias
1642+
ERROR_DLA_ERR_ENGINE_TIMEOUT = cudlaErrorDlaErrEngineTimeout
1643+
ErrorDlaErrEngineTimeout = ERROR_DLA_ERR_ENGINE_TIMEOUT # backward-compat alias
1644+
ERROR_DLA_ERR_DATA_MISMATCH = cudlaErrorDlaErrDataMismatch
1645+
ErrorDlaErrDataMismatch = ERROR_DLA_ERR_DATA_MISMATCH # backward-compat alias
1646+
ERROR_UNKNOWN = cudlaErrorUnknown
1647+
ErrorUnknown = ERROR_UNKNOWN # backward-compat alias
16241648

16251649
class Mode(_cyb_IntEnum):
16261650
"""

‎cuda_bindings_13/cuda/bindings/driver.pyx‎

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
# SPDX-License-Identifier: Apache-2.0
33

44
# This code was automatically generated with version 13.4.1. Do not modify it directly.
5-
# CYTHON-BINDINGS-GENERATED-DO-NOT-MODIFY-THIS-FILE: format=1; content-sha256=348b02f0a76a3a271fbb11535f02d660d811d3c21a877e46bfc070bbabf43e76
5+
# CYTHON-BINDINGS-GENERATED-DO-NOT-MODIFY-THIS-FILE: format=1; content-sha256=8932ee959b6a2f1e69316f813cb8e8492c8e112094812dc1310c49970f00779a
66
from typing import Any, Optional
77
import cython
88
import ctypes
@@ -30899,7 +30899,7 @@ def cuDeviceRegisterAsyncNotification(device, callbackFunc, userData):
3089930899
if err != cydriver.CUDA_SUCCESS:
3090030900
free(cbData)
3090130901
else:
30902-
m_global._allocated[int(callback)] = cbData
30902+
m_global._insert(int(callback), cbData)
3090330903
_helper_input_void_ptr_free(&cyuserDataHelper)
3090430904
if err != cydriver.CUDA_SUCCESS:
3090530905
return (_CUresult(err), None)
@@ -30948,8 +30948,7 @@ def cuDeviceUnregisterAsyncNotification(device, callback):
3094830948
with nogil:
3094930949
err = cydriver.cuDeviceUnregisterAsyncNotification(cydevice, cycallback)
3095030950
if err == cydriver.CUDA_SUCCESS:
30951-
free(m_global._allocated[pcallback])
30952-
m_global._allocated.erase(<void_ptr>pcallback)
30951+
free(m_global._take(pcallback))
3095330952
return (_CUresult(err),)
3095430953

3095530954
@cython.embedsignature(True)
@@ -55743,7 +55742,7 @@ def cuLogsRegisterCallback(callbackFunc, userData):
5574355742
if err != cydriver.CUDA_SUCCESS:
5574455743
free(cbData)
5574555744
else:
55746-
m_global._allocated[int(callback_out)] = cbData
55745+
m_global._insert(int(callback_out), cbData)
5574755746
_helper_input_void_ptr_free(&cyuserDataHelper)
5574855747
if err != cydriver.CUDA_SUCCESS:
5574955748
return (_CUresult(err), None)
@@ -55774,8 +55773,7 @@ def cuLogsUnregisterCallback(callback):
5577455773
with nogil:
5577555774
err = cydriver.cuLogsUnregisterCallback(cycallback)
5577655775
if err == cydriver.CUDA_SUCCESS:
55777-
free(m_global._allocated[pcallback])
55778-
m_global._allocated.erase(<void_ptr>pcallback)
55776+
free(m_global._take(pcallback))
5577955777
return (_CUresult(err),)
5578055778

5578155779
@cython.embedsignature(True)
@@ -57375,6 +57373,19 @@ def cuGraphicsVDPAURegisterOutputSurface(vdpSurface, unsigned int flags):
5737557373

5737657374
cdef class cudaBindingsDriverGlobal:
5737757375
cdef map[void_ptr, void*] _allocated
57376+
cdef cython.pymutex _lock
57377+
57378+
cdef void _insert(self, void_ptr key, void* value) noexcept:
57379+
with self._lock:
57380+
self._allocated[key] = value
57381+
57382+
cdef void* _take(self, void_ptr key) noexcept:
57383+
cdef void* value = NULL
57384+
with self._lock:
57385+
if self._allocated.count(key) != 0:
57386+
value = self._allocated[key]
57387+
self._allocated.erase(key)
57388+
return value
5737857389

5737957390
def __dealloc__(self):
5738057391
for item in self._allocated:

‎cuda_bindings_13/cuda/bindings/runtime.pyx‎

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
# SPDX-License-Identifier: Apache-2.0
33

44
# This code was automatically generated with version 13.4.1. Do not modify it directly.
5-
# CYTHON-BINDINGS-GENERATED-DO-NOT-MODIFY-THIS-FILE: format=1; content-sha256=ea95eb12334cbd4c1bf3fc8e890fb6f9493063b12faea853bb3d8c6288934182
5+
# CYTHON-BINDINGS-GENERATED-DO-NOT-MODIFY-THIS-FILE: format=1; content-sha256=4cc5d08de16bc7cac781ba6e469ffe16b0d8e30beea5ec6f5e579f0fae24e834
66
from typing import Any, Optional
77
import cython
88
import ctypes
@@ -21228,7 +21228,7 @@ def cudaDeviceRegisterAsyncNotification(int device, callbackFunc, userData):
2122821228
if err != cyruntime.cudaSuccess:
2122921229
free(cbData)
2123021230
else:
21231-
m_global._allocated[int(callback)] = cbData
21231+
m_global._insert(int(callback), cbData)
2123221232
_helper_input_void_ptr_free(&cyuserDataHelper)
2123321233

2123421234
if err != cyruntime.cudaSuccess:
@@ -21270,8 +21270,7 @@ def cudaDeviceUnregisterAsyncNotification(int device, callback):
2127021270
with nogil:
2127121271
err = cyruntime.cudaDeviceUnregisterAsyncNotification(device, cycallback)
2127221272
if err == cyruntime.cudaSuccess:
21273-
free(m_global._allocated[pcallback])
21274-
m_global._allocated.erase(<void_ptr>pcallback)
21273+
free(m_global._take(pcallback))
2127521274
return (_cudaError_t(err),)
2127621275

2127721276
@cython.embedsignature(True)
@@ -40262,6 +40261,19 @@ def getLocalRuntimeVersion():
4026240261

4026340262
cdef class cudaBindingsRuntimeGlobal:
4026440263
cdef map[void_ptr, void*] _allocated
40264+
cdef cython.pymutex _lock
40265+
40266+
cdef void _insert(self, void_ptr key, void* value) noexcept:
40267+
with self._lock:
40268+
self._allocated[key] = value
40269+
40270+
cdef void* _take(self, void_ptr key) noexcept:
40271+
cdef void* value = NULL
40272+
with self._lock:
40273+
if self._allocated.count(key) != 0:
40274+
value = self._allocated[key]
40275+
self._allocated.erase(key)
40276+
return value
4026540277

4026640278
def __dealloc__(self):
4026740279
for item in self._allocated:

‎cuda_bindings_13/tests/cudla/test_cudla_bindings.py‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -197,8 +197,9 @@ def test_cudla_error_stores_status(self):
197197
assert err.status == int(cudla.Status.ErrorInvalidParam)
198198

199199
def test_cudla_error_str(self):
200+
assert cudla.Status.ErrorInvalidParam is cudla.Status.ERROR_INVALID_PARAM
200201
err = cudla.CudlaError(int(cudla.Status.ErrorInvalidParam))
201-
assert "ErrorInvalidParam" in str(err)
202+
assert "ERROR_INVALID_PARAM" in str(err)
202203

203204

204205
# ---------------------------------------------------------------------------
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
# SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
2+
# SPDX-License-Identifier: Apache-2.0
3+
4+
import threading
5+
6+
import pytest
7+
8+
from cuda.bindings import driver
9+
from cuda_python_test_helpers import driver_version_less_than
10+
11+
NUM_THREADS = 16
12+
NUM_ITERATIONS = 500
13+
14+
15+
@pytest.mark.agent_authored(model="claude-sonnet-5-5")
16+
@pytest.mark.skipif(
17+
driver_version_less_than(12090),
18+
reason="cuLogs* functions were introduced in CUDA 12.9",
19+
)
20+
@pytest.mark.thread_unsafe(reason="starts its own threads and needs them to overlap")
21+
def test_culogs_register_unregister_from_many_threads():
22+
(err,) = driver.cuInit(0)
23+
assert err == driver.CUresult.CUDA_SUCCESS
24+
25+
barrier = threading.Barrier(NUM_THREADS)
26+
failures = []
27+
28+
def worker():
29+
try:
30+
barrier.wait()
31+
for _ in range(NUM_ITERATIONS):
32+
err, handle = driver.cuLogsRegisterCallback(0, None)
33+
assert err == driver.CUresult.CUDA_SUCCESS
34+
(err,) = driver.cuLogsUnregisterCallback(handle)
35+
assert err == driver.CUresult.CUDA_SUCCESS
36+
except BaseException as e:
37+
failures.append(e)
38+
39+
threads = [threading.Thread(target=worker) for _ in range(NUM_THREADS)]
40+
for t in threads:
41+
t.start()
42+
for t in threads:
43+
t.join()
44+
45+
assert not failures, failures

‎cuda_bindings_13/tests/test_graphics_apis.py‎

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
gl_context_not_on_nvidia_gpu_reason,
1414
is_gl_context_unavailable,
1515
open_gl_window,
16+
select_headless_egl_device_for_cuda,
1617
tcc_skip_reason,
1718
)
1819

@@ -22,12 +23,20 @@
2223

2324

2425
def _configure_pyglet_headless():
25-
"""On headless Linux: enable EGL mode or skip if EGL is absent."""
26+
"""On headless Linux: enable EGL mode, matched to CUDA device 0, or skip if EGL is absent."""
2627
if sys.platform.startswith("linux") and not (os.environ.get("DISPLAY") or os.environ.get("WAYLAND_DISPLAY")):
2728
if ctypes.util.find_library("EGL") is None:
2829
pytest.skip("No DISPLAY and no EGL runtime available for headless context.")
2930
pyglet.options["headless"] = True
3031

32+
# CUDA_VISIBLE_DEVICES does not reorder EGL's device enumeration, so on
33+
# headless multi-GPU systems EGL device 0 may not be the physical GPU
34+
# behind CUDA device 0, which these tests register against. Pick the
35+
# EGL device that the driver reports as corresponding to it.
36+
egl_device = select_headless_egl_device_for_cuda(0)
37+
if egl_device is not None:
38+
pyglet.options["headless_device"] = egl_device
39+
3140

3241
def _allocate_gl_texture(win):
3342
"""Allocate a 2-D RGBA8 texture. Caller must have a current GL context.

0 commit comments

Comments
 (0)