Concurrency in Python: CSP and Coroutines
bytes.yingw787.com
bytes.yingw787.com
Eventually I found and fell in love with gevent because I could write fairly straightforward code in a synchronous fashion and reason about the code a lot easier than other models. But then I found some warts with gevent: what about good community support? What about exploiting parallelism? Monkey patching 3rd party libs is a bit ugly and not 100% without faults.
So imagine how I felt when I found that Go offers this model of concurrency CSP with support for parallelism due to the M to N threading model. Also a not quite but close enough Python looking syntax and at that point I never looked back.
Sure there other models of concurrency and other languages that are also proving to be useful. But Go has been a good bet...at least for now.
And I know this is controversial...but Go’s time is running out...other languages are getting there with more advanced support for asynchronous programming...so I imagine in due time I’ll be onto the next thing.
My experience with golang was pretty short; this was back in the days of `go get` and I just couldn't get used to the dependency management system. I think others have had the same problem: https://bluxte.net/musings/2018/04/10/go-good-bad-ugly
IMHO a language is a combination of different factors: the community, the spec, the libraries, the support, the toolchain, etc. and the concurrency model is only one small part of that. If your concurrency model is CSP, the truer that statement may be, because CSP allows you to write highly stateful code, and because given time all user code trends towards the properties of the language and CSP doesn't really enforce a whole lot.
I did a deep dive on thespian instead, I think it’s used at scale by GoDaddy. One of the issues I ran into with both libraries is that there’s not much of an OTP-like library built on top of them, which makes them difficult for production usage.
At least for Thespian, it allows you to use different system bases like multiprocTCPBase or multiprocUDPbase to run your actors on, which all inherit from a common systemBase class, so you can swap out your base without changing your user code. It's nice for testing b/c you can explicitly split debugging overhead into different parts based on the systemBase you use.
But yeah, one of the difficulties of using these Python concurrency libraries is that the language and runtime don't really help you out. You have to retrofit a lot of your own stuff on the language to enforce certain properties of the model.
Reminds me of a discussion with Guido van Rossum about adding Go's goroutines to Python:
https://groups.google.com/d/topic/python-tulip/BO3KPIgQ_x4/d...
Russ Cox also makes Guido's point of how channels are baked into golang's runtime, whereas a Python channel would be implemented as an object on top of the runtime. Very interesting to see how things similar at face value differ underneath the hood.
Are you trying to number-crunch across many machines? In that case, I guess MPI is standard, but how is CSP related to this?
If you're trying to concurrently download ten files, why not just use asyncio/trio and async/await? You're mentioning await/async, but you're not explaining how it is relevant to either MPI or CSP, or whatever this blog post is about.
You claim that CSP helps "efficiently abstracting away dependencies on underlying hardware", but how is this relevant to CSP? Any decent piece of software is portable, it isn't a property of CSP. "CSP provides [abstraction from hardware primitives] by multiplexing and scheduling coroutines on top of a CPU thread pool". Well, which concurrency frameworks don't do that?
This is mostly an academic exercise for me personally. I’m not familiar with different concurrency models as I’m starting off in my career and don’t get a whole lot of exposure to it in production. I was inspired by Paul Butcher’s book on seven concurrency models in seven weeks, where we actually does solve problems with different concurrency models in languages that have good support for them. So I thought if I could write down my thoughts and explain it to other people I will have gained some sticky understanding for me.
I think Paul took a year or more in order to research and write his book, and it shows. Conversely it shows how my posts are sort of link aggregations because this series has taken about two months so far. Python’s also not terribly great for CPU-bound concurrency work in Python code.
As to your points, I saw MPI and async await as primitive constructs on top of which you could build something like CSP. Not all software is portable; one example, if you want MKL acceleration in numpy, you have to use Intel CPUs.
The next blog post I’m writing I’m writing about is hardware-based parallelism. IMHO this is Python’s bread and butter, and I should be able to demonstrate how Python comes in handy with code samples.
I was reviewing gevent (greenlets plus event loop) but that didn’t make it into the post, I’ll take another look at mpi4py!