[HN Gopher] What's up, Python? The GIL removed, a new compiler, ...
___________________________________________________________________
What's up, Python? The GIL removed, a new compiler, optparse
deprecated
Author : BiteCode_dev
Score : 94 points
Date : 2023-07-30 19:32 UTC (3 hours ago)
(HTM) web link (www.bitecode.dev)
(TXT) w3m dump (www.bitecode.dev)
| mkoubaa wrote:
| And alternative C APIs are being proposed, which is as exciting
| as all of the above
| fbdab103 wrote:
| Still not encouraged by the no-GIL, "We don't want another Python
| 2->3 situation", yet very little proffered on how to avoid that
| scenario. More documentation on writing thread-safe code,
| suggested tooling to lint for race conditions (for whatever it is
| worth), discussions with popular C libraries, dedicated support
| channels for top tier packages, what about the enormous long-tail
| of abandoned extensions which still work today, etc.
| doctoboggan wrote:
| The big and obvious difference is that all the GIL vs no-GIL
| stuff happens in the background and your average python dev can
| just ignore it if they want to. The interpreter will note if
| you have C extensions that don't opt in to no-GIL and then will
| give you the GIL version.
|
| This is _very_ different to the 2-to-3 transition where
| absolutely every single person, even those who couldn't care
| less, had to change their code if they wanted to use python 3.
| threatripper wrote:
| I was assuming that no-GIL will only be enabled if all imported
| libraries support it. That means that they are marked as no-GIL
| ready and otherwise the import would throw an exception. Not
| sure how it is implemented now but that sounded very reasonable
| to me. The no-GIL compatible code would start with the core
| libraries and then expand from that. Using legacy libraries
| just means that you have to revert back to GIL-mode. Any no-GIL
| enabled library should 100% still function in GIL-mode, so I
| don't expect the Python 2->3 transition situation to repeat.
| LexiMax wrote:
| In a past life I hacked on PHP for a living, and in the time it
| took Python 2 to ride off into the sunset, PHP got two major
| migrations under its belt in 5.2 to 5.3, and then again 5.6 to
| 7.0.
|
| It was amazing to see the contrast between the two languages.
| PHP gave you plenty of reasons to upgrade, and the amount of
| incompatible breaking changes was kept to a minimum, often
| paired with a way to easily shim older code to continue
| working.
|
| I really hope to see no-GIL make it into Python, but in the
| back of my mind I also worry about what lessons were learned
| from the 2 to 3 transition. Does the Python team have a more
| effective plan this time around?
| charrondev wrote:
| I've taken an application codebase from PHP 5.3 to 8.2 now
| and it was relatively easy the whole way.
|
| The real key to minimize the pain was writing effective
| integration tests with high coverage. We didn't have a good
| test suite to start but once we added some utilities to
| easily call our various endpoints (and internal API client if
| you will) and make assertions about the coverage came
| quickly.
|
| Popular frameworks like Laravel offer such test utilities out
| of the box now.
|
| That combined with static analysis tools like psalm make it
| so we can fearlessly move past major upgrades.
|
| One thing I was surprised at was just how much crap PHP
| allowed with just a notice (not even a warning for a long
| time). A lot of that stuff still works (although over time
| some notices have progressed to warnings or errors
| gradually). We have our test suite convert any notices or
| warnings to exceptions and fail the test case.
| cvnmalk wrote:
| Which, except for optparse, was all on the front page yesterday.
| So optparse is deprecated. More work I guess apart from auditing
| extensions for threading.
|
| Life is great in the Python treadmill.
| devwastaken wrote:
| This is exactly what I have been looking forward to. Allow me to
| do no-gil, let me the developer make that choice. There are
| issues with that certainly, but I am conscious of this fact and
| given an analysis of no-gil benefits it is significantly more
| beneficial to have no-gil for certain use cases.
|
| One of the most significant of these cases to me is threading
| outside an Operating system context. What if I want to use both
| of the cores to a Cortex M0? Multiprocessing can't help me, there
| are no processes. If I need locking, I will impliment it using
| the platform I have available to me.
|
| The second is the fact that CPU's are increasingly scaling in
| core count. When I have to use multiprocessing the program
| becomes far more complex than one would expect. Why am I doing
| message passing and shared memory when the OS and CPU supplies
| better tools already? It also pollutes the process ID's. Imagine
| if we built every application in Python - there would be hundreds
| of thousands of individual processes all to use multiple cores.
| Because this is a problem mostly unique to python we often end up
| having to build applications in other languages that otherwise
| would have been better in Python.
|
| I want a world where I can say "just use python" to almost
| anything. Telling new coders to drop their favorite language and
| use any other language to get the result they want immedietely
| kills the innovation they are working on. Instead of spending
| time creating the idea, they're spending time learning a
| languages I believe are unnecessary.
| andrewstuart wrote:
| From reading the thread on HN the other day, it sounds like
| removing the GIL isn't really of much value. Maybe for somewhat
| obscure multithreading cases.
|
| Is that right?
| Jtsummers wrote:
| That discussion was amusing. Removing the GIL opens up the
| possibility of actually getting a real performance benefit from
| multithreaded Python code. That's the value. Given every modern
| desktop and server is multicore (and increasingly getting to
| tens of cores if not hundreds), multithreading in Python
| unhampered by the GIL will be a useful thing. And no,
| multiprocessing is not a good alternative to multithreading.
| It's just an alternative, but it's slower, uses more memory,
| and coordination between processes is slower than between
| threads.
| oivey wrote:
| That was the opinion of a handful of vocal posters. The
| overhead of using multiprocessing and/or some network service
| is extremely high for a lot of applications.
| FartyMcFarter wrote:
| I would disagree with that.
|
| The GIL means you can't use Python multithreading in order to
| take advantage of more CPU time by parallelism. Obviously
| getting rid of the GIL makes that a real option, just as it is
| in other languages.
| squeaky-clean wrote:
| Currently, yes that's kind of true. But it's really only
| considered obscure because the GIL makes it so you either have
| to do some weird non thread pattern or go with a different
| language, and people often go with a different language.
|
| Kind of a Catch-22 of "Well no one uses it that way, so why
| should we make it possible to use it that way? Well, no one
| uses it that way because it's impossible to use it that way"
| kukkamario wrote:
| Well Python doesn't really do proper multi-threading currently
| thanks to GIL blocking any additional execution threads. So
| removing it would enable making Python code that is actually
| multi-threaded without resorting to extra processes and their
| overhead.
|
| So if you are writing small single process Python script then
| removing GIL shouldn't really change much. If you are doing
| some heavier computing or eg. running server back-end, then
| there are significant performance gains available with this
| change.
| umanwizard wrote:
| You don't have to use separate processes to get the benefit
| of multithreading in Python today -- you can also call into a
| library written in native code that drops the GIL (e.g. Numpy
| or Pytorch).
| cpgxiii wrote:
| That only works in some cases, if the boundary between
| Python and native code is absolute. In many cases users
| want to extend/configure the behavior of that native code,
| e.g. through callbacks or subclassing, and the GIL makes
| the behavior prohibitively slow (needing to lock/unlock to
| serialize at any of these potential Python<->native
| boundaries) or unsafe (deadlocks/corruption if the GIL
| isn't handled).
|
| There's a lot of C++ code bound in python (e.g. via
| pybind11) where the GIL currently imposes a hard bound on
| how users can employ parallelism, even in "nominally"
| native code.
| masklinn wrote:
| Even then the GIL can cause issues, concerns of PyTorch are
| specifically one of the motivations of the PEP, and one of
| the reasons Meta / FB really really wants this:
|
| > In PyTorch, Python is commonly used to orchestrate ~8
| GPUs and ~64 CPU threads, growing to 4k GPUs and 32k CPU
| threads for big models. While the heavy lifting is done
| outside of Python, the speed of GPUs makes even just the
| orchestration in Python not scalable. We often end up with
| 72 processes in place of one because of the GIL. Logging,
| debugging, and performance tuning are orders-of-magnitude
| more difficult in this regime, continuously causing lower
| developer productivity.
| umanwizard wrote:
| I feel like orchestrating thousands of GPUs is such a
| niche use case that it's fair to expect the people
| wanting to do it to learn a more suited language, rather
| than ruining Python for everyone else.
| sidlls wrote:
| It's (likely) much less expensive (in many ways, not just
| financially) to employ a larger number of python
| programmers than a smaller number of them skilled in a
| language more appropriate for the use case. Engineer
| flexibility, salary costs, maintenance/correctness
| concerns with implications for development time, etc.,
| are all factors here. The technical choice of "python or
| not python" is rarely the only--or even most important--
| choice to make.
| csmpltn wrote:
| There are plenty of other Python VMs that don't have a GIL and
| can be used already today, out of the box (examples include
| Jython and IronPython). Despite that fact - CPython remains the
| most popular Python VM out there (it utilizes a GIL).
|
| Instead of waiting for the GIL to be removed out of CPython -
| take your fancy Python code and just run it using a different
| VM. It's literally as simple as that.
|
| If the GIL was such a bottleneck as people make it out to be -
| people would move off of CPython a long time ago. But they
| won't, despite having the options. This only serves to prove
| that 95%+ of the workflows people build with Python can be
| satisfied regardless of GIL, often using some of the other
| parallelism mechanisms available in Python today
| (multiprocessing, asyncio, etc).
|
| Most of the stuff people build with Python are CRUD apps,
| Jupyter notebooks, automations, tinkering, small hacks, etc. If
| you're okay with not utilizing all of your 64k CPUs at home -
| Python's multiprocessing and asyncio libraries should serve you
| just fine.
|
| The whole GIL/No-GIL conversation is a complete waste of time
| and a distraction. People have all the options they need
| already here and now - but slinging crap at eachother over an
| issue tracker is so much fun that people can't help it.
| oivey wrote:
| People stay on CPython due to the performance of C extensions
| and the vast ecosystem based on them. The fact that people
| have stuck with CPython isn't at all evidence that they like
| the GIL or that it doesn't lead to significant technical
| problems.
|
| Besides the C extension issue, Jython is based on Python 2.7
| and IronPython appears to be on 3.4. These aren't serious
| alternatives.
| quickthrower2 wrote:
| Would a large codebase seemlessly run on another interpreter?
| bafe wrote:
| Not likely, particularly if you depend on modules written
| (partly) in C like numpy/scipy etc
| quickthrower2 wrote:
| I just did some searching around PyPy and that seems to
| be the case. IronPython is out of support now but the
| looks of it. Which is a shame. I heard of it 10 years
| ago, but assumed it was some "Microsoftized Python" and
| not at all a compatible thing :-)
| actionfromafar wrote:
| If you have a lot of code, there's plenty of Internet drama
| to be had in moving to another runtime, too.
| masklinn wrote:
| > Maybe for somewhat obscure multithreading cases.
|
| They're only "somewhat obscure" because currently you can't do
| it at all, so you don't do it and you do something else: it's
| of value for any case where you're multithreading for
| computational parallelism (as opposed to IO concurrency). The
| PEP also outlines a bunch of other situations where using
| process-based parallelism is problematic:
| https://peps.python.org/pep-0703/#motivation
|
| With the proviso that while it will work for all pure-python
| code out of the box[0] loading any _native_ package which has
| not opted into "no gil" mode will re-enable the GIL:
| https://peps.python.org/pep-0703/#py-mod-gil-slot
|
| [0] modulo new race conditions where the code relied on the GIL
| for correctness, something which isn't _strictly_ correct and
| can already break when the scheduler logic changes
| [deleted]
| Spivak wrote:
| Right now multi-threading makes your Python code (that isn't
| really C) slower. The only real use of it is time slicing so
| you don't starve more important code like the web server or UI
| thread. You still have all the concurrency issues because your
| threads can still still be paused and resumed at arbitrary
| times. It does allow some operations in Python to be atomic but
| I, maybe naively, assume that those cases will be guarded by
| new, not whole interpreter, locks.
|
| With no-gil your multithreading code can, with no change to
| your code, take advantage of multiple cores and actually speed
| up your program. If
| wmwmwm wrote:
| Historically I've written several services that load up some big
| datastructure (10s or 100s of GB), then expose an HTTP API on top
| of it. Every time I've done a quick implementation in Python of a
| service that then became popular (within a firm, so 100s or 1000s
| of clients) I've often ended up having to rewrite in Java so I
| can throw more threads at servicing the requests (often CPU
| heavy). I may have missed something but I couldn't figure out how
| to get the multi-threaded performance out of Python but of course
| no-GIL looks interesting for this!
| wood_spirit wrote:
| That's right.
|
| In the past, for read-only data, I've used a disk file and
| relied on the the OS page cache to keep it performant.
|
| For read-write, using a raw file safely gets risky quickly. And
| alternative languages with parallelism runs rings around
| python.
|
| So getting rid of the GIL and allowing parallelism will be a
| big boon.
| Waterluvian wrote:
| No, that's about right.
|
| The response, which isn't technically wrong, is "unless you're
| CPU bound, your application should be parallized with a WSGI.
| You shouldn't be loading all that up in memory so it shouldn't
| matter that you run 5 Python processes that each handle many
| many concurrent I/O bound requests."
|
| And this is kinda true... I've done it a lot. But it's very
| inflexible. I hate programming architectures/patterns/whatnot
| where the answer is "no you're doing it wrong. You shouldn't be
| needing gigs of memory for your web server. Go learn task
| queues or whatever." They're not always wrong, but very
| regularly it's the wrong time to worry about such "anti
| patterns."
| rrishi wrote:
| I am not too deeply experienced with Python so forgive my
| ignorance.
|
| But I am curious to understand why you were not able to utilize
| the concurrency tools provided in Python.
|
| A quick google search gave me these relevant resources
|
| 1. An intro to threading in Python
| (https://realpython.com/intro-to-python-
| threading/#conclusion...)
|
| 2. Speed Up Your Python Program With Concurrency
| (https://realpython.com/python-concurrency/)
|
| 3. Async IO in Python: A Complete Walkthrough
| (https://realpython.com/async-io-python/)
|
| Forgive me for my naivety. This topic has been bothering me for
| quite a while.
|
| Several people complain about the lack of threading in Python
| but I run into plenty of blogs and books on concurrency in
| Python.
|
| Clearly there is a lack in my understanding of things.
| Jtsummers wrote:
| Re (3): asyncio does not give you a boost for CPU bound
| tasks. It's a single-threaded, cooperative multi-tasking
| system that can (if you're IO bound) give you a performance
| boost.
| aardvark179 wrote:
| Threading in Python is fine if your threads are io bound or
| spend their time in a C extension which releases the GIL, if
| you are bound then the GIL means effectively one thread can
| run at a time and you gain no advantage from multiple
| threads.
| teraflop wrote:
| The whole point of the GIL is that even if you use Python's
| threading or asyncio, you don't get any benefits from scaling
| beyond a single CPU core, because all of your threads (or
| coroutines) are competing for a single lock. They run
| "concurrently", but not actually in parallel. The pages you
| linked explain this in more detail.
|
| In theory, multiprocessing could allow you to distribute the
| workload, but in a situation like OP describes -- just
| serving API requests based on a data structure -- the
| overhead of dispatching requests would likely be bigger than
| the cost of just handling the request in the first place. And
| your main server process is still a bottleneck for actually
| parsing the incoming requests and sending responses. So
| you're unlikely to see a significant benefit.
| [deleted]
| wmwmwm wrote:
| You can throw python threads at it, but if each request
| traverses the big old datastructure using python code and
| serialises a result then you're stuck with only one live
| thread at a time (due to the GIL). In Java it's so much
| easier especially if the datastructure is read only or is
| updated periodically in an atomic fashion. Every attempt to
| do something like this in python has led me to having to
| abandon nice pythonic datastructures, fiddle around with
| shared memory binary formats, before sighing and reaching for
| java! Especially annoying if the service makes use of handy
| libraries like numpy/pandas/scipy etc!
| threatripper wrote:
| You have a single big data structure that can't be shared
| easily between multiple processes. Can't you use
| multiprocessing with that? Maybe mapping the data structure to
| a file and mmapping that in multiple processes? Maybe wrapping
| the whole thing in database instead of just using one huge
| nested dictionary? To me multi-threading sounds so much less
| painful than all the alternatives that I could imagine. Just
| adding multi-threading could give you >10x improvement on
| current hardware without much extra work if your data structure
| plays nice.
| kroolik wrote:
| One annoying part with multiprocessing in Python is that you
| could abuse the COW mechanism to save on loading time when
| forking. But Python stores ref counters together with objects
| so every single read will bust your COW cache.
|
| Now, you wanted it simple, but got to fight with the memory
| model of a language that wasn't designed with performance in
| mind, for programs whose focus wasn't performance.
| dathinab wrote:
| > You have a single big data structure that can't be shared
| easily between multiple processes. Can't you use
| multiprocessing with that? Maybe mapping the data structure
| to a file and mmapping that in multiple processes? Maybe
| wrapping the whole thing in database instead of just using
| one huge nested dictionary?
|
| ton of additional complexity, not worth it for many use-cases
| and anything on the line of "using multiple processes or
| threads to increase python performance" does have (or at
| least did have) quite a bunch of additional foot guns in
| python
|
| In that context porting a very trivial ad-hoc application to
| Java (or C# or Rust, depending on what knowhow exist in the
| Team) would faster or at least not much slower to do. But it
| would be reliable estimable by reducing the chance for any
| unexpected issues, like less perf then expected.
|
| Basically the moment "use mmap" or "use multi-processing" is
| a reasonable recommendation for something ad-hocish there is
| something rally wrong with the tools you use IMHO.
| threatripper wrote:
| The use case I'm thinking about is very simple: One big
| data structure that is mostly read from and sometimes
| written to. Use a single mutex with a shared lock for
| reading and an exclusive lock for writing. Then the readers
| are safe and would only block during updates when one
| writer is active. Everything else beside the data structure
| can be per-thread and wouldn't interfere.
|
| The problem why we wouldn't want to port this application
| to another language is 100k lines of existing code that is
| best written in Python and no resources to rewrite all
| that.
| ggm wrote:
| > _Basically the moment "use mmap" or "use multi-
| processing" is a reasonable recommendation for something
| ad-hocish there is something rally wrong with the tools you
| use IMHO._
|
| Hmm. So you're saying only languages which bury lock and
| mutex over shared data are appropriate to use for async
| parallelism over shared data? Because calling explicit
| lock() and releae() isn't that hard. However it does incur
| a function call overhead. I suppose some explicit in
| language support could minimise that partially.
| strictfp wrote:
| My tip for this is Node.js and some stream processing lib like
| Highland. You can get _ridiculous_ IO parallelism with a very
| little code and a nice API.
|
| Python just scales terribly, no matter if you use multi-process
| or not. Java can get pretty good perf, but you'll need some
| libs or quite a bit of code to get nonblocking IO sending
| working well, or you're going to eat huge amounts of resources
| for moderate returns.
|
| Node really excels at this use case. You can saturate the lines
| pretty easily.
| xcv123 wrote:
| > I may have missed something
|
| You did not miss anything. The GIL prevents parallel multi
| threading.
| jeremycarter wrote:
| Similar experience. Even with multi process and threads python
| is slow, very slow. Java, Go and .NET all provide a very
| performant out of box experience.
| brightball wrote:
| This is actually one of the reasons I was drawn to Ruby over
| Python. Ruby also has the GIL but jRuby is an excellent option
| when needed.
| antod wrote:
| I wonder what lead to JRuby attracting support while Jython
| not? I know the Jython creator went on to other things (was
| it eg IronPython for dotnet?). I suppose it was the inverse
| with dotnet - eg IronPython surviving while IronRuby seems
| dead.
|
| Is it just down to corporate sponsorship?
| nwallin wrote:
| > I may have missed something but I couldn't figure out how to
| get the multi-threaded performance out of Python
|
| Multiprocessing. The answer is to use the python
| multiprocessing module, or to spin up multiple processes behind
| wsgi or whatever.
|
| > Historically I've written several services that load up some
| big datastructure (10s or 100s of GB), then expose an HTTP API
| on top of it.
|
| Use the python multiprocessing module. If you've already
| written it with the multithreading module, it is a drop in
| replacement. Your data structure will live in shared memory and
| can be accessed by all processes concurrently without incurring
| the wrath of the GIL.
|
| Obviously this does not fix the issue of Python just being
| super slow in general. It just lets you max out all your CPU
| cores instead of having just one core at 100% all the time.
| godelski wrote:
| This exists, but one of two things happen, which still
| significantly slows things down. Either 1) you generate
| multiple python instances or 2) you push the code to a
| different language. Both are cumbersome and have significant
| effects. The latter is more common in computational libraries
| like numpy or pytorch, but in this respect it is more akin to
| python being a wrapper for C/C++/Cuda. Your performance is
| directly related to the percentage of time your code spends
| within those computation blocks otherwise you get hammered by
| IO operations.
| hanniabu wrote:
| Will writing multithreaded code become easier? Or will the
| developer UX remain the same?
| dpedu wrote:
| The opposite, writing multithreaded code will get harder
| because you'll likely need to handle concurrency issues
| yourself that the GIL previously avoided. But, the tradeoff is
| that multithreaded programs could now actually achieve
| multithreaded performance gains.
| bvrmn wrote:
| A single Go thread still replaces 10 Python threads, speaking
| very roughly. It's a quite particular narrow set of problems
| noGIL would solve.
| Jtsummers wrote:
| > writing multithreaded code will get harder because you'll
| likely need to handle concurrency issues yourself
|
| I'd phrase this differently: Writing _correct_ multithreaded
| code will be just as challenging (or not, depending on the
| person and their comfort with concurrent and parallel code
| development) as before, but now you won 't be able to get
| away with _sloppy_ multithreaded code that relied on the GIL
| to not break.
| fbdab103 wrote:
| It was correctly written to the invariant promises of the
| platform at the time. If Python is altering the deal, that
| does not suddenly make the library writer at fault.
| oivey wrote:
| There seems to be some confusion here. The GIL is not an
| invariant of Python that makes your code thread safe.
| Python is not altering the deal. You can still use
| threads to write concurrent code in Python today, and
| you'll still run into all of the classic concurrency
| related bugs.
|
| People just mostly don't bother writing threaded code in
| Python today because it provides no performance benefit.
| That may change, and it very likely will expose many
| threading bugs that already exist in many libraries that
| just have never been found.
| BiteCode_dev wrote:
| Summary:
|
| - Python without the GIL, for good
|
| - LPython: a new Python Compiler
|
| - Pydantic 2 is getting usable
|
| - PEP 387 defines "Soft Deprecation", getopt and optparse soft
| deprecated
|
| - Cython 3.0 released with better pure Python support
|
| - PEP 722 - Dependency specification for single-file scripts
|
| - Python VSCode support gets faster
|
| - Paint in the terminal
| bigbillheck wrote:
| Python's been a little too happy to hard-deprecate things for my
| liking, so this soft-deprecation sounds pretty good.
| schemescape wrote:
| The title says "GIL removed", but the article says "This means in
| the coming years, Python will have its GIL removed."
|
| I'm assuming the article is correct and the GIL has not been
| removed yet (but there is a plan to remove it in the future). If
| that's not the case, please correct me!
| Jtsummers wrote:
| It's not been removed. PEP 703 has been accepted and they've
| got a path forward to no-GIL. No-GIL versions will be available
| as experimental versions starting with 3.13 or 3.14.
|
| https://peps.python.org/pep-0703/
|
| https://discuss.python.org/t/a-steering-council-notice-about...
___________________________________________________________________
(page generated 2023-07-30 23:00 UTC)