PEP 703: --disable-gil and other small changes (#2979)
* Rename `--without-gil` to `--disable-gil`. Suggested by Inada Naoki. * Add two sections to "Rejected Ideas": - Why Not Deprecate ``PyDict_GetItem`` in Favor of ``PyDict_FetchItem``? - Why Not Use PEP 683 Immortalization? * Expand on Python build modes
This commit is contained in:
parent
b4de31296d
commit
d9503c0be9
96
pep-0703.rst
96
pep-0703.rst
|
@ -8,7 +8,7 @@ Type: Standards Track
|
||||||
Content-Type: text/x-rst
|
Content-Type: text/x-rst
|
||||||
Created: 09-Jan-2023
|
Created: 09-Jan-2023
|
||||||
Python-Version: 3.12
|
Python-Version: 3.12
|
||||||
Post-History: 09-Jan-2023
|
Post-History: `09-Jan-2023 <https://discuss.python.org/t/22606>`__
|
||||||
Resolution:
|
Resolution:
|
||||||
|
|
||||||
|
|
||||||
|
@ -18,7 +18,7 @@ Abstract
|
||||||
CPython's global interpreter lock ("GIL") prevents multiple threads
|
CPython's global interpreter lock ("GIL") prevents multiple threads
|
||||||
from executing Python code at the same time. The GIL is an obstacle
|
from executing Python code at the same time. The GIL is an obstacle
|
||||||
to using multi-core CPUs from Python efficiently. This PEP proposes
|
to using multi-core CPUs from Python efficiently. This PEP proposes
|
||||||
adding a build configuration (``--without-gil``) to CPython to let it
|
adding a build configuration (``--disable-gil``) to CPython to let it
|
||||||
run Python code without the global interpreter lock and with the
|
run Python code without the global interpreter lock and with the
|
||||||
necessary changes needed to make the interpreter thread-safe.
|
necessary changes needed to make the interpreter thread-safe.
|
||||||
|
|
||||||
|
@ -326,10 +326,10 @@ Build Configuration Changes
|
||||||
|
|
||||||
The global interpreter lock will remain the default for CPython builds
|
The global interpreter lock will remain the default for CPython builds
|
||||||
and python.org downloads. A new build configuration flag,
|
and python.org downloads. A new build configuration flag,
|
||||||
``--without-gil`` will be added to the configure script that will
|
``--disable-gil`` will be added to the configure script that will
|
||||||
build CPython without the global interpreter lock.
|
build CPython without the global interpreter lock.
|
||||||
|
|
||||||
When built with ``--without-gil``, CPython will define the
|
When built with ``--disable-gil``, CPython will define the
|
||||||
``Py_NOGIL`` macro in Python/patchlevel.h. The ABI tag will include
|
``Py_NOGIL`` macro in Python/patchlevel.h. The ABI tag will include
|
||||||
the letter "n" (for "nogil").
|
the letter "n" (for "nogil").
|
||||||
|
|
||||||
|
@ -647,7 +647,7 @@ CPython Free Lists
|
||||||
CPython makes use of free lists to speed up the allocation of small,
|
CPython makes use of free lists to speed up the allocation of small,
|
||||||
frequently allocated objects like tuples and numbers. These free
|
frequently allocated objects like tuples and numbers. These free
|
||||||
lists are not thread-safe and will need to be disabled when building
|
lists are not thread-safe and will need to be disabled when building
|
||||||
Python in the ``--without-gil`` mode.
|
Python in the ``--disable-gil`` mode.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -1280,7 +1280,7 @@ Backwards Compatibility
|
||||||
=======================
|
=======================
|
||||||
|
|
||||||
This PEP poses a number of backwards compatibility issues when
|
This PEP poses a number of backwards compatibility issues when
|
||||||
building CPython with the ``--without-gil`` flag, but those issues do
|
building CPython with the ``--disable-gil`` flag, but those issues do
|
||||||
not occur when using the default build configuration. Nearly all the
|
not occur when using the default build configuration. Nearly all the
|
||||||
backwards compatibility concerns involve the C-API:
|
backwards compatibility concerns involve the C-API:
|
||||||
|
|
||||||
|
@ -1332,14 +1332,14 @@ Distribution
|
||||||
This PEP poses new challenges for distributing Python. At least for
|
This PEP poses new challenges for distributing Python. At least for
|
||||||
some time, there will be two versions of Python requiring separately
|
some time, there will be two versions of Python requiring separately
|
||||||
compiled C-API extensions. It may take some time for C-API extension
|
compiled C-API extensions. It may take some time for C-API extension
|
||||||
authors to build ``--without-gil`` compatible packages and upload
|
authors to build ``--disable-gil`` compatible packages and upload
|
||||||
them to PyPI. Additionally, some authors may be hesitant to support
|
them to PyPI. Additionally, some authors may be hesitant to support
|
||||||
the ``--without-gil`` mode until it has wide adoption, but adoption
|
the ``--disable-gil`` mode until it has wide adoption, but adoption
|
||||||
will likely depend on the availability of Python's rich set of
|
will likely depend on the availability of Python's rich set of
|
||||||
extensions.
|
extensions.
|
||||||
|
|
||||||
To mitigate this, the author will work with Anaconda to distribute
|
To mitigate this, the author will work with Anaconda to distribute
|
||||||
a ``--without-gil`` version of Python together with compatible
|
a ``--disable-gil`` version of Python together with compatible
|
||||||
packages from conda channels. This centralizes the challenges of
|
packages from conda channels. This centralizes the challenges of
|
||||||
building extensions, and the author believes this will enable more
|
building extensions, and the author believes this will enable more
|
||||||
people to use Python without the GIL sooner than they would otherwise
|
people to use Python without the GIL sooner than they would otherwise
|
||||||
|
@ -1370,7 +1370,7 @@ The other changes with significant performance impact are:
|
||||||
How to Teach This
|
How to Teach This
|
||||||
=================
|
=================
|
||||||
|
|
||||||
As part of implementing the ``--without-gil`` mode, the author will
|
As part of implementing the ``--disable-gil`` mode, the author will
|
||||||
write a "HOWTO" guide [#howto]_ for making packages compatible when
|
write a "HOWTO" guide [#howto]_ for making packages compatible when
|
||||||
running Python without the GIL.
|
running Python without the GIL.
|
||||||
|
|
||||||
|
@ -1531,6 +1531,52 @@ author is not aware of a way to add write barriers to CPython without
|
||||||
substantially breaking the C-API.
|
substantially breaking the C-API.
|
||||||
|
|
||||||
|
|
||||||
|
Why Not Deprecate ``PyDict_GetItem`` in Favor of ``PyDict_FetchItem``?
|
||||||
|
----------------------------------------------------------------------
|
||||||
|
|
||||||
|
This PEP proposes a new API ``PyDict_FetchItem`` which behaves like
|
||||||
|
``PyDict_GetItem``, but returns a new reference instead of a borrowed
|
||||||
|
reference. As described in `Borrowed References`_, some uses of
|
||||||
|
borrowed references that were safe when running with the GIL are
|
||||||
|
unsafe when running without the GIL and need to be replaced by
|
||||||
|
functions like ``PyDict_FetchItem`` that return new references.
|
||||||
|
|
||||||
|
This PEP does *not* propose deprecating ``PyDict_GetItem`` and similar
|
||||||
|
functions that return borrowed references for a few reasons:
|
||||||
|
|
||||||
|
* Many of the uses of borrowed references are safe, even when running
|
||||||
|
without the GIL. For example, C API functions often use
|
||||||
|
``PyDict_GetItem`` to retrieve items from the keyword
|
||||||
|
argument dictionary. These calls are safe because the keyword
|
||||||
|
argument dictionary is only visible to a single thread.
|
||||||
|
* I tried this approach early on and found that wholesale replacing of
|
||||||
|
``PyDict_GetItem`` with ``PyDict_FetchItem`` frequently introduced
|
||||||
|
new reference counting bugs. In my opinion, the risk of
|
||||||
|
introducing new reference counting bugs generally outweighs the
|
||||||
|
risks of missing a ``PyDict_GetItem`` call that is unsafe without
|
||||||
|
the GIL.
|
||||||
|
|
||||||
|
|
||||||
|
Why Not Use PEP 683 Immortalization?
|
||||||
|
------------------------------------
|
||||||
|
|
||||||
|
Like :pep:`683`, this PEP proposes an immortalization scheme for
|
||||||
|
Python objects, but the PEPs use different bit representations to
|
||||||
|
mark immortal objects. The schemes cannot be identical because this
|
||||||
|
PEP depends on biased reference counting, which has two reference
|
||||||
|
count fields instead of one. The schemes could be made more
|
||||||
|
superficially similar, but it is not clear that would be worthwhile.
|
||||||
|
PEP 683 maintains compatibility with extensions compiled to the
|
||||||
|
stable ABI, and therefore uses the second most significant bit
|
||||||
|
(i.e., 2^62 on 64-bit platforms) to mark immortal objects. Checking
|
||||||
|
that bit typically requires an extra instruction on x86-64 compared
|
||||||
|
with checking the sign bit or one of the low 32 bits. This PEP
|
||||||
|
cannot maintain compatibility with extensions compiled to the stable
|
||||||
|
ABI because of the use of two reference count fields, and so this PEP
|
||||||
|
is free to propose a representation that allows slightly more
|
||||||
|
efficient checks for immortality on x86-64.
|
||||||
|
|
||||||
|
|
||||||
Open Issues
|
Open Issues
|
||||||
===========
|
===========
|
||||||
|
|
||||||
|
@ -1548,23 +1594,39 @@ manner.
|
||||||
Python Build Modes
|
Python Build Modes
|
||||||
------------------
|
------------------
|
||||||
|
|
||||||
This PEP introduces a new build mode (``--without-gil``) that is not
|
This PEP introduces a new build mode (``--disable-gil``) that is not
|
||||||
ABI compatible with the standard build mode. The additional build
|
ABI compatible with the standard build mode. The additional build
|
||||||
mode adds complexity for both Python core developers and extension
|
mode adds complexity for both Python core developers and extension
|
||||||
developers. The author believes a worthwhile long-term goal is to
|
developers. The author believes a worthwhile goal is to combine
|
||||||
combine these build modes and have the global interpreter lock
|
these build modes and have the global interpreter lock controlled at
|
||||||
controlled at runtime, possibly disabled by default. The path to
|
runtime, possibly disabled by default. The path to this goal remains
|
||||||
this goal remains an open issue.
|
an open issue, but a possible path might look like the following:
|
||||||
|
|
||||||
|
#. In 2024, CPython 3.13 is released with support for a
|
||||||
|
``--disable-gil`` build time flag. There are two ABIs for
|
||||||
|
CPython, one with the GIL and one without. Extension authors
|
||||||
|
target both ABIs.
|
||||||
|
#. After 2--3 releases, (i.e., in 2026--2027), CPython is released
|
||||||
|
with with the GIL controlled by a runtime environment variable or
|
||||||
|
flag. The GIL is enabled by default. There is only a single ABI.
|
||||||
|
#. After another 2--3 release (i.e., 2028--2030), CPython switches to
|
||||||
|
the GIL being disabled by default. The GIL can still be enabled
|
||||||
|
at runtime via an environment variable or command line flag.
|
||||||
|
|
||||||
|
This PEP covers the first step, with the remaining steps left as open
|
||||||
|
issues. In this scenario, there would be a two to three year period
|
||||||
|
where extension authors would target an extra CPython build per
|
||||||
|
supported CPU architecture and OS.
|
||||||
|
|
||||||
|
|
||||||
Mitigations for Single-Threaded Performance
|
Mitigations for Single-Threaded Performance
|
||||||
-------------------------------------------
|
-------------------------------------------
|
||||||
|
|
||||||
The changes proposed in the PEP will increase execution overhead for
|
The changes proposed in the PEP will increase execution overhead for
|
||||||
``--without-gil`` builds compared to Python builds with the GIL. In
|
``--disable-gil`` builds compared to Python builds with the GIL. In
|
||||||
other words, it will have slower single-threaded performance. There
|
other words, it will have slower single-threaded performance. There
|
||||||
are some possible optimizations to reduce execution overhead,
|
are some possible optimizations to reduce execution overhead,
|
||||||
especially for ``--without-gil`` builds that only use a single
|
especially for ``--disable-gil`` builds that only use a single
|
||||||
thread. These may be worthwhile if a longer term goal is to have a
|
thread. These may be worthwhile if a longer term goal is to have a
|
||||||
single build mode, but the choice of optimizations and their
|
single build mode, but the choice of optimizations and their
|
||||||
trade-offs remain an open issue.
|
trade-offs remain an open issue.
|
||||||
|
|
Loading…
Reference in New Issue