Live data from Hacker News

A viable solution for Python concurrency

lwn.net

141–150 of 366 posts

Re: A viable solution for Python concurrency

#141
post #132
post #82

Earlier quoted context omitted.

Has it since been fixed?

Probably not. CPickle is famously shunned by anyone who has to do serious, performance-critical serialization/deserialization.

I was curious, and an issue that fits the description was fixed in Py 3.7.x here: https://bugs.python.org/issue34572 but other threading bugs remain: https://bugs.python.org/issue38884

Re: A viable solution for Python concurrency

#142

This may be a silly question, but if you really need concurrency, why not use a language that's built for concurrency from the ground up instead? Elixir is a great example.

I rarely need concurrency, and do a lot of Python because it's what all my dependencies are written in. But sometimes, I find myself bottlenecked on a trivially parallelizable operation. In the state (my dependecies are in Python, I have a working Python implementation), there's no way in hell that (rewrite my dependencies in Elixir, rewrite my code in Elixir) is a sensible next move.

Re: A viable solution for Python concurrency

#143

If this effort succeeds (and I hope it does) now Python developers will need to contend with the event-loop albatross of asyncio and all of its weird complexity. In an alternate Python timeline, asyncio was not introduced into the Python standard library, and instead we got a natively supported, robust, easy-to-use concurrency paradigm built around green/virtual threading that accommodates both IO and CPU bound work.

Yes, I have a big sense of tragedy about Python 3. Python should run on something like (or maybe the actual) Erlang BEAM with lightweight isolated processes. All my threaded Python code is written using that style anyway (threads communicating through synchronized queues) and I've almost never needed traditional shared mutable objects. Maybe completely never, but I'm not sure about a certain program any more. Added:…

You are likely being downvoted because most claims about the pain of a Python 3 transition are inflated/hyperbole.

It took less than a day to migrate all my code to Python 3. And by "less than a day" I mean "less than 2 hours". Granted, bigger projects would take longer, but saying stuff like "10+ years of pain" is ridiculous. Probably less than 1% of projects had serious issues with the migration. We just hear of a few popular ones that had some pain and assume that was representative.

Re: A viable solution for Python concurrency

#144
post #2

> This "optimization" actually slows single-threaded accesses down slightly, according to the design document, but that penalty becomes worthwhile once multi-threaded execution becomes possible. My understanding was that CPython viewed any single-threaded performance regression as a blocker to GIL-removal attempts, regardless of if other work by the developer has sped up the interpreter? This article seems to somewha…

C extensions can continue to be supported. Said extensions already explicitly lock/release the GIL, so to keep things backwards compatible it would be perfectly fine if there was a GIL that existed strictly for C extension compatibility.

Re: A viable solution for Python concurrency

#145
post #3

"The biggest source of problems might be multi-threaded programs with concurrency-related bugs that have been masked by the GIL until now."

> concurrency-related bugs that have been masked by the GIL

Yeah... could phrase this as "All programs written with the assumption of a GIL are now broken" instead. Wish they had done this as part of the breaking changes for python 3, I guess they'll have to wait for Python 4 for this?

Re: A viable solution for Python concurrency

#146
post #79
post #44

Earlier quoted context omitted.

I like this idea. In fact another possibility is to have a thread-local reference count for each thread that uses the object which can use fast non-atomic operations, and then each thread can use a shared atomic reference count, that counts how many threads use the object. When each thread-local count goes to zero, the shared count is decremented by one. This way, if an object is created in one thread and transferred…

How would the storage be laid out? With the proposed scheme, there are two counters (and, i assume, the ID of the owning thread), so a small fixed-size structure, which can sit directly in the object header. With your scheme, you need a variable and unbounded number of counters. Where would they go?

Maybe each thread could have a mapping storing the number of references held (in that thread) for each object? This way only the atomic refcount has to be in the object header. Also I don’t think there would be an owning thread at all with this idea, so no ID needed.

Re: A viable solution for Python concurrency

#147

I dont know about others, but I really enjoy content about the Python GIL. Its a fascinatingly complex problem.

For a minute I thought I finally found someone else who likes the GIL, but then you said content about. Programs that just divide up work across processes are much easier to write without introducing obscure bugs due to the lack of atomicity. I'm definitely excited for a GIL-less python, even if it's a rare scenario where it makes sense to try to do performant code in python in the first place rather than offloading a few lines to another language to be fast, but I am a bit afraid that people (particularly beginner programmers) will grab this with too many hands. Having also seen recommendations for this-or-that threading method going around in other languages, threads are recommended really much more often than where it makes sense and beginners won't have a comparative experience yet of writing multi-process code instead.

That said, I am also always interested in GIL-related content like this! Loved the article.

Re: A viable solution for Python concurrency

#148

Earlier quoted context omitted.

Python Zen = one obvious way to do it. Having a bunch of very different ones, each with serious disadvantages, is a bad look.

It's a technical thread, not a political one. If you were so sure of your argument, you wouldn't use a throwaway. Besides, it's weird, like saying we should not have int, float and complex, there should be one way to do it. Just because those are 3 numbers doesn't mean they don't have each their own specific benefit.

int, float, and complex are for different purposes. async and threads paper over each others' weaknesses, instead of fixing the weaknesses at the start. Async itself is an antipattern (technical opinion, so there) but Python uses it because of the hazards and high costs of threads. Chuck Moore figured out 50 years ago to keep the async stuff out of the programmer's way, when he put multitasking into Polyforth, which ran on tiny machines. Python (and Node) still make the programmer deal with it.

If you look at Haskell, Erlang/Elixir, and Go, they all let you write performant sequential code by pushing the async into the runtime where the programmer doesn't have to see it. Python had an opportunity to do the same, but stayed with async and coroutines. What a pain.

Re: A viable solution for Python concurrency

#150

Earlier quoted context omitted.

>Edit: I probably should have explicitly noted that, as jetrink points out, the object is initialized with a atomic refcount of one (the "local refcount is nonzero" reference), and destroyed when the atomic refcount is one and to-be-decremented, so a purely local object never has atomic writes. I think you're under the impression that the refcount would only ever need to be incremented if the object was shared to ano…

> Even objects that never leave their creator thread will be likely to have their reference count incremented and decremented a few times over their life. I think you're under the impression that there's only one refcount. The point of the original design (and this one) is that there are two refcounts: one that's updated only by the thread that created the object, and therefor doesn't need to use slow atomic accesses…

Oh, I misunderstood you then. I thought you were trying to get rid of the local refcount and make the atomic one handle its job too, but what you're suggesting is a possible simplification of the logic that detects when it's time to destroy the object. That makes sense, just seems more minor than I thought you were going at and I guess I missed it.
Post reply on HN