This PEP poses new challenges for distributing Python. At least for some time, there will be two versions of Python requiring separately compiled C-API extensions. It may take some time for C-API extension authors to build --disable-gil compatible packages and upload them to PyPI. Additionally, some authors may be hesitant to support the --disable-gil mode until it has wide adoption, but adoption will likely depend on the availability of Python’s rich set of extensions.
To mitigate this, the author will work with Anaconda to distribute a --disable-gil version of Python together with compatible packages from conda channels. This centralizes the challenges of building extensions, and the author believes this will enable more people to use Python without the GIL sooner than they would otherwise be able to.
For extension developers, in practice this would mean that both the --disable-gil and GIL versions will need to be maintained for an extended period of time. Given the lifecycle of Linux releases such as ubuntu and debian at least 5 years. During this time there will be limitations on how extensions can be developed because of the dual compatibility. There is not really a choice to only develop for x or y. If you want your extension/prorgram to be seriously considered, it needs to run on both versions of the interpreter. I really don’t want another era where I have to write a limited subset of python, literally getting the worst of both worlds, for compatibility reasons. Python 2’s well deserved rest felt as a liberation to me and going back to a similar scenario fills me with dread.
Thanks for your feedback, I appreciate the candor. However, my question is not ignorant of the use cases and the potential benefits a no-gil version to those use cases would have.
I am merely observing, from my own background, that the “GIL issues” are often raised due to considering a program and data design that are ameanable to shared-all free threading concurrency model, whereas Python (or rather CPython) effectively prefers shared-nothing concurrency. Incidentally, the latter has been known easier to reason about, to be less prone to failures, and in many cases also to be easier to scale.
I propose that this can be seen as a benefit, not a burden and I am asking if the risks inherent in a change of this dimension is warranted, including giving up on a fundamental benefit.
Two things can be true at once. This comment is generally true, and there are also situations where shared-nothing does not work well, as pointed out in many posts on the various topics about removing the GIL.
Even if you have no use for shared memory parallelism, and only want to use the safer share-nothing approach, it is beneficial if the underlying VM can support sharing objects as it can make message passing much more efficient.
I agree that share-nothing is superior in terms of safety, but multiprocessing is an inefficient way to do it.
Erlang processes are conceptually isolated, but generally run in the same OS process (if running on the same physical machine).
The JVM supports a shared memory concurrency model, but nothing prevents you building a share-nothing application on top of it.
Yes, but do we want to? I for one deliberately left Java behind in favor of Python for all the (very often unnecessary) complexity the going powers that were and the common dogma would declare best practice. In particular Java’s multithreading and memory model is not something I miss.
Also it took the JVM years to be free of concurrency issues.
Yes, many people want to have free-threading in Python. It might be a good idea to read this thread, and the two PEP 703 discussion threads (first, second), in full (yes, all 370+ messages). Many people have shown why the existing models are not enough, and have presented real-life examples where the GIL was a bottleneck, and sometimes caused a rewrite in another language.
Free-threading might not be easy to implement at first, but it is certainly worth the effort in the long term. If PEP 703 is rejected, I would (in my personal opinion) consider it as an admission that Python is a toy language, requiring “serious” workflows to be implemented in C.
That’s a bit too strong of a position IMO. If PEP 703 is rejected, I would consider it an admission that free threading is hard, requires difficult decisions in terms of what consequences are acceptable, and will require further planning before it gets implemented.
The general tone from most people has been “this would be great, but what are the costs”. Rejecting one specific proposal for free threading doesn’t mean that nobody wants free threading.
I think this does depend on the form of rejection, though. If it came down in the same tone as some of the posts in this thread , I don’t imagine another Sam Gross coming along for the foreseeable future.
not that I think it would, based on the discussions I’ve read ↩︎
It’s already implemented and working, with minimal performance losses compared to previous efforts and at least one mega-org committed to subsidizing the effort for years with engineers that have expertise with the code.
If this doesn’t happen now then I would be shocked if it ever did.
That’s fair, but I agree, I don’t foresee a rejection in the form of “this is a terrible idea at any cost”. Of course, I can’t speak for the SC in any way. I just wanted to clarify the distinction between rejecting PEP 703 (one very specific proposal for free threading) and rejecting the notion of free threading altogether.
That’s probably the point of contention in this thread: can we expect “most code” to add locks in all the right places? If yes, then full-in nogil is fine. If no, nogil is a bad option. I am with the no camp because in my experience people want performance but value safety. That’s only possible in a gil world.
You are talking about code which is pure Python and is supposed to run in a threaded environment. Unless it’s properly protected with locks/queues etc, it’s going to be failing regardless of whether it’s running with free threads or not. Either the (Python) code is threadsafe and then you can run it with threads (GILed CPython, pypy, ironpython or CPython with free threads) or it’s not threadsafe and then just don’t use threads or sooner or later it will fail.
people want performance but value safety. That’s only possible in a gil world.
Other programming languages don’t have GIL and I wouldn’t call them unsafe (because of that). Python world isn’t “special” in a sense that it “can’t handle” free threads. It can. It will take a while to get used to it and there will be bugs, but those that happen frequently will be squashed quickly. If you are running a heart rate monitor or something, stay with 3.11 until you feel it’s safe enough for you to upgrade.
I’m not sure you understand what Brett wrote. The requirements for thread safety are no different in the GIL and no-GIL scenarios. I believe the original reason for including the GIL was to simplify Python’s C internals. It also simplifies extension module implementations. It has no effect on the correctness of Python code.
That is not necessarily true. Threaded code in nogil will likely have side effects that need additional explicit locking that are not needed with the GIL. This means the same Python code running just fine, implicated by the GIL, may fail in nogil for reasons that are not obvious.
This describes the Python-2-3 migration - which took a whole decade - and nobody wants to go back to that. So let’s not do that please.
I get that many people want free threading, yet isn’t it also true that many times more people do not need it, and might suffer from having to live through the process to get there, or because they rely on the implicit guarantees given by the GIL?
Btw it’s not that I wouldn’t want free threading in Python, I just happen to think that the risks to Python as a language, and to the ecosystem while getting there are not worth taking. I would much rather see efforts spent on making use of nogil extensions (e.g. using Cython) both more known and less cumbersome.
Please provide an example. Many people (myself included) have expressed this concern, and have been convinced that it is not an actual problem. If you have code that is correct (and threadsafe) under the GIL, but will not be threadsafe without the GIL, please show it.
Note that if your code is not threadsafe with the GIL, that’s not a problem with nogil - it’s just something for you to decide (do you want to support threads in the first place).
I think it’s a misunderstanding that we are faced with a choice between a path forward where we need extra care with C extension thread safety, and a path forward where we don’t.
Rather, the choice is between improving multi-core performance with PEP 703 free-threading, and improving multi-core performance with subinterpreters. Both make the same demands on C extension thread safety. For example, the Linux putenv/getenv issue that was mentioned as a problem for regular threading, applies just as much to subinterpreters.
There are differences: One is that subinterpreters have an additional requirement that PyObjects from one subinterpreter must not be used in another. Another is that we can ask more thread-safety diligence of authors of subinterpreter code, as it will be new code, whereas regular threaded code has a large installed base.
But unless we want subinterpreters to be second class use-at-your-own-risk citizens of the Python ecosystem, we need to address C extension thread safety.