Skip to content
Draft
Changes from 1 commit
Commits
Show all changes
81 commits
Select commit Hold shift + click to select a range
4187872
Let "python3" be set at the commandline.
ericsnowcurrently Aug 19, 2024
424dc37
Add a NEWS entry.
ericsnowcurrently Aug 20, 2024
9ab68fa
Add the concurrency howto doc.
ericsnowcurrently Aug 19, 2024
fce455e
Add more explanation.
ericsnowcurrently Aug 20, 2024
28d8ac0
More explanation.
ericsnowcurrently Aug 20, 2024
503d829
Re-structure the comparison table.
ericsnowcurrently Aug 20, 2024
e5d904f
Add basic examples for each concurrency model.
ericsnowcurrently Aug 20, 2024
b7bb9a5
Clarify about "spook action at a distance".
ericsnowcurrently Aug 21, 2024
7efb9b4
Clarify about the "pain" threads can cause.
ericsnowcurrently Aug 21, 2024
daaa02b
Add references to the howto in the library docs.
ericsnowcurrently Aug 21, 2024
ad50bdd
Clean up the Python concurrency models section.
ericsnowcurrently Aug 21, 2024
3a82978
Add a section about concurrent.futures.
ericsnowcurrently Aug 21, 2024
560f26e
Make the examples runnable.
ericsnowcurrently Aug 21, 2024
4f49ed7
Revert changes to Makefile.
ericsnowcurrently Aug 22, 2024
5151e3b
Fix a typo.
ericsnowcurrently Aug 22, 2024
14e59f8
Fix sphinx warnings.
ericsnowcurrently Aug 22, 2024
0b27fd9
Adjust the references.
ericsnowcurrently Aug 22, 2024
0586c72
Fill out and restructure the comparisons.
ericsnowcurrently Aug 22, 2024
8df61ad
Fill out the section about Python theads.
ericsnowcurrently Aug 22, 2024
269eaac
Fill out the section about multiple interpreters.
ericsnowcurrently Aug 22, 2024
7754912
Fill out the section about multprocessing.
ericsnowcurrently Aug 22, 2024
2c9a793
Fill out the section about async/await.
ericsnowcurrently Aug 23, 2024
2975bbb
Shuffle the concurrency model order.
ericsnowcurrently Aug 23, 2024
b82a18b
Fill out the section about distributed concurrency.
ericsnowcurrently Aug 23, 2024
5e7f7c3
Drop an incomplete note.
ericsnowcurrently Aug 23, 2024
c06b843
Fix typos.
ericsnowcurrently Aug 23, 2024
e05e76e
Add a missing divider.
ericsnowcurrently Aug 23, 2024
e7144ec
Add a link to the "overhead" table.
ericsnowcurrently Aug 26, 2024
e131b83
Expand the general explanation of workloads.
ericsnowcurrently Aug 26, 2024
c601e27
Updates for the first two workload examples.
ericsnowcurrently Aug 26, 2024
5c05581
Do not worry about demonstrating a web service.
ericsnowcurrently Aug 27, 2024
a0a8ebb
Move the grep example up.
ericsnowcurrently Aug 27, 2024
c3d1688
Implement threads for the grep example.
ericsnowcurrently Aug 27, 2024
48ac79d
Implement grep using concurrent.futures.
ericsnowcurrently Aug 28, 2024
9a1a81c
Fix nested lists and add quadrants.
ericsnowcurrently Aug 29, 2024
03156b5
Implement grep using multiprocessing.
ericsnowcurrently Aug 29, 2024
e0d833e
Start reorganizing, and dump a bunch of explanation.
ericsnowcurrently Aug 29, 2024
6dd91e3
Clarify about Python-supported concurrency models.
ericsnowcurrently Sep 3, 2024
1e935df
Small clarifications and cleanup.
ericsnowcurrently Sep 3, 2024
4fdf9f5
Move the high-level APIs section down.
ericsnowcurrently Sep 3, 2024
cb843f6
Clarify about the comparisons.
ericsnowcurrently Sep 3, 2024
8a87617
Updates about free-threading caveats.
ericsnowcurrently Sep 3, 2024
288c4f4
Formatting and links for intro section.
ericsnowcurrently Sep 4, 2024
0b768ae
wording tweaks
ericsnowcurrently Sep 4, 2024
ab24e83
Update the section about multiple interpreters.
ericsnowcurrently Sep 4, 2024
f7f1769
Update the section about coroutines.
ericsnowcurrently Sep 4, 2024
fdf46cb
Update the sections about multi-processing.
ericsnowcurrently Sep 4, 2024
4cc62a1
Clear out the section on downsides.
ericsnowcurrently Sep 4, 2024
54bacb6
Update the section about shared resources.
ericsnowcurrently Sep 4, 2024
49ec62f
Normalize TODO comments.
ericsnowcurrently Sep 4, 2024
8fd8406
Move the explanations to the right places.
ericsnowcurrently Sep 4, 2024
fdcc128
Add sub-sections.
ericsnowcurrently Sep 4, 2024
3033875
Move the caveats subsections around.
ericsnowcurrently Sep 4, 2024
3e4ab6a
Fix formatting.
ericsnowcurrently Sep 4, 2024
f07c696
Drop a TODO.
ericsnowcurrently Sep 4, 2024
7a04361
Hide the incomplete portions of text.
ericsnowcurrently Sep 4, 2024
f9815bb
Tweak a table header.
ericsnowcurrently Sep 4, 2024
48551a7
Fix a table header.
ericsnowcurrently Sep 4, 2024
eac23f9
Fix the sidebar table of contents.
ericsnowcurrently Sep 16, 2024
3e1c53e
Expand the grep section and code.
ericsnowcurrently Sep 16, 2024
9f6ea1f
Make the examples more uniform.
ericsnowcurrently Sep 16, 2024
3aaa4d1
Fix some wording.
ericsnowcurrently Sep 17, 2024
3a7b0be
Reorganize the example code a little.
ericsnowcurrently Sep 17, 2024
36edcce
Split up the examples file.
ericsnowcurrently Sep 18, 2024
7b4af12
Tweak CLI.
ericsnowcurrently Sep 18, 2024
bc6e725
Simplify the examples.
ericsnowcurrently Sep 19, 2024
f4749f6
Drop all the context manager stuff.
ericsnowcurrently Sep 19, 2024
eaaecca
Implement the async example.
ericsnowcurrently Sep 20, 2024
ebf3130
Drop the text about do_search().
ericsnowcurrently Sep 20, 2024
21ff9e1
Fix a typo.
ericsnowcurrently Sep 23, 2024
3682348
Move the grep examples to individual files.
ericsnowcurrently Sep 23, 2024
10ee369
Tweak run-examples.py to run the newer example code.
ericsnowcurrently Sep 23, 2024
e6f0088
Drop the combined grep package.
ericsnowcurrently Sep 24, 2024
3f2637b
Fix the highlighting.
ericsnowcurrently Sep 24, 2024
9ce6ccf
cleanups
ericsnowcurrently Sep 24, 2024
10a6571
Fix typos and wording.
ericsnowcurrently Sep 24, 2024
793bfa0
Limit side-by-side example lines to 60 characters.
ericsnowcurrently Sep 24, 2024
3e19d7e
Fix the examples.
ericsnowcurrently Sep 24, 2024
f826c9c
Fix a ref.
ericsnowcurrently Sep 24, 2024
049f1de
lint
ericsnowcurrently Sep 25, 2024
7686e10
Merge branch 'main' into concurrency-howto
AA-Turner Apr 29, 2025
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
Prev Previous commit
Next Next commit
Fix typos and wording.
  • Loading branch information
