Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions doc/neps/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,10 +39,10 @@
templates_path = ['../source/_templates/']

# The suffix(es) of source filenames.
# You can specify multiple suffix as a list of string:
# You can specify multiple suffix as a dict mapping suffixes to parsers:
#
# source_suffix = ['.rst', '.md']
source_suffix = '.rst'
# source_suffix = {'.rst': 'restructuredtext', '.md': 'markdown'}
source_suffix = {'.rst': 'restructuredtext'}

# The master toctree document.
master_doc = 'content'
Expand Down
2 changes: 1 addition & 1 deletion doc/source/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ class PyTypeObject(ctypes.Structure):
templates_path = ['_templates']

# The suffix of source filenames.
source_suffix = '.rst'
source_suffix = {'.rst': 'restructuredtext'}

# General substitutions.
project = 'NumPy'
Expand Down
2 changes: 2 additions & 0 deletions doc/source/reference/c-api/array.rst
Original file line number Diff line number Diff line change
Expand Up @@ -4272,6 +4272,8 @@ Memory management

Returns 0 if nothing was done, -1 on error, and 1 if action was taken.

.. _array.ndarray.capi.threading:

Threading support
~~~~~~~~~~~~~~~~~

Expand Down
3 changes: 3 additions & 0 deletions doc/source/reference/random/multithreading.rst
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@ well-behaved (writable and aligned). Under normal circumstances, arrays
created using the common constructors such as :meth:`numpy.empty` will satisfy
these requirements.

.. seealso::
:ref:`thread_safety` for general information about thread safety in NumPy.

This example makes use of :mod:`concurrent.futures` to fill an array using
multiple threads. Threads are long-lived so that repeated calls do not
require any additional overheads from thread creation.
Expand Down
72 changes: 72 additions & 0 deletions doc/source/reference/routines.err.rst
Original file line number Diff line number Diff line change
@@ -1,8 +1,80 @@
.. _fp_error_handling:

Floating point error handling
=============================

.. currentmodule:: numpy

Error handling settings are stored in :py:mod:`python:contextvars`
allowing different threads or async tasks to have independent configurations.
For more information, see :ref:`thread_safety`.

.. _misc-error-handling:

How numpy handles numerical exceptions
--------------------------------------

The default is to ``'warn'`` for ``invalid``, ``divide``, and ``overflow``
and ``'ignore'`` for ``underflow``. But this can be changed, and it can be
set individually for different kinds of exceptions. The different behaviors
are:

- ``'ignore'`` : Take no action when the exception occurs.
- ``'warn'`` : Print a :py:exc:`RuntimeWarning` (via the Python :py:mod:`warnings` module).
- ``'raise'`` : Raise a :py:exc:`FloatingPointError`.
- ``'call'`` : Call a specified function.
- ``'print'`` : Print a warning directly to ``stdout``.
- ``'log'`` : Record error in a Log object.

These behaviors can be set for all kinds of errors or specific ones:

- ``all`` : apply to all numeric exceptions
- ``invalid`` : when NaNs are generated
- ``divide`` : divide by zero (for integers as well!)
- ``overflow`` : floating point overflows
- ``underflow`` : floating point underflows

Note that integer divide-by-zero is handled by the same machinery.

The error handling mode can be configured :func:`numpy.errstate`
context manager.

Examples
--------

::

>>> with np.errstate(all='warn'):
... np.zeros(5, dtype=np.float32) / 0.0
<python-input-1>:2: RuntimeWarning: invalid value encountered in divide
array([nan, nan, nan, nan, nan], dtype=float32)

::

>>> with np.errstate(under='ignore'):
... np.array([1.e-100])**10
array([0.])

::

>>> with np.errstate(invalid='raise'):
... np.sqrt(np.array([-1.]))
...
Traceback (most recent call last):
File "<python-input-1>", line 2, in <module>
np.sqrt(np.array([-1.]))
~~~~~~~^^^^^^^^^^^^^^^^^
FloatingPointError: invalid value encountered in sqrt

