Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add initial free-threading page for the guide #4577

Merged
merged 10 commits into from
Oct 21, 2024

Conversation

ngoldbaum
Copy link
Contributor

Moves the existing content on free-threading in the migration guide into its own page. Also adds some new content about things we know are going to be issues for some users.

Comments and suggestions are very welcome. I'd really appreciate ideas for illustrative code examples to add, if anyone has any.

guide/src/free-threading.md Outdated Show resolved Hide resolved
Copy link
Contributor

@Icxolu Icxolu left a comment

Choose a reason for hiding this comment

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

Sounds good already, added some thoughts that came to mind while reading (from someone who hasn't looked a lot into free-threading yet)

(Nit: Maybe we can use a consistent capitalization of "Python" 🙃)

guide/src/free-threading.md Outdated Show resolved Hide resolved
guide/src/free-threading.md Outdated Show resolved Hide resolved
Comment on lines 39 to 50
Instead, you can think about whether or not you a rust scope has access to a
Python **thread state** in `ATTACHED` status. See [PEP
703](https://peps.python.org/pep-0703/#thread-states) for more background about
Python thread states and status. In order to use the CPython C API in both the
GIL-enabled and free-threaded builds of CPython, you must own an attached
Python thread state. The `with_gil` function sets this up and releases the
thread state after the closure passed to `with_gil` finishes. Similarly, in both
the GIL-enabled and free-threaded build, you must use `allow_threads` in
order to use rust threads. Both of `with_gil` and `allow_threads` tell CPython
to put the Python thread state into `DETACHED` status. In the GIL-enabled build,
this is equivalent to releasing the GIL. In the free-threaded build, this unblocks
CPython from triggering a stop-the-world for a garbage collection pass.
Copy link
Contributor

Choose a reason for hiding this comment

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

This is very valuable information, but also pretty technical. Maybe we should put this in a <details> tab and summarize that on a higher level, so that it's a bit easier to grasp for new users. Maybe that "GIL" refers to the interaction with the Python interpreter or something like that.

Copy link
Member

Choose a reason for hiding this comment

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

I think I agree, the main point that PyO3 still requires attachment to a Python thread to do Python work is a bit blurred with the technical details of how attachment works here.

Comment on lines 45 to 47
thread state after the closure passed to `with_gil` finishes. Similarly, in both
the GIL-enabled and free-threaded build, you must use `allow_threads` in
order to use rust threads. Both of `with_gil` and `allow_threads` tell CPython
Copy link
Contributor

Choose a reason for hiding this comment

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

I'm not quite sure how to interpret the "Rust threads" part. I don't think there is a problem in just spawning Rust thread an doing something different non Python related in the background. It's more about detaching the current thread from it's interaction with the Interpreter and handing back control, if I got that correctly.

Copy link
Member

@davidhewitt davidhewitt left a comment

Choose a reason for hiding this comment

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

Thanks, this is already looking great to me! I have a few suggestions too...

Comment on lines 39 to 50
Instead, you can think about whether or not you a rust scope has access to a
Python **thread state** in `ATTACHED` status. See [PEP
703](https://peps.python.org/pep-0703/#thread-states) for more background about
Python thread states and status. In order to use the CPython C API in both the
GIL-enabled and free-threaded builds of CPython, you must own an attached
Python thread state. The `with_gil` function sets this up and releases the
thread state after the closure passed to `with_gil` finishes. Similarly, in both
the GIL-enabled and free-threaded build, you must use `allow_threads` in
order to use rust threads. Both of `with_gil` and `allow_threads` tell CPython
to put the Python thread state into `DETACHED` status. In the GIL-enabled build,
this is equivalent to releasing the GIL. In the free-threaded build, this unblocks
CPython from triggering a stop-the-world for a garbage collection pass.
Copy link
Member

Choose a reason for hiding this comment

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

I think I agree, the main point that PyO3 still requires attachment to a Python thread to do Python work is a bit blurred with the technical details of how attachment works here.

Comment on lines 54 to 59
If you wrote code that makes strong assumptions about the GIL protecting shared
mutable state, it may not currently be straightforward to support free-threaded
Python without the risk of runtime mutable borrow panics. PyO3 does not lock
access to python state, so if more than one thread tries to access a python
object that has already been mutably borrowed, only runtime checking enforces
safety around mutably aliased data owned by the Python interpreter.
Copy link
Member

Choose a reason for hiding this comment

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

Here there is a point to be made that the user would have knowingly made such an assumption by using unsafe impl for Send and/or Sync (especially if the PyO3 API is correct in its requirements of these).

guide/src/free-threading.md Outdated Show resolved Hide resolved
guide/src/free-threading.md Outdated Show resolved Hide resolved
@ngoldbaum
Copy link
Contributor Author

Thanks for all the comments! I hope the new text addresses the concerns and is clearer.

I'd like to add sections on the critical section and PyMutex wrappers, assuming those get merged, and also maybe another section in the docs about multithreaded programming using PyO3? I definitely found it nontrivial to learn and things like std::thread::scope should be pointed at explicitly in the PyO3 docs.

Copy link
Contributor

@Icxolu Icxolu left a comment

Choose a reason for hiding this comment

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

Very nice, this reads a lot easier to me.

I guess my main concern is still what terminology we use, when we want to talk about interacting with the interpreter.

I think there are now 3 different wordings in different paragraphs. Sometimes it's still referred to as "GIL", then we have "thread state" and we have "attached to the runtime". I think unifying them makes sense to not overload readers. Personally I like the "attached to the runtime" variant because it's high level enough that someone without much experience can get an idea about whats going on (I think?) and it's independent of the build-mode. We can also add a later (sub)section explaining what "attached to the runtime" means as technical documentation.

guide/src/free-threading.md Outdated Show resolved Hide resolved
guide/src/free-threading.md Outdated Show resolved Hide resolved
guide/src/free-threading.md Outdated Show resolved Hide resolved
guide/src/free-threading.md Outdated Show resolved Hide resolved
Copy link
Member

@davidhewitt davidhewitt left a comment

Choose a reason for hiding this comment

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

Looking great, thanks! Just a few smaller thoughts, and then let's merge 👍

the GIL is acquired. In the free-threaded build there is no GIL, but the same C
macros that release or acquire the GIL in the GIL-enabled build instead ask the
interpreter to attach the thread to the Python runtime, and there can be many
threads simultaneously attached.
Copy link
Member

Choose a reason for hiding this comment

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

I think we should add a sentence here along the lines of

"Similarly, in the GIL-enabled build PyO3 uses the Python<'py> type and the 'py lifetime to signify attachment the global interpreter lock; in the freethreaded build these simply mean the thread is currently attached to the Python interpreter."

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I incorporated this and edited the surrounding paragraphs a bit. I think it reads better now, thanks for the suggestion.

guide/src/free-threading.md Outdated Show resolved Hide resolved
guide/src/free-threading.md Outdated Show resolved Hide resolved
guide/src/free-threading.md Outdated Show resolved Hide resolved
guide/src/free-threading.md Outdated Show resolved Hide resolved
guide/src/free-threading.md Outdated Show resolved Hide resolved
guide/src/free-threading.md Outdated Show resolved Hide resolved
guide/src/free-threading.md Outdated Show resolved Hide resolved
@ngoldbaum ngoldbaum changed the title add first draft of free-threading page for the guide Add initial free-threading page for the guide Oct 18, 2024
Copy link
Member

@davidhewitt davidhewitt left a comment

Choose a reason for hiding this comment

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

Looks great, thanks!

@davidhewitt davidhewitt added this pull request to the merge queue Oct 21, 2024
Merged via the queue into PyO3:main with commit 7f961b2 Oct 21, 2024
42 of 43 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants