13 ms·
I worked in Python for years and while I suppose I'm glad for any improvement, I have never understood the obsession with true multi-threading. Languages are ab
by aeturnum 5y ago
I worked in Python for years and while I suppose I'm glad for any improvement, I have never understood the obsession with true multi-threading. Languages are about trade-offs and Python, again and again, chooses flexibility over performance. It's a good choice! You can see it in how widely Python is used and the diversity of its applications.
Performance doesn't come from any one quality, but from the holistic goals at each level of the language. I think some of the most frustrating aspects from the history of Python have been when the team lost focus on why and how people used the language (i.e. the 2 -> 3 transition, though I have always loved 3). I hope that this is a sensible optimization and not an over-extension.
- lmilcin 5y agoThe issue is people try to get throughput from Python and GIL stands in the way. A lot of people learned Python and now want to use it for something more serious even if Python was not designed for it. I work on high volume backends (like million TPS on a single node) and Python for me is just a toy language. But I see no reason to purposefully inconvenience these people by keeping GIL if it can be removed.
- emerged 5y agoFrom my perspective as a huge Python fan, efficient multithreading is simply the only major thing missing from the language. I would still use C/C++/assembly for bleeding edge performance needs, but efficient multithreading in Python would have me reaching for alternatives far less often. Basically I love peanut butter ice cream (Python) I’d just like it even more with sprinkles.
- heavenlyblue 5y agoPython uses a lot of memory, multi-threading makes you have only one process sharing all the same memory.
- klyrs 5y agoLosing the GIL strictly makes the language strictly more flexible. Previous GILectomies tanked performance to an unacceptable degree. In single-threaded code, this one is a moderate performance improvement in some benchmarks, and a small detriment in others -- which is about as close to perfect as one could expect from such a change. That's why people are excited about it. At a higher level, Python is getting serious about performance. But this gives both flexibility and performance.
- aeturnum 5y agoYah, that's definitely the future I'm hoping for. What I am worried about are the kind of transition issues I mentioned. Python 2 -> 3 strictly made the language more flexible too - but the Python ecosystem is about existing code almost more than the language and I worry that we could find similar problems here. Potential for plenty of growing pains while chasing relatively small gains.
- ynik 5y agoIn the company I'm working for, we had to spent more engineer time on GIL workarounds (dealing with the extra complexity caused by multiprocessing, e.g. patching C++ libraries to put all their state into shared memory) than we needed for the Python 2 -> 3 migration. And we've only managed to parallelize less than half of our workload so far. Even if this will be a major breaking change to Python, it'll be worth it for us.
- gshulegaard 5y agoCall me optimistically skeptical. I share similar reservations about GIL obsession with the original comment author, but if this is true: > The overall effect of this change, and a number of others with it, actually boosts single-threaded performance slightly—by around 10% Then it sounds like having the cake and eating it too (optimism). Although my experience keeps nagging at me with, "there is not such thing as a free lunch" (skepticism).
- comex 5y agoPerhaps better coverage on LWN: https://lwn.net/Articles/872869/ https://lwn.net/Articles/872869/ The no-GIL version is actually about 8% slower on single-threaded performance than the GIL version, but the author bundled in some unrelated performance improvements that make the no-GIL version overall 10% faster than today's Python.
- qeternity 5y agoThis suggests that the unrelated patches improve perf by 20% (0.92 * 1.20 ~= 1.10) I would love to be proven wrong but I am skeptical.
- amelius 5y ago> Performance doesn't come from any one quality, but from the holistic goals at each level of the language. It starts to become an issue when you have built a few well-performing subsystems and now want them to run together and interact. With the GIL, your subsystems are suddenly not performing as well anymore. Without the GIL, you can still get good performance (within limits of course). Performance referring here to throughput and/or latency (responsiveness).
- tester756 5y ago>again and again, chooses flexibility over performance. It's a good choice! You can see it in how widely Python is used and the diversity of its applications. What does it mean? how is python different here than Java/C#?
- aeturnum 5y agoI mean, you can modify Python code at runtime if you like. This has a good overview of all the nonsense happening under the hood: http://jakevdp.github.io/blog/2014/05/09/why-python-is-slow/ http://jakevdp.github.io/blog/2014/05/09/why-python-is-slow/
- xmcqdpt2 5y agoThis is my main issue with python. The whole GIL thing is basically necessary because of Python's heavily dynamic model, which is almost always used improperly. Mypy and other static analysis tools are becoming more common in part because IMO they basically require you to stop and think about your "Pythonic" dynamic patterns (containers of mixed element types, duck typing of function arguments, mutable OOP etc.), and often realize that they are a bad idea. So in some way we are hampering multithreading to support programming constructs that are mostly used to make python flavoured spaghetti, especially in the hands of beginners and non-programmers who are encouraged to learn Python... I'm not sure Python is fixable at this point. Oh well.
- cma 5y agoThere are 64-core, 128-thread prosumer CPUs now and it is only going to go higher. At some point it just becomes necessary.
- turminal 5y agoWhat does a 128 thread python app do better than 128 single threaded ones?
- jhoechtl 5y agoOS overhead of 128 processes is higher than scheduling 128 tasks. Varies from os to os, but it's especially bad on Windows.
- turminal 5y agoYeah, I know about that argument but it just doesn't make sense to me. Removing the GIL means that 1) you make your language runtime more complex and 2) you make your app more complex. Is it truly worth it just to avoid some memory overhead? Or is there some other windows specific thing that I'm missing here?
- dragonwriter 5y ago> Yeah, I know about that argument but it just doesn't make sense to me. Removing the GIL means that 1) you make your language runtime more complex and 2) you make your app more complex. #2 need not be true; e.g., the approach proposed here is transparent to most Python code and even minimized impact on C extensions, still exposing the same GIL hook functions which C code would use in the same circumstances, though it has slightly different effect.
- lmm 5y agoIt doesn't have to be. On Linux 2.4 (pre-NPTL) processes and threads were represented exactly the same way.
- Redoubts 5y ago
- darthrupert 5y agoLack of multithreading can easily be a win for a language. A tiny subset of problems really needs it these days and for everything else it's a potential way to either screw things up or make them way more complicated that needs to be.
- cm2187 5y ago> A tiny subset of problems like processing web requests?
- darthrupert 5y agoNo, that doesn't require multithreading at all.
- dkersten 5y agoDoesn't require, sure. Nothing "requires" multithreading. It may benefit from it, though, since threads are lower overhead (context switching and memory) than processes. If you have any shared data, then that too may be a benefit (but I guess your point is that most web requests don't share data).
- cm2187 5y agoAlso the smaller the memory footprint, the more you live in the CPU cache.
- dkersten 5y agoTrue. A lot of people will argue that its not worth optimising for, that programmer time is more important and expensive. This may be true at the start, and is probably even worthwhile when you need to get a product out fast to test the waters in a startup, but I've worked in multiple companies that have spent significant developer time to try to reduce their cloud infrastructure costs. At this point, having your language and famework be able to make good use of the available hardware really can make a real difference to the overall performance and therefore cost, both hardware cost and engineering time to optimise it later. The productivity gap between languages that optimise for development and those that try to at least somewhat optimise for runtime really isn't that large anymore nowadays. Even modern Java is quite productive now, compared to 10 or 15 year ago. Outside of a startup trying to find product market fit building their MVP's super fast to see what works, I think its usually worth spending a bit more on up front development time, a one off cost, to reduce the recurring infrastructure cost. Of course, it takes a lot more than just a language that supports multithreading to do this, but everything the language and the libraries/frameworks you use do to help you is helpful. I'd rather have a tool that won't get in my way later, that gives me lots of room to grow when performance starts to become an issue, than one where I need to invest in significant and painful development time (based on personal experiences at least) later. This is one area where Go seems to shine, perhaps Rust too, although I have not tried any web backend dev in Rust yet so don't know how productive it would be.
- cm2187 5y agoPopularity has probably as much to do, if not more to do, with ease of access (or lack of alternative) than good design of the language. Php is equally if not more popular than python.
- aeturnum 5y agoI'm not a PHP expert, but I did not know it was also used in data science, game programming, embedded programming and machine learning as Python is. Of course they are both used for web services.
- tored 5y agoFunny thing is that PHP does not have GIL, thus it would perform better on each of those things that you list.
- antod 5y agoI thought the reason PHP doesn't have a GIL, is that out of the box, it doesn't even have threads at all? Is my PHP knowledge out of date? Is the this the current state the art: ? https://www.php.net/manual/en/parallel.setup.php https://www.php.net/manual/en/parallel.setup.php
- tored 5y agoPHP doesn’t ship with an API for creating threads, but PHP can be executed in threads depending on setup. And it does that without using a GIL, instead it internally uses something called Thread-Safe Resource Manager https://github.com/php/php-src/tree/master/TSRM https://github.com/php/php-src/tree/master/TSRM I have written about this recently https://news.ycombinator.com/item?id=28692014 https://news.ycombinator.com/item?id=28692014
- lioeters 5y agoI don't know much about it, but I've heard here and there about Swoole, a "PHP extension for Async IO, Coroutines and Fibers". > Swoole is a complete PHP async solution that has built-in support for async programming via fibers/coroutines, a range of multi-threaded I/O modules (HTTP Server, WebSockets, TaskWorkers, Process Pools) and support for popular PHP clients like PDO for MySQL, Redis and CURL. https://www.swoole.co.uk/ https://www.swoole.co.uk/
- dec0dedab0de 5y agoI agree, but I don't do anything that can be split up, and would benefit from sharing memory. That is really the only benefit of removing the GIL. Multiprocessing can do true concurrency, and so can Celery, which even allows you to use multiple computers. The only time that is a pain is when you need to share memory, or I guess maybe if you're low on resources and can't spare the overhead from multiple processes. I think a JIT would be the best possible improvement for CPython as far as speed is concerned. Though I can imagine there are plenty of people doing processor heavy stuff with c extensions that would benefit from sharing memory. So from their perspective removing the GIL would be a better improvement. So basically a JIT would help every Python program, and removing the GIL would only help a small subset of Python programs. Though I'm just happy I get to make a living using Python. Edit: This was in the back of my head, but I didn't mention it, and it would be unfair to dismiss. A JIT does slowdown startup time, so for short programs that are finished running quickly it may make things worse. Though I suspect it would be easy enough to have a value to turn off the JIT at the start of the program.
- phkahler 5y ago>> So basically a JIT would help every Python program, and removing the GIL would only help a small subset of Python programs. What if the "Global Interpreter Lock" needs to be removed for JIT? I put that in quotes to highlight it because AFAICT no compiled (or JITed) language has such a thing. I think it functions differently than regular stuff like critical sections.
- dec0dedab0de 5y agoWhat if the "Global Interpreter Lock" needs to be removed for JIT? It doesn't. PyPy has a JIT and a GIL. The JIT just compiles the byte code to native code before running, along with some tricks that are over my head. Edit: Here is PyPy's FAQ about it https://doc.pypy.org/en/latest/faq.html#does-pypy-have-a-gil-why https://doc.pypy.org/en/latest/faq.html#does-pypy-have-a-gil...
- heavyset_go 5y agoLast time I looked, Ruby had a GIL and JIT.
- m0zg 5y agoOne does not preclude another: the language can be flexible and offer higher concurrency that it does now. My workstation has 64 hyperthreads. Python can use one at a time. That's messed up since I use it as a general purpose language.
- didip 5y agoThis is because Python, by luck, ended up dominating the data science market. In this market you really want to shuffle tons of data quickly, and that’s usually achieved through parallelism. Python multiprocess library does a poor job at that.
- anthk 5y agoThat's calling C and Fortran in the background, actually.
- Mehdi2277 5y agoThat’s a workaround that is not as ergonomic as writing python more directly. The person working on this Gil project is one of the major maintainers of a key ml library. They have used c/c++ binding approach but want to make life easier and be able to multi thread directly in python.
- mechanical_bear 5y agoBy luck? I think that is a bit reductionist.
- sillysaurusx 5y agoIt wasn't entirely Python's inborn merits. For example, we don't use the best language for each task today. Instead, we use whatever language our coworkers and other companies use, which we often convince ourselves is the best language for a task. The timing was critical, and although Python may be the Facebook of languages, one can't discount that it was extraordinarily lucky for Guido to be in the precise time and place to capitalize on good design choices.
- senderista 5y agoDitto with Ruby and web dev. The language was never designed with that application in mind (and very few people used it for that when I got into Ruby around 2000). Path dependence mostly accounts for the ubiquity of Python in science and Ruby in web dev; it just as easily could have gone the other way around.
- heavyset_go 5y agoIt's because threads in Python are only really good for parallel I/O, and are ineffective for CPU bound workloads. This can be a problem for a lot of treading use cases. If I'm working on an ETL app that parses large amounts of data, either the related CPU bound tasks need to either run sequentially, call out to C extensions, or use multiple processes which incurs an overhead. It's a pain when you know threads would suit your use case well, but the threading implementation in the language you're working in isn't up to the task.
- Godel_unicode 5y agoWhile it would be nice to have the language be able to do it, the fact that you can't today leads to some tidy separation of concerns for parallelization. For instance, many people I've talked to use things like Spark or dask to get high scale on data processing tasks. That means that all of the management of distributed jobs is handled through an easily googleable framework that your ops team can manage, as opposed to needing to build all of that yourself. I see this as being a nice stopgap solution for those who are too big for single-threaded but not big enough to need Spark.
- deleted 5y ago[deleted]
- ketozhang 5y agoIt's very interesting you mentioned ETL tasks. In ETL batch jobs, a unit in the batch is defined small enough to rarely be CPU bound; rather, as you mentioned, it is I/O bound. In what situation must you define a unit of work to be so heavily CPU bound? To me that's a smell for too large of a unit.
- heavyset_go 5y agoI'm using ETL as shorthand for a "I wrote a script at home that parses my data and puts it in a database, and threads might save time" situation. I wouldn't reach for a thread pool for anything serious.
- zone411 5y agoNote that Python's poor single-threaded performance compared to single-threaded performance of other languages makes the ability to multi-thread that much more crucial. You can sometimes get away with 10x slower code but not 100x slower. I've had to rewrite my Python code in another language in 3 different projects already (multi-processing wasn't an option) and I'm not even a heavy user. Removing GIL would be very welcome.
- dragonwriter 5y ago> You can sometimes get away with 10x slower code but not 100x slower. That Python and other languages in its speed class are still used for new projects in production demonstrates that you can, often, get away with 100× slower code. But, sure, you can get away with 10× slower more often.
- Fiahil 5y agoThink about the datascience use case: you need to load data from disk or network as fast as possible and compute a lot of CPU-bound operations right after that. Threads will allow you to split your I/O in multiple procedures, so you might start computations as soon as possible when the data is ready. They will also allow you to massively speed up aggregates without having to create a new process each time (which doesn't allow you to share memory). Threads are a BIG issue when you don't want to rely on asyncio[1]. Note [1]: Asyncio pools are single-threaded because of the GIL. This is already bad enough in practice, but they also perform very badly in CPU-bound contexts. This make them an absolute no-go when dealing with datascience code: a cpu-bounded core in an i/o-bounded wrapper.
- alanfranz 5y agoYou can release the GIL in extensions, and a lot of datascience libraries do that, so not all python computations are single threaded.
- Fiahil 5y agoSupport is partial and uneven. Moreover, you don't generally use a single datascience library, it's often a mix of pandas, numpy, scikit-learn, custom algorithms, custom optimization suite, and arrow. Letting individual library release the GIL is nice, but you need deep knowledge of those library to know what computation are thread-able or not.
- xmcqdpt2 5y agoIn practice, for single-machine workloads, it's currently mostly numpy and/or whatever deep learning framework you use that does the number crunching. This means that provided the code is operating on sufficiently large amounts of data (such that calls to numpy are each of sufficient duration), the multithreading in BLAS / Lapack within numpy usually give you weak scaling wrt to thread count without any tricks. The issue however is that this require by hand making everything into structs of arrays from arrays of structs, removing as many iterations from python as possible, potentially balancing thread usage within python and within numpy etc. By this point IMO your "python" code looks more like Fortran or SQL with better string IO...
- karmasimida 5y agoRemoving GIL brings flexibility too. Assuming now you have a big dictionary, which contains tens of millions of records to be filtered upon, another say TB of data. In current Python land, you either: 1. Using multi-processing, but each process needs to create its own dictionary 2. Or create an external DB, and using the DB's client to retrieve data in certain way. This pattern has occurred again and again in my use case, and it is always messy to solve in Python. Had Python has true multi-threading, then sharing some big but read-only object among real threads would be a possibility, and believe me, a lot of people would be really happy.