Skip to content

Commit d9503c0

Browse files
authored
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
1 parent b4de312 commit d9503c0

1 file changed

Lines changed: 79 additions & 17 deletions

File tree

pep-0703.rst

Lines changed: 79 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ Type: Standards Track
88
Content-Type: text/x-rst
99
Created: 09-Jan-2023
1010
Python-Version: 3.12
11-
Post-History: 09-Jan-2023
11+
Post-History: `09-Jan-2023 <https://discuss.python.org/t/22606>`__
1212
Resolution:
1313

1414

@@ -18,7 +18,7 @@ Abstract
1818
CPython's global interpreter lock ("GIL") prevents multiple threads
1919
from executing Python code at the same time. The GIL is an obstacle
2020
to using multi-core CPUs from Python efficiently. This PEP proposes
21-
adding a build configuration (``--without-gil``) to CPython to let it
21+
adding a build configuration (``--disable-gil``) to CPython to let it
2222
run Python code without the global interpreter lock and with the
2323
necessary changes needed to make the interpreter thread-safe.
2424

@@ -326,10 +326,10 @@ Build Configuration Changes
326326

327327
The global interpreter lock will remain the default for CPython builds
328328
and python.org downloads. A new build configuration flag,
329-
``--without-gil`` will be added to the configure script that will
329+
``--disable-gil`` will be added to the configure script that will
330330
build CPython without the global interpreter lock.
331331

332-
When built with ``--without-gil``, CPython will define the
332+
When built with ``--disable-gil``, CPython will define the
333333
``Py_NOGIL`` macro in Python/patchlevel.h. The ABI tag will include
334334
the letter "n" (for "nogil").
335335

@@ -647,7 +647,7 @@ CPython Free Lists
647647
CPython makes use of free lists to speed up the allocation of small,
648648
frequently allocated objects like tuples and numbers. These free
649649
lists are not thread-safe and will need to be disabled when building
650-
Python in the ``--without-gil`` mode.
650+
Python in the ``--disable-gil`` mode.
651651

652652

653653

@@ -1280,7 +1280,7 @@ Backwards Compatibility
12801280
=======================
12811281

12821282
This PEP poses a number of backwards compatibility issues when
1283-
building CPython with the ``--without-gil`` flag, but those issues do
1283+
building CPython with the ``--disable-gil`` flag, but those issues do
12841284
not occur when using the default build configuration. Nearly all the
12851285
backwards compatibility concerns involve the C-API:
12861286

@@ -1332,14 +1332,14 @@ Distribution
13321332
This PEP poses new challenges for distributing Python. At least for
13331333
some time, there will be two versions of Python requiring separately
13341334
compiled C-API extensions. It may take some time for C-API extension
1335-
authors to build ``--without-gil`` compatible packages and upload
1335+
authors to build ``--disable-gil`` compatible packages and upload
13361336
them to PyPI. Additionally, some authors may be hesitant to support
1337-
the ``--without-gil`` mode until it has wide adoption, but adoption
1337+
the ``--disable-gil`` mode until it has wide adoption, but adoption
13381338
will likely depend on the availability of Python's rich set of
13391339
extensions.
13401340

13411341
To mitigate this, the author will work with Anaconda to distribute
1342-
a ``--without-gil`` version of Python together with compatible
1342+
a ``--disable-gil`` version of Python together with compatible
13431343
packages from conda channels. This centralizes the challenges of
13441344
building extensions, and the author believes this will enable more
13451345
people to use Python without the GIL sooner than they would otherwise
@@ -1370,7 +1370,7 @@ The other changes with significant performance impact are:
13701370
How to Teach This
13711371
=================
13721372

