Skip to content

Commit d826eb3

Browse files
committed
docs: clarify cuda.core concurrency and thread-safety policy
Document the concurrency contract that was previously agreed only in review threads: concurrent reads of a cuda.core object are supported, but concurrent mutation of the same object requires application-provided synchronization. Distinct objects can still collide through shared CUDA driver/context state (e.g. peer device access), which is also the caller's responsibility. - docs/source/concurrency.rst: new user-facing "Concurrency and Thread Safety" page, linked into the docs toctree. - cuda_core/AGENTS.md: contributor-facing invariants (reads-safe/mutation boundary, prefer immutable designs, shared-driver-state collisions, guarding internal cached state only for legitimately-shared objects, GIL-held entry points, and releasing the GIL before entering the driver from callback/__del__ paths).
1 parent 8b20f77 commit d826eb3

3 files changed

Lines changed: 68 additions & 1 deletion

File tree

cuda_core/AGENTS.md

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,44 @@ This file describes `cuda_core`, the high-level Pythonic CUDA subpackage in the
6363
- Prefer explicit error propagation over silent fallback paths.
6464
- If you change public behavior, update tests and docs under `docs/source/`.
6565

66+
## Concurrency and free-threading
67+
68+
`cuda.core` ships free-threaded (no-GIL) wheels and builds with
69+
`freethreading_compatible=True`. The user-facing policy lives in
70+
`docs/source/concurrency.rst`; the invariants below are for contributors. Reviewers
71+
and agents should flag violations.
72+
73+
- **Reads are safe; mutation is the boundary**: concurrent reads of an object are
74+
supported, but concurrent mutation of the same public object (e.g., building one
75+
graph from two threads, or `close()` racing another call) is the caller's
76+
responsibility -- do not add locks to make it safe. Prefer immutable designs to
77+
keep the mutable, thread-unsafe surface small. Protecting library-internal state
78+
*is* in scope.
79+
- **Distinct objects can still collide via shared driver state**: operating on
80+
separate objects is not automatically safe when they share driver or context
81+
state (e.g., changing peer device access while another thread touches affected
82+
memory). Synchronizing these cases is the caller's responsibility; do not try to
83+
lock around them internally.
84+
- **Protect internal cached/module-level state**: guard lazily-populated
85+
`cdef object` caches and module-level state so concurrent access cannot corrupt
86+
interpreter state (CPython reference counts -- a strictly free-threading hazard).
87+
Established patterns are `@cython.critical_section` on accessors (#2215), an
88+
atomic initialization flag (#2216), and `dict.setdefault` for identity caches
89+
(#2217). Guard state only on objects that are legitimately shared between threads;
90+
objects that are not meant to be shared (e.g., the thread-local `Device`) do not
91+
need such guards (see #2321). Reference-count integrity is guaranteed; cache
92+
value-identity/idempotency is not.
93+
- **Entry points assume the GIL is held**: the helpers in `_cpp/resource_handles.*`
94+
are called from Cython with the GIL held and do not re-acquire it. Driver and
95+
destructor callbacks run at arbitrary times, so they take the GIL (`with gil`)
96+
and probe for interpreter shutdown before touching Python objects.
97+
- **Lock ordering -- release the GIL before entering the driver**: any CUDA work
98+
reachable from a host callback or a retained object's `__del__` must release the
99+
GIL before calling the driver, to avoid GIL/driver-lock deadlocks (see the
100+
`_py_host_trampoline` path and numba-cuda#321). Objects retained into a graph
101+
(kernel arguments, memcpy/memset operands, `dst_owner`/`src_owner`, and
102+
host-callback closures) inherit this contract.
103+
66104
## API design guidelines
67105

68106
These are some API design guidelines we try to follow when adding new APIs to
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
.. SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
2+
.. SPDX-License-Identifier: Apache-2.0
3+
4+
.. currentmodule:: cuda.core
5+
6+
Concurrency and Thread Safety
7+
=============================
8+
9+
``cuda.core`` allows concurrent reads of its objects from multiple host
10+
threads, but concurrent *mutation* of the same object is **not supported** --
11+
for example, adding nodes to the same graph, or closing a resource while
12+
another thread is using it. Whenever an object is shared across threads and at
13+
least one of them may mutate it, the application is responsible for providing
14+
external synchronization.
15+
16+
The library does protect the integrity of its own internal state (such as
17+
cached attributes and reference counting), so that concurrent reads of the same
18+
object, or any kind of concurrent use of *distinct* objects, cannot corrupt the
19+
interpreter. This is an integrity guarantee only: the ordering and outcome of
20+
concurrent operations on a shared object are otherwise undefined.
21+
22+
Additional limitations apply because ``cuda.core`` inherits the concurrency
23+
constraints of the underlying CUDA driver. Distinct ``cuda.core`` objects can
24+
share driver or context state, so operating on separate objects is not always
25+
safe. For example, modifying peer device access from one thread while another
26+
thread accesses device memory affected by that change is unsafe, even though the
27+
two threads use different objects. The application is responsible for
28+
synchronizing operations that concurrently read and modify shared driver state.

cuda_core/docs/source/index.rst

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
.. SPDX-FileCopyrightText: Copyright (c) 2024-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
1+
.. SPDX-FileCopyrightText: Copyright (c) 2024-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
22
.. SPDX-License-Identifier: Apache-2.0
33
44
``cuda.core``: Pythonic access to CUDA core functionality
@@ -14,6 +14,7 @@ Welcome to the documentation for ``cuda.core``.
1414
install
1515
examples
1616
interoperability
17+
concurrency
1718
api
1819
api_nvml
1920
environment_variables

0 commit comments

Comments
 (0)