::

>>> def errorhandler(errstr, errflag):
... print("saw stupid error!")
>>> with np.errstate(call=errorhandler, all='call'):
... np.zeros(5, dtype=np.int32) / 0
saw stupid error!
array([nan, nan, nan, nan, nan])

Setting and getting error handling
----------------------------------

Expand Down
7 changes: 7 additions & 0 deletions doc/source/reference/routines.io.rst
Original file line number Diff line number Diff line change
Expand Up @@ -59,8 +59,15 @@ Memory mapping files
memmap
lib.format.open_memmap

.. _text_formatting_options:

Text formatting options
-----------------------

Text formatting settings are maintained in a :py:mod:`context variable <python:contextvars>`,
allowing different threads or async tasks to have independent configurations.
For more information, see :ref:`thread_safety`.

.. autosummary::
:toctree: generated/

Expand Down
49 changes: 38 additions & 11 deletions doc/source/reference/thread_safety.rst
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ Thread Safety
*************

NumPy supports use in a multithreaded context via the `threading` module in the
standard library. Many NumPy operations release the GIL, so unlike many
standard library. Many NumPy operations release the :term:`python:GIL`, so unlike many
situations in Python, it is possible to improve parallel performance by
exploiting multithreaded parallelism in Python.

Expand All @@ -22,7 +22,7 @@ are not reproducible, let alone correct. It is also possible to crash the Python
interpreter by, for example, resizing an array while another thread is reading
from it to compute a ufunc operation.

In the future, we may add locking to ndarray to make writing multithreaded
In the future, we may add locking to :class:`~numpy.ndarray` to make writing multithreaded
algorithms using NumPy arrays safer, but for now we suggest focusing on
read-only access of arrays that are shared between threads, or adding your own
locking if you need to mutation and multithreading.
Expand All @@ -32,6 +32,18 @@ from use of the `threading` module, and instead might be better served with
`multiprocessing`. In particular, operations on arrays with ``dtype=np.object_``
do not release the GIL.

Context-local state
-------------------

NumPy maintains some state for ufuncs context-local basis, which means each
thread in a multithreaded program or task in an asyncio program has its own
independent configuration of the `numpy.errstate` (see
:doc:`/reference/routines.err`), and of :ref:`text_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 value
before entering the context manager.

Free-threaded Python
--------------------

Expand All @@ -40,12 +52,27 @@ Free-threaded Python
Starting with NumPy 2.1 and CPython 3.13, NumPy also has experimental support
for python runtimes with the GIL disabled. See
https://py-free-threading.github.io for more information about installing and
using free-threaded Python, as well as information about supporting it in
libraries that depend on NumPy.

Because free-threaded Python does not have a global interpreter lock to
serialize access to Python objects, there are more opportunities for threads to
mutate shared state and create thread safety issues. In addition to the
limitations about locking of the ndarray object noted above, this also means
that arrays with ``dtype=np.object_`` are not protected by the GIL, creating data
races for python objects that are not possible outside free-threaded python.
using :py:term:`free-threaded <python:free threading>` Python, as well as
information about supporting it in libraries that depend on NumPy.

Because free-threaded Python does not have a
global interpreter lock to serialize access to Python objects, there are more
opportunities for threads to mutate shared state and create thread safety
issues. In addition to the limitations about locking of the
:class:`~numpy.ndarray` object noted above, this also means that arrays with
``dtype=np.object_`` are not protected by the GIL, creating data races for python
objects that are not possible outside free-threaded python.

C-API Threading Support
-----------------------

For developers writing C extensions that interact with NumPy, several parts of
the :doc:`C-API array documentation </reference/c-api/array>` provide detailed
information about multithreading considerations.

See Also
--------

* :doc:`/reference/random/multithreading` - Practical example of using NumPy's
random number generators in a multithreaded context with
:mod:`concurrent.futures`.
Loading