Skip to content

Commit

Permalink
pythongh-124370: Add "howto" for free-threaded Python
Browse files Browse the repository at this point in the history
This is a guide aimed at people writing Python code, as oppposed to the
existing guide for C API extension authors.
  • Loading branch information
colesbury committed Sep 23, 2024
1 parent d9d5b3d commit 5b4a8aa
Show file tree
Hide file tree
Showing 3 changed files with 122 additions and 0 deletions.
119 changes: 119 additions & 0 deletions Doc/howto/free-threading-python.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
.. _freethreading-python-howto:

*********************************
Python Support for Free Threading
*********************************

Starting with the 3.13 release, CPython has experimental support for running
with the :term:`global interpreter lock` (GIL) disabled in a configuration
called :term:`free threading`. This document describes the implications of
free threading for Python code. See :ref:`freethreading-extensions-howto` for
information on how to write C extensions that support the free-threaded build.


Installation
============

Starting with Python 3.13.0b2, the offical macOS and Windows installers
optionally support installing free-threaded Python binaries. The installers
are available at https://www.python.org/downloads/.

.. seealso::

`Installing a Free-Threaded Python
<https://py-free-threading.github.io/installing_cpython/>`_:
A community-maintained installation guide for installing free-threaded
Python.


Identifying Free-Threaded Python
================================

The free-threaded build of CPython can optionally run with the global
interpreter lock enabled, such as when :envvar:`PYTHON_GIL` is set to ``1``,
or when importing an extension module that requires the GIL.

The :func:`sys._is_gil_enabled` function will return ``False`` if the global
interpreter lock is currently disabled. This is the recommended mechanism for
decisions like whether to use multithreading or multiprocessing.

The ``sysconfig.get_config_var("Py_GIL_DISABLED")`` configuration variable can
be used to determine whether the build supports free threading. If the variable
is set to ``1``, then the build supports free threading. This is the recommended
mechanism for decisions related to the build configuration.


Thread Safety
=============

The free-threaded build of CPython aims to provide similar thread-safety
behavior at the Python level to the GIL-enabled build. Built-in
types like :class:`dict`, :class:`list`, and :class:`set` use internal locks
to protect against concurrent modifications in ways that behave similarly to
the GIL. However, Python has not historically guaranteed specific behavior for
concurrent modifications to these built-in types, so this should be treated
as a description of the current implementation, not a guarantee of future
behavior.

.. note::

It's recommended to use the :class:`threading.Lock` or other synchronization
primitives instead of relying on the internal locks of built-in types, when
possible.



Known Limitations
=================

This section describes known limitations of the free-threaded CPython build.

Immortalization
---------------

The free-threaded build of the 3.13 release makes some objects :term:`immortal`
in order to avoid reference count contention that would prevent efficient
multi-threaded scaling. This means that these objects are never deallocated.
This expected to be addressed in the upcoming 3.14 release with
`deferred reference counting <https://peps.python.org/pep-0703/#deferred-reference-counting>`_.

The objects that are immortalized are:

* :ref:`function <user-defined-funcs>` objects declared at the module level
* :ref:`method <instance-methods>` descriptors
* :ref:`code <code-objects>` objects
* :term:`module` objects and their dictionaries
* :ref:`classes <classes>` (type objects)

The immortalization of these objects happens the first time a thread is started
after the main thread.

Additionally, numeric and string literals in the code as well as strings
returned by :func:`sys.intern` are also interned. This behavior is expected to
remainin the 3.14 free-threaded build.


Frame Objects
-------------

It is not safe to access :ref:`frame <frame-objects>` objects from other
threads. This means that :func:`sys._current_frames` is generally not safe to
use in a free-threaded build.

Iterators
---------

Sharing the same iterator object between multiple threads is generally not
safe and threads may see duplicate or missing elements when iterating or crash
the interpreter.


Single-Threaded Performance
---------------------------

The free-threaded build has additional overhead when executing Python code
compared to the default GIL-enabled build. In 3.13, this overhead is about
40% on the `pyperformance <https://pyperformance.readthedocs.io/>`_ suite.
Programs that spend most of the their time in C extensions or I/O will see
less of an impact. This overhead is expected to be reduced in the upcoming
3.14 release.
2 changes: 2 additions & 0 deletions Doc/howto/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ Python Library Reference.
isolating-extensions.rst
timerfd.rst
mro.rst
free-threading-python.rst
free-threading-extensions.rst

General:
Expand All @@ -52,6 +53,7 @@ General:
Advanced development:

* :ref:`curses-howto`
* :ref:`freethreading-python-howto`
* :ref:`freethreading-extensions-howto`
* :ref:`isolating-extensions-howto`
* :ref:`python_2.3_mro`
Expand Down
1 change: 1 addition & 0 deletions Doc/reference/datamodel.rst
Original file line number Diff line number Diff line change
Expand Up @@ -846,6 +846,7 @@ this case, the special read-only attribute :attr:`!__self__` is set to the objec
denoted by *alist*. (The attribute has the same semantics as it does with
:attr:`other instance methods <method.__self__>`.)

.. _classes:

Classes
^^^^^^^
Expand Down

0 comments on commit 5b4a8aa

Please sign in to comment.