1373-
As part of implementing the ``--without-gil`` mode, the author will
1373+
As part of implementing the ``--disable-gil`` mode, the author will
13741374
write a "HOWTO" guide [#howto]_ for making packages compatible when
13751375
running Python without the GIL.
13761376

@@ -1531,6 +1531,52 @@ author is not aware of a way to add write barriers to CPython without
15311531
substantially breaking the C-API.
15321532

15331533

1534+
Why Not Deprecate ``PyDict_GetItem`` in Favor of ``PyDict_FetchItem``?
1535+
----------------------------------------------------------------------
1536+
1537+
This PEP proposes a new API ``PyDict_FetchItem`` which behaves like
1538+
``PyDict_GetItem``, but returns a new reference instead of a borrowed
1539+
reference. As described in `Borrowed References`_, some uses of
1540+
borrowed references that were safe when running with the GIL are
1541+
unsafe when running without the GIL and need to be replaced by
1542+
functions like ``PyDict_FetchItem`` that return new references.
1543+
1544+
This PEP does *not* propose deprecating ``PyDict_GetItem`` and similar
1545+
functions that return borrowed references for a few reasons:
1546+
1547+
* Many of the uses of borrowed references are safe, even when running
1548+
without the GIL. For example, C API functions often use
1549+
``PyDict_GetItem`` to retrieve items from the keyword
1550+
argument dictionary. These calls are safe because the keyword
1551+
argument dictionary is only visible to a single thread.
1552+
* I tried this approach early on and found that wholesale replacing of
1553+
``PyDict_GetItem`` with ``PyDict_FetchItem`` frequently introduced
1554+
new reference counting bugs. In my opinion, the risk of
1555+
introducing new reference counting bugs generally outweighs the
1556+
risks of missing a ``PyDict_GetItem`` call that is unsafe without
1557+
the GIL.
1558+
1559+
1560+
Why Not Use PEP 683 Immortalization?
1561+
------------------------------------
1562+
1563+
Like :pep:`683`, this PEP proposes an immortalization scheme for
1564+
Python objects, but the PEPs use different bit representations to
1565+
mark immortal objects. The schemes cannot be identical because this
1566+
PEP depends on biased reference counting, which has two reference
1567+
count fields instead of one. The schemes could be made more
1568+
superficially similar, but it is not clear that would be worthwhile.
1569+
PEP 683 maintains compatibility with extensions compiled to the
1570+
stable ABI, and therefore uses the second most significant bit
1571+
(i.e., 2^62 on 64-bit platforms) to mark immortal objects. Checking
1572+
that bit typically requires an extra instruction on x86-64 compared
1573+
with checking the sign bit or one of the low 32 bits. This PEP
1574+
cannot maintain compatibility with extensions compiled to the stable
1575+
ABI because of the use of two reference count fields, and so this PEP
1576+
is free to propose a representation that allows slightly more
1577+
efficient checks for immortality on x86-64.
1578+
1579+
15341580
Open Issues
15351581
===========
15361582

@@ -1548,23 +1594,39 @@ manner.
15481594
Python Build Modes
15491595
------------------
15501596

1551-
This PEP introduces a new build mode (``--without-gil``) that is not
1597+
This PEP introduces a new build mode (``--disable-gil``) that is not
15521598
ABI compatible with the standard build mode. The additional build
15531599
mode adds complexity for both Python core developers and extension
1554-
developers. The author believes a worthwhile long-term goal is to
1555-
combine these build modes and have the global interpreter lock
1556-
controlled at runtime, possibly disabled by default. The path to
1557-
this goal remains an open issue.
1600+
developers. The author believes a worthwhile goal is to combine
1601+
these build modes and have the global interpreter lock controlled at
1602+
runtime, possibly disabled by default. The path to this goal remains
1603+
an open issue, but a possible path might look like the following:
1604+
1605+
#. In 2024, CPython 3.13 is released with support for a
1606+
``--disable-gil`` build time flag. There are two ABIs for
1607+
CPython, one with the GIL and one without. Extension authors
1608+
target both ABIs.
1609+
#. After 2--3 releases, (i.e., in 2026--2027), CPython is released
1610+
with with the GIL controlled by a runtime environment variable or
1611+
flag. The GIL is enabled by default. There is only a single ABI.
1612+
#. After another 2--3 release (i.e., 2028--2030), CPython switches to
1613+
the GIL being disabled by default. The GIL can still be enabled
1614+
at runtime via an environment variable or command line flag.
1615+
1616+
This PEP covers the first step, with the remaining steps left as open
1617+
issues. In this scenario, there would be a two to three year period
1618+
where extension authors would target an extra CPython build per
1619+
supported CPU architecture and OS.
15581620

15591621

15601622
Mitigations for Single-Threaded Performance
15611623
-------------------------------------------
15621624

15631625
The changes proposed in the PEP will increase execution overhead for
1564-
``--without-gil`` builds compared to Python builds with the GIL. In
1626+
``--disable-gil`` builds compared to Python builds with the GIL. In
15651627
other words, it will have slower single-threaded performance. There
15661628
are some possible optimizations to reduce execution overhead,
1567-
especially for ``--without-gil`` builds that only use a single
1629+
especially for ``--disable-gil`` builds that only use a single
15681630
thread. These may be worthwhile if a longer term goal is to have a
15691631
single build mode, but the choice of optimizations and their
15701632
trade-offs remain an open issue.

0 commit comments

Comments
 (0)