ericsnowcurrently committed Sep 24, 2024
commit 10a65718e3b1845211ace98355afddf0a3673662
44 changes: 22 additions & 22 deletions Doc/howto/concurrency.rst
Original file line number Diff line number Diff line change
Expand Up @@ -496,12 +496,11 @@ short turns, so none have to wait too long, but it still prevents
any actual parallelism of CPU-bound code.

That said, the Python runtime (and extension modules) can release the
:term:`!GIL` when the thread is going to be doing something unrelated
to Python, particularly something slow or long,
like a blocking IO operation.
:term:`!GIL` when the thread is doing slow or long-running work
unrelated to Python, like a blocking IO operation.

There is also an ongoing effort to eliminate the :term:`!GIL`:
:pep:`630`. Any attempt to remove the :term:`!GIL` necessarily involves
:pep:`703`. Any attempt to remove the :term:`!GIL` necessarily involves
some slowdown to single-threaded performance and extra maintenance
burden to the Python project and extension module maintainers.
However, there is sufficient interest in unlocking full multi-core
Expand Down Expand Up @@ -549,7 +548,7 @@ Using multiple interpreters is fairly straight-forward:
3. call :func:`exec`, but targeting the new interpreter
4. switch back
Comment thread
savannahostrowski marked this conversation as resolved.

Note that no threads were involved. That's because running in an
Note that no threads were involved; running in an

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a bit confusing; the second step before says "switch the current thread" and now it says "no threads were involved". I understand that before it means "switch this one main thread" and here is more "no other threads were involved, not multithreading at all", but maybe this could be rephrased?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, it should be "no new threads were involved". I'll fix that.

