Why is he forgetting about concurrency? There seem to be plenty of tools for managing concurrency right now in Python, and they are working fine for me.
What languages are you considering that have a better story here? Note that better story has to mean more than "syntax-level support" -- I run highly concurrent services in Python right now using Twisted without language level support, and it's not always obvious in which ways language level support would make things nicer in ways that aren't already implemented (e.g generators + @inlineCallbacks).
2. You can't parallelize computation if it's written in Python. (Yeah, yeah, concurrency is different from parallelism, but there is a lot of overlap.) Even if it's written in a different language, the granularity is constrained due to the GIL.
1. I don't, but that's an entirely different story.
2. Sure I can :) Usually this means deferToThreading with things that release the GIL, sometimes it means multiple processes, both of which have quite good tools in Python. Not that they can't afford to be better, but I've never thought "man, the GIL is really holding me back now" -- despite having dealt with projects that are almost entirely about heavy computation.
Have you tried using PyPy and gevent? In a well-designed benchmark[1], it outperforms Node.js. That means it's at least competitive when it comes to concurrency... right? The GIL is not a big deal because shared state concurrency is a fundamentally broken model.
The GIL is not a big deal because shared state concurrency is a fundamentally broken model.
This depends on the problem domain. A lot of the code I write is limited by memory bandwidth. The number of outstanding memory requests is limited by hardware, so saturating the memory bandwidth, especially when many active memory streams are needed, requires several cores to participate. A particularly useful approach now is for threads running on those cores sharing a particular cache level/prefetch unit to perform software "buddy prefetch" while working together on a traversal. The threads are weakly synchronized by memory dependencies, sharing both cache and bandwidth.
If you remove shared state, the threads each need their own ghost region and cannot share cache and bandwidth. I avoid shared state, especially shared mutable state, whenever possible, but there are still plenty of cases where it makes sense, especially at cache and NUMA domain granularity.
1. I don't use Python for this task, but libraries like numpy give you ready access to unboxed arrays. It's becoming common in scientific codes to glue together "dumb" numeric components (written in C or Fortran) using Python. Threading granularity is limited in this case due to the GIL, to the point where either "smarter" code must be pushed into the compiled language. To keep the "smart" code in Python, many projects end up using only MPI for parallelism. This was fine until recently, but with modern memory hierarchies and proliferation of cores within a node, it gives up enough performance to be an issue.
2. As I said above, you need to use multiple cores per memory bus to utilize the hardware bandwidth because there is a limited number of outstanding memory requests per core (or hardware thread). Remember that the max bandwidth realized by your application is bounded above by
independent of the theoretical bandwidth of the link. Additionally, when you use more hardware threads, you get access to more level 1 caches. On machines with non-inclusive L2/L3, this also means you can fit more in cache.
what are you talking about? everybody admits it but it's not an easy problem, otherwise it'd be solved by now. multiprocessing module helps a bit in scenarios where it makes sense to use multiple processes instead of threads for cpu-bound stuff; io-bound problems don't suffer from GIL that much.