11 ms·
Everything you need to know about Python 3.13 – JIT and GIL went up the hill
- MrThoughtful 2y agoRemoving the GIL sounds like it will make typical Python programs slower and will introduce a lot of complexity? What is the real world benefit we will get in return? In the rare case where I need to max out more than one CPU core, I usually implement that by having the OS run multiple instances of my program and put a bit of parallelization logic into the program itself. Like in the mandelbrot example the author gives, I would simply tell each instance of the program which part of the image it will calculate.
- cma 2y agoThere will be consumer chips with 64 cores before long
- tonygrue 2y agoThere is an argument that if you need in process multithreading you should use a different language. But a lot of people need to use python because everything else they’re doing is in python. There are quite a few common cases where in process multi threading is useful. The main ones are where you have large inputs or large outputs to the work units. In process is nice because you can move the input or output state to the work units instead of having to copy it. One very common case is almost all gui applications. Where you want to be able to do all work on background threads and just move data back and forth from the coordinating ui thread. JavaScript’s lack of support here, outside of a native language compiled into emscripten, is one reason web apps are so hard to make jankless. The copies of data across web workers or python processes are quite expensive as far as things go. Once a week or so, I run into a high compute python scenario where the existing forms of multiprocessing fail me. Large shared inputs and or don’t want the multiprocess overhead; but GIL slows everything down.
- vlovich123 2y ago> Where you want to be able to do all work on background threads and just move data back and forth from the coordinating ui thread. JavaScript’s lack of support here, outside of a native language compiled into emscripten, is one reason web apps are so hard to make jankless I thought transferring array buffers through web workers didn’t involve any copies of you actually transferred ownership: worker.postMessage(view.buffer, [view.buffer]); I can understand that web workers might be more annoying to orchestrate than native threads and the like but I’m not sure that it lacks the primitives to make it possible. More likely it’s really hard to have a pauseless GC for JS (Python predominantly relies on reference counting and uses gc just to catch cycles).
- Etheryte 2y agoThis is true, but when do you really work with array buffers in Javascript? The default choice for whatever it is that you're doing is almost always something else, save for a few edge cases, and then you're stuck trying to bend your business logic to a different data type.
- vlovich123 2y agoThat’s a choice you get to make and probably depends on your problem domain and other things. For example when I was writing R2 it was all ArrayBuffers up and down the stack. And you could use something like capnproto or flat buffers for managing your object graph within an array buffer. But yeah, being able to transfer custom object graphs would be more powerful.
- simonw 2y agoMy hunch is that in just a few years time single core computers will be almost extinct. Removing the GIL now feels to me like good strategic preparation for the near future.
- im3w1l 2y agoSingle core computers yes. Single core containers though..
- gomerspiles 2y agoSingle core containers are also a terrible idea. Life got much less deadlocked as soon as there were 2+ processors everywhere. (Huh, people like hard OS design problems for marginal behavior? OSes had trouble adopting SMP but we also got to jettison a lot of deadlock discussions as soon as there was CPU 2. It only takes a few people not prioritizing 1 CPU testing at any layer to make your 1 CPU container much worse than a 2 VCPU container limited to a 1 CPU average.)
- seabrookmx 2y agoIt's actually quite difficult to get a "single core" container (ie: a container with access to only one logical processor). When you set "request: 1" in Kubernetes or another container manager, you're saying "give me 1 CPU worth of CPU time" but if the underlying Linux host has 16 logical cores your container will still see them. Your container is free to use 1/16th of each of them, 100% of one of them, or anything in-between. You might think this doesn't matter in the end but it can if you have a lot of workloads on that node and those cores are busy. Your single threaded throughout can become quite compromised as a result.
- Dylan16807 2y ago> if you have a lot of workloads on that node and those cores are busy. Your single threaded throughout can become quite compromised as a result. While yes this can cause a slowdown, wouldn't it still happen if each container thought it had a single core?
- Zyten 2y agoWhat you’re describing is basically using MPI in some way, shape or form. This works, but also can introduce a lot of complexity. If your program doesn’t need to communicate, then it’s easy. But that’s not the case for all programs. Especially once we’re talking about simulations and other applications running on HPC systems. Sometimes it’s also easier to split work using multiple threads. Other programming languages let you do that and actually use multiple threads efficiently. In Python, the benefit was just too limited due to the GIL.
- lifthrasiir 2y ago> Removing the GIL sounds like it will make typical Python programs slower and will introduce a lot of complexity? This was the original reason for CPython to retain GIL for very long time, and probably true for most of that time. That's why the eventual GIL removal had to be paired with other important performance improvements like JIT, which was only implemented after some feasible paths were found and explicitly funded by a big sponsor.
- klranh 2y agoThat is the official story. None of it has materialized so far.
- lifthrasiir 2y agoPython development is done in public so you can just benchmark against the development version to see its improvement. In fact, daily benchmarks are already posted to [1]; it indicates around 20% improvement (corresponding to 1.25x in the table) since 3.10. The only thing you can't easily verify is that whether GIL was indeed historically necessary in the past. [1] https://github.com/faster-cpython/benchmarking-public https://github.com/faster-cpython/benchmarking-public
- pansa2 2y ago> What is the real world benefit we will get in return? If you have many CPU cores and an embarrassingly parallel algorithm, multi-threaded Python can now approach the performance of a single-threaded compiled language.
- Certhas 2y agoThe question really is if one couldn't make multiprocess better instead of multithreaded. I did a ton of MPI work with python ten years ago already. What's more I am now seeing in Julia that multithreading doesn't scale to larger core counts (like 128) due to the garbage collector. I had to revert to multithreaded again.
- 0x000xca0xfe 2y agoYou could already easily parallelize with the multiprocessing module. The real difference is the lower communication overhead between threads vs. processes thanks to a shared address space.
- bdd8f1df777b 2y agoThe biggest use case (that I am aware of) of GIL-less Python is for parallel feeding data into ML model training. * PyTorch currently uses `multiprocessing` for that, but it is fraught with bugs and with less than ideal performance, which is sorely needed for ML training (it can starve the GPU). * Tensorflow just discards Python for data loading. Its data loaders are actually in C++ so it has no performance problems. But it is so inflexible that it is always painful for me to load data in TF. Given how hot ML is, and how Python is currently the major language for ML, it makes sense for them to optimize for this.
- carapace 2y ago> What is the real world benefit we will get in return? None. I've been using Python "in anger" for twenty years and the GIL has been a problem zero times. It seems to me that removing the GIL will only make for more difficulty in debugging.
- inoop 2y agoAs always, it depends a lot on what you're doing, and a lot of people are using Python for AI. One of the drawbacks of multi-processing versus multi-threading is that you cannot share memory (easily, cheaply) between processes. During model training, and even during inference, this becomes a problem. For example, imagine a high volume, low latency, synchronous computer vision inference service. If you're handling each request in a different process, then you're going to have to jump through a bunch of hoops to make this performant. For example, you'll need to use shared memory to move data around, because images are large, and sockets are slow. Another issue is that each process will need a different copy of the model in GPU memory, which is a problem in a world where GPU memory is at a premium. You could of course have a single process for the GPU processing part of your model, and then automatically batch inputs into this process, etc. etc. (and people do) but all this is just to work around the lack of proper threading support in Python. By the way, if anyone is struggling with these challenges today, I recommend taking a peek at nvidia's Triton inference server (https://github.com/triton-inference-server/server https://github.com/triton-inference-server/server), which handles a lot of these details for you. It supports things like zero-copy sharing of tensors between parts of your model running in different processes/threads and does auto-batching between requests as well. Especially auto-batching gave us big throughput increase with a minor latency penalty!
- saagarjha 2y agoMachine learning people not call their thing Triton challenge (IMPOSSIBLE)
- buildbot 2y agoThis (Nvidia’s) triton predates openAI’s by a few years.
- jgraettinger1 2y ago> For example, imagine a high volume, low latency, synchronous computer vision inference service. I'm not in this space and this is probably too simplistic, but I would think pairing asyncio to do all IO (reading / decoding requests and preparing them for inference) coupled with asyncio.to_thread'd calls to do_inference_in_C_with_the_GIL_released(my_prepared_request), would get you nearly all of the performance benefit using current Python.
- deleted 2y ago[deleted]
- imron 2y ago> Removing the GIL sounds like it will make typical Python programs slower and will introduce a lot of complexity? There is a lot of Python code that either explicitly (or implicitly) relies on the GIL for correctness in multithreaded programs. I myself have even written such code, explicitly relying on the GIL as synchronization primitive. Removing the GIL will break that code in subtle and difficult to track down ways. The good news is that a large percentage of this code will stay running on older versions of python (2.7 even) and so will always have a GIL around. Some of it however will end up running on no-GIL python and I don't envy the developers who will be tasked tracking down the bugs - but probably they will run on modern versions of python using --with-gil or whatever other flag is provided to enable the GIL. The benefit to the rest of the world then is that future programs will be able to take advantage of multiple cores with shared memory, without needing to jump through the hoops of multi-process Python. Python has been feeling the pain of the GIL in this area for many years already, and removing the GIL will make Python more viable for a whole host of applications.
- deleted 2y ago[deleted]
- pininja 2y agoI remember first discussions about removing the GIL back in 2021 and a lot of initial confusion about what the implications would be. This is a great summary if, like me, you weren’t satisfied with the initial explanations given at the time.
- ffsm8 2y ago2021 wasn't the first discussion about that. You can find forum and Reddit posts going back 15-20 years of people attempting to remove the GIL, Guido van Rossum just made the requirement that single core performance cannot be hurt by removing it, this made ever previous attempt fail in the end I.e. https://www.artima.com/weblogs/viewpost.jsp?thread=214235 https://www.artima.com/weblogs/viewpost.jsp?thread=214235
- pansa2 2y agoDid this attempt manage to preserve single-threaded performance, or was the requirement dropped?
- rightbyte 2y agoHe folded. The patches dropped some unrelated dead weight such that the effect is not as bad.
- klranh 2y agoThe effect is still 20-50% slowdown for single thread, even with the purported unrelated speedups to make the feature more palatable. That is absolutely in the range of previous attempts, which were rejected! The difference here is that its goes in now to gratify Facebook.
- EasyMark 2y agoFacebook or Microsoft?
- pjmlp 2y agoI really find a bummer that there is such a resistance to make JIT enable versions available for download, alongside the other variants. Naturally I can easily compile my own Python 3.13 version, no biggie. However from my experience, this makes many people that could potentially try it out and give feedback, don't care and rather wait.
- pzo 2y agonot sure if there will distributed in homebrew et al but at least "Pre-built binaries marked as free-threaded can be installed as part of the official Windows and macOS installers" [0] [0] https://docs.python.org/3.13/whatsnew/3.13.html#free-threaded-cpython https://docs.python.org/3.13/whatsnew/3.13.html#free-threade...
- Ralfp 2y agoJIT is in weird place now because according to a recent talk from PyCON US by it’s author, the tier 2 optimizer that prepares code for JIT reduces performance by 20% and JIT just recovers that performance loss. A lot of langugage is still not optimized by tier 2 [1] and even less has copy and patch templates for JIT. And JIT itself currently has some memory management issues to iron out. [1]: https://github.com/python/cpython/issues/118093 https://github.com/python/cpython/issues/118093 Talk by Brandt Butcher was there but it was made private: https://www.youtube.com/watch?v=wr0fVU3Ajwc https://www.youtube.com/watch?v=wr0fVU3Ajwc
- pjmlp 2y agoI have seen some stuff about that, however that is to be expected. Many of these kind of changes take time, and require multiple interactions. See Go or .NET tooling bootstraping, all the years that took MaximeVM to evolve into GraalVM, Swift evolution versus Objective-C, Java/Kotlin AOT evolution story on Android, and so on. If only people that really deeply care get to compile from source to try out the JIT and give feedback, it will have even less people trying it out than those that bother with PyPy.
- punnerud 2y agoThe ones saying they will never use Python because it’s slow, is the probability high that their “fast” language is not thread safe?
- IshKebab 2y agoWhat do you mean by thread safe exactly? Instead of Python I would use Typescript or Rust or possibly Go.
- continuational 2y agoPython isn't "thread safe", not even its lists are. What are you getting at?
- meindnoch 2y agoPython is not thread safe.
- Quothling 2y agoHow many teams actually decide against using Python because it's "slow"? I'll personally never really get why people prefer interpreted languages in the age of Go, but even if we go back a few years, you would just build the computation heavy parts of your Python in C. Just like you would do with your C#, your Java or whatever you use when it was required. Considering Instagram largely ran/run their back-end on Python, I'd argue that you can run whatever you want with Python. Maybe I've just lived a sheltered life, but I've never heard speed being used as a serious argument against Python. Well, maybe on silly discussions where someone really disliked Python, but anyone who actually cares about efficiency is using C.
- wongarsu 2y agoYou occasionally hear stories about teams writing something in Python, then rewriting it in another language because Python turned out to be slow. I have one such story. With the excellent Python/Rust interop there is now another great alternative to rewriting the heavy parts in C. But sometimes the performance sensitive part spans most of your program
- 2y ago
- deleted 2y ago[deleted]
- kenzo123456789 2y ago[flagged]
- kenzo123456789 2y ago[flagged]
- sandos 2y agoSo is it impossible to optimize the no-GIL case more really? 20% slower sounds like a lot really.
- Ralfp 2y agoWhere it says that? Its simply that Python releases features in yearly cycles and thats what was completed for release. Idea is to let people experiment with no-GIL to see what it breaks while maintainers and outside contractors improve the performance in future versions.
- klranh 2y agoNo that was not the idea. The feature went in under the assumption that the single thread slowdown would be offset by other minor speed improvements. That was literally the official reason why it was accepted. Now we have slowdowns ranging from 20-50% compared to Python 3.9. What outside contractors would fix the issue? The Python ruling class has chased away most people who actually have a clue about the Python C-API, which are now replaced by people pretending to understand the C-API and generating billable hours.
- v3ss0n 2y agoExperimentally JIT WHILE there is totally stable , 4-100x faster, almost 100% compatible PyPy exist and all they need is adopt it but didn't due to some politics. Yeah right..
- ksec 2y agoI don't follow Python closely. So why PyPy isn't adopted?
- dagw 2y agoThe biggest reasons is that it isn't compatible with the python C API. So any library that uses the C API would have to be rewritten.
- tekknolagi 2y agoThey have gotten much better about that recently and it's much much more compatible now.
- v3ss0n 2y agoThe main reason GVR said is "May be this is future of Python , but not now" . At that time pypy was already stable at 2.7.x version but python 2-3 split happen. PyPy team have to rewrite everything for Python3 and took them a while to catchup. I had managed to talk with one ex pypy developer that the main reason GVR and Python community do not promote much about PyPy is due to NIH - Not invented here - Since PyPy is developed by seperate but full time computer scientist and researchers, PHDs , not by the Guido community . https://pypy.org/people.html https://pypy.org/people.html One problem about popularity of pypy is they don't do any advertisement , promotion which I had critically voiced about it in their community - they moved to Github finally. Only other problem is CPython Ext , which is compatible but a little bit slower than CPython - that only pain point we have - which could be solved if there are more contributors and users using pypy. Actually Python , written in Python should be the main
- jononor 2y agoThankfully everyone is free to use PyPy, if they consider it the better solution!
- wruza 2y agoIt’s worth mentioning that there is a bit more overhead in using multiple processes as opposed to multiple threads, in addition to it being more difficult to share data. There’s probably a whole generation of programmers (if not two) who don’t know the feeling of shooting yourself in the foot with multithreading. You spend a month on a prototype, then some more to hack it all together for semi-real world situations, polish the edges, etc. And then it falls flat day 1 due to unexpected races. Not a bad thing on itself, transferrable experience is always valuable. And don’t worry, this one is. Enough ecos where it’s not “difficult to share data”.
- jononor 2y agoThis. Multi-threading is very prone to nasty, hard to reproduce, bugs if used liberally in a codebase. It really should be used with care, and compartmentalized to areas where it demonstratively brings critical performance improvements.
- neonsunset 2y agoLet’s not tout abysmal state of multi-tasking in Python as an advantage. Somehow, it’s perfectly fine in C#, Java, now Go, Rust and many other languages, with relatively low frequency of defects.
- jononor 2y agoThat is not all what I did. But there are several languages/ecosystems which are very prone to such issues - notably C and C++. It is critical important (in my opinion) that Python does not regress to anywhere near that state. This might seem like an invalid concern - after all Python is a high-level, memory-safe language - right? The problem is that use of extensions (mostly in C or C++) are very common, and they rely on particular semantics - which are now changing. A vast amount of Python programs make use of such extensions, probably the majority of programs (even if excluding the standard library). Some of the biggest challenges around nogil and multi-threading in Python are mostly around extension/C related stuff. It was notably also on of the main challenges faced by PyPy. So maybe it's actually a little bit tricky to get right - and not just the developers being stupid or lazy ;) I mean in addition to the the usual general trickiness of major changes making to the core of an interpreter relied by thousands of companies/projects, in a wide range of fields, built over decades, with varying level of quality and maintenance....
- mg74 2y agoThe number one thing I wish was addressed in future version of Python is the semantically significant whitespace. Python is absolutely the worst language to work in with respect to code formatters. In any other language I can write my code, pressing enter or skipping enter however I want, and then the auto formatter just fixes it and makes it look like normal code. But in python, a forgotten space or an extra space, and it just gives up. It wouldn't even take much, just add a "end" keyword and the LSP's could just take care of the rest. GIL and JIT are nice, but please give me end.
- stavros 2y agoI don't have this problem, and I've been writing Python for more than twenty years. Sure, I may have the occasional wrong space somewhere, but it's maybe a few times a month, whereas I'd otherwise have to type "end" for every single block.
- mg74 2y agoI dont think this is a problem anymore in todays world of LSPs and auto formatters. I almost never have to type "end" in Elixir for instance, it is always autocompleted for me.
- stavros 2y agoHow does it know when to end a block?
- tredre3 2y agoThe autoformatter does it based on indentation, but when writing code the editor just inserts it when you open a block (after your cursor), same way } is added when you type { in other languages.
- stavros 2y agoAhh OK, I see, thanks. I don't really see much difference with whitespace sensitive languages, I've never really had problems with it. Maybe I've been lucky.
- zahsdga 2y agoThe performance degradation with nogil is quoted as 20%. It can easily be as much as 50%. The JIT does not seem to help much. All in all a very disappointing release that may be a reflection of the social and corporate issues in CPython. A couple of people have discovered that they can milk CPython by promising features, silencing those who are not 100% enthusiastic and then underdeliver. Marketing takes care of the rest.
- nmstoker 2y agoCould you clarify what/who you mean by the final sentence. It gives the impression you didn't take on board the articles mention about the three phases.
- jononor 2y agoWhy are you disappointed? Do you think that the progress should be faster? Or that this work should never have been started? Or that they should wait until it works better before integrering in master and having it in a mainline release?
- gavindean90 2y agoThe last one.
- akkad33 2y agoI think they explained why they are disappointed
- nmstoker 2y agoJust a minor correction: it's looking like the release will be 7th October, back from 2nd October, for the reasons discussed here: https://discuss.python.org/t/incremental-gc-and-pushing-back-the-3-13-0-release/65285 https://discuss.python.org/t/incremental-gc-and-pushing-back...
- drewsberry 2y agoThanks for pointing this out, I hadn't seen that – I've just pushed an update to reflect this.
- William_BB 2y agoCan someone explain this part: > What happens if multiple threads try to access / edit the same object at the same time? Imagine one thread is trying to add to a dict while another is trying to read from it. There are two options here Why not just ignore this fact, like C and C++? Worst case this is a datarace, best case the programmer either puts the lock or writes a thread safe dict themselves? What am I missing here?
- tliltocatl 2y agoMemory safety, heap integrity and GC correctness i guess. If you ignore facts like C your language will be as safe as C, except it's worse because at least C doesn't silently rearrange your heap in background.
- Numerlor 2y agoThere is an expectation of not dealing with data races from Python code. Apart from being a language where people expect these things to not be an issue it is also the behaviour with thw Gil in place and would be breaking
- deleted 2y ago[deleted]
- 0xFEE1DEAD 2y agoLet me preface this by saying I have no source to prove what I’m about to say, but Guido van Rossum aimed to create a programming language that feels more like a natural language without being just a toy language. He envisioned a real programming language that could be used by non-programmers, and for this to work it couldn’t contain the usual footguns. One could argue that he succeeded, considering how many members of the scientific community, who don’t primarily see themselves as programmers, use Python.
- William_BB 2y agoAll the answers were good, but I think this explained it the best. Thank you
- 2y ago
- djoldman 2y agoSlightly off topic: does anyone have a link to recent work done toward automatic parallelization? (Write single threaded code and have a compiler create multithreaded code) https://en.m.wikipedia.org/wiki/Automatic_parallelization_tool https://en.m.wikipedia.org/wiki/Automatic_parallelization_to...
- Vecr 2y agoRust's Rayon could probably have a mode with additional heuristics, so it wouldn't multi-thread if it guessed the memory usage increase or overhead would be too much. Not really automatic, but for some iterator chains you can just slap an adapter on. Currently you have to think and benchmark, but for some scripting type applications the increased overhead of the heuristics might be justified, as long as it was a new mode.
- buildbot 2y agoReposting this answer as it’s relevant here too - we already do this - a modern superscalar CPU is essentially an engine for turning sequential code into 6-8 (or more!) simultaneous operations that are dispatched all at once. Downstream, some 4-8 (or more!) ops are retired at once, their operations complete. This is all in a single core.
- bilsbie 2y agoI wonder if they could now add a way for the interpreter to automatically find instances where it could run your code in parallel? You’d think certain patterns could be probably safe and the interpreter could take the initiative. Is there a term for this concept?
- bmitc 2y agoNo way that's possible or even desirable with Python's OOP and mutable nature and scoping structure.
- jerf 2y agoAutomatic parallelization, as someone else linked to. It is another one of those things that many programmers ask "Why hasn't this been tried?" and the answer is, it has, many times over. It just failed so hard and so fast you've never heard of the results. Toy problems speed up by less than you'd hope and real code gets basically nothing. Your intuition says your code is full of parallelization opportunities; your intuition turns out to be wrong. A subset of the general problem that even very experienced developers still never get great at knowing how code will perform without simply runninga profiler. It has failed hard and fast in languages much friendlier to the process than Python. Proving something is truly parallel-safe in Fortran is hard enough. Proving it in Python is effectively impossible, you just don't know when something is going to dynamically dynamic the dynamics on you.
- biorach 2y ago> you just don't know when something is going to dynamically dynamic the dynamics on you. I'm going to use that!
- buildbot 2y agoI’ll take a different tact than previous answers and say we already do this - a modern superscalar CPU is essentially an engine for turning sequential code into 6-8 (or more!) simultaneous operations that are dispatched all at once. Downstream, some 4-8 (or more!) ops are retired at once, their operations complete. This is all in a single core.
- bilsbie 2y agoThis sounds silly but I’ve actually turned off garbage collection in short running, small memory programs and gotten a big speed boost. I wonder if that’s something they could automate? I’m sure there are some weird risks with that. Maybe a small program ends up eating all your memory in some edge case?
- theossuary 2y agoYou'd run into the halting problem. Maybe for some small subset of programs it'd be possible to prove a short runtime, but in general it wouldn't be, so this type of automation wouldn't be impossible. It sounds like maybe you want GCs to be very tunable? That way, developers and operators can change how it runs for a given workload. That's actually one of the (few) reasons I like Java, its ability to monitor and tune its GC is awesome. No one GC is going to be optimal for all workloads/usages. But it seems like the prevailing thought is to change the code to suit the GC where absolutely necessary, instead of tuning the GC to the workload. I'm not sure why that is?
- Arch-TK 2y agoReliable implementation most likely involves solving the halting problem.
- jordan_bonecut 2y agoDisagree, there are practical trivial subsets of the halting problem to which I imagine many short-running scripts would conform.
- Arch-TK 2y agoMost short running scripts call into the standard library or into other packages. I think the trivial subset is too small to bother with such an optimisation.
- tln 2y agoTurn on GC after the first sbrk
- geor9e 2y agois 3.13 bigger than 3.9
- 01HNNWZ0MV43FF 2y agoOh it's like the rhyme "Jack and Jill went up the hill". I spent all day not knowing whether "up the hill" meant they shipped or didn't ship. So they shipped, right? Or they shipped a JIT but removed the GIL?
- debo_ 2y agoWhat an incredible title.
- ossusermivami 2y agoIs it related to the mojo language work? would that affect how they track the language features?