interpreter happens relative to the current thread. New threads
aren't implicitly involved.

Expand All @@ -574,9 +573,9 @@ Python 3.13+ on PyPI: :pypi:`interpreters-pep-734`.
Improving performance for multiple interpreters
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

The long effort to improve on Python's implementation of multiple
interpreters focused on isolation and stability. There was very little
done to improve performance. This has the most impact on:
The long-running effort to improve on Python's implementation of multiple
interpreters focused on isolation and stability; very little done
to improve performance. This has the most impact on:

* how much memory each interpreter uses
(i.e. how many can run at the same time)
Expand All @@ -586,7 +585,7 @@ It also impacts how efficiently data/objects can be passed between
interpreters, and how effectively objects can be shared.

As the work on isolation wraps up, improvements will shift to focus
on performance and memory usage. Thus the overhead associated with
on performance and memory usage. Thus, the overhead of
using multiple interpreters will drastically decrease over time.

Shared resources
Expand All @@ -595,7 +594,7 @@ Shared resources
Aside from memory, all physical threads in a process share the

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is true also for multiple interpreters? here it says explicitly "physical threads", but all the last points were about multiple interpreters and confuses a little.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This section covers caveats for all the different concurrency models, though I can see how the ordering of the sub-sections may have lead to confusion. I'll either move this section earlier or I'll add a sentence to make it clear that it applies to Python threads and multiple interpreters equally.

following resources:

* commandline arguments ("argv")
* command line arguments ("argv")
* env vars
* current working directory
* signals, IPC, etc.
Expand All @@ -612,8 +611,8 @@ TBD

The other potential problem with using threads is that the conceptual
model has no inherent synchronization, so it can be hard to follow
what is going on in the program at any given moment. That is
especially challenging for testing and debugging.
what is going on in the program at any given moment. That
would especially impact your efforts at testing and debugging.

* "callback hell"
* "where was this thread/coroutine started?"
Expand Down Expand Up @@ -643,7 +642,7 @@ explicitly yielding control at the appropriate moments.

Normal functions do not follow this pattern, so they cannot take
advantage of that cooperative scheduling to avoid blocking
the program. Thus coroutines and non-coroutines don't mix well.
the program. Thus, coroutines and non-coroutines don't mix well.
While there are tools for wrapping normal functions to act like
coroutines, they are often converted into coroutines instead.
At that point, if any non-async code relies on the function then
Expand Down Expand Up @@ -827,7 +826,7 @@ TBD
"thread" of execution.

Sometimes it makes sense to break up that sequence into smaller pieces,
where some of them can run independently of others. Thus the program
where some of them can run independently of others. Thus, the program
then involves multiple logical threads. This is also called
"multitasking" and each logical thread a "task".

Expand Down Expand Up @@ -958,13 +957,14 @@ TBD

As mentioned earlier, each concurrency model has its own set of tradeoffs.
Free-threading probably has the most notoriety and the most examples,
but is also has the most pitfalls (see `Critical caveats`_ above).
but it also has the most pitfalls (see `Critical caveats`_ above).
Isolated threads have few of those pitfalls but are less familiar
and at least a little less efficient.
Multiprocessing and distributed are likewise isolated, but less
efficient, which can have a larger negative impact at smaller scales.
Multiprocessing and distributed computing are likewise isolated,
but less efficient, which can have a larger negative impact
at smaller scales.
Async can be straightforward, but may cascade throughout a code base
and doesn't necessarily give you parallelism.
and doesn't provide parallelism.

free-threading:

Expand Down Expand Up @@ -1045,7 +1045,7 @@ TBD
Dealing with data races is often managed using locks (AKA mutexes),
at a low level, and thread-safe types and APIs at a high level.
Depending on the programming language, the complexity is sometimes
mitigated somewhat by the compiler and runtime. There are even
mitigated by the compiler and runtime. There are even
libraries and frameworks that help abstract away the complexity
to an extent. On top of that, there are tools that can help identify
potential races via static analysis. Unfortunately, none of these aids
Expand Down Expand Up @@ -1099,9 +1099,9 @@ TBD
Python Concurrency Workload Examples
====================================

Below we have a series of examples of how to implement the most
Below, we have a series of examples of how to implement the most
common Python workloads that take advantage of concurrency.
For each workload you will find an implementation for each of the
For each workload, you will find an implementation for each of the
concurrency models.

The implementations are meant to accurately demonstrate how best
Expand Down Expand Up @@ -1163,7 +1163,7 @@ Also see:

.. note::

Each example is implemented as a basic commandline tool, but can be
Each example is implemented as a basic command line tool, but can be
easily adapted to run as a web service.

Workload: grep
Expand Down