Thread Safety#
NumPy supports use in a multithreaded context via thethreading module in thestandard library. Many NumPy operations release theGIL, so unlike manysituations in Python, it is possible to improve parallel performance byexploiting multithreaded parallelism in Python.
The easiest performance gains happen when each worker thread owns its own arrayor set of array objects, with no data directly shared between threads. BecauseNumPy releases the GIL for many low-level operations, threads that spend most ofthe time in low-level code will run in parallel.
It is possible to share NumPy arrays between threads, but extreme care must betaken to avoid creating thread safety issues when mutating arrays that areshared between multiple threads. If two threads simultaneously read from andwrite to the same array, they will at best produce inconsistent, racey results thatare not reproducible, let alone correct. It is also possible to crash the Pythoninterpreter by, for example, resizing an array while another thread is readingfrom it to compute a ufunc operation.
In the future, we may add locking tondarray to make writing multithreadedalgorithms using NumPy arrays safer, but for now we suggest focusing onread-only access of arrays that are shared between threads, or adding your ownlocking if you need to mutation and multithreading.
Note that operations thatdo not release the GIL will see no performance gainsfrom use of thethreading module, and instead might be better served withmultiprocessing. In particular, operations on arrays withdtype=np.object_do not release the GIL.
Context-local state#
NumPy maintains some state for ufuncs context-local basis, which means eachthread in a multithreaded program or task in an asyncio program has its ownindependent configuration of thenumpy.errstate (seeFloating point error handling), and ofText formatting options.
You can update state stored in a context variable by entering a context manager.As soon as the context manager exits, the state will be reset to its valuebefore entering the context manager.
Free-threaded Python#
New in version 2.1.
Starting with NumPy 2.1 and CPython 3.13, NumPy also has experimental supportfor python runtimes with the GIL disabled. Seehttps://py-free-threading.github.io for more information about installing andusingfree-threaded Python, as well asinformation about supporting it in libraries that depend on NumPy.
Because free-threaded Python does not have aglobal interpreter lock to serialize access to Python objects, there are moreopportunities for threads to mutate shared state and create thread safetyissues. In addition to the limitations about locking of thendarray object noted above, this also means that arrays withdtype=np.object_ are not protected by the GIL, creating data races for pythonobjects that are not possible outside free-threaded python.
C-API Threading Support#
For developers writing C extensions that interact with NumPy, several parts oftheC-API array documentation provide detailedinformation about multithreading considerations.
See Also#
Multithreaded generation - Practical example of using NumPy’srandom number generators in a multithreaded context with
concurrent.futures.