Executors
So what are executors? Executors sit between tasks and their execution context, the way iterators sit between collections and algorithms. Executors could potentially do many things, for example:
- parallelize tasks (over multiple cores, for example)
- distribute tasks (over multiple machines or to GPUs, for example)
- sequence tasks (stitch tasks together over time)
- prioritize tasks (a task scheduled at a fixed time might trump a deferred task)
My take on multi-threading
- apply the rule of zero (mutexes)
- apply the motto: there can be only one! (thread)
Multi-threading 101 in a nutshell: if you can avoid it, do so.
Why, you might ask?
Some attributes of multi-threaded code:
- difficult to get right (write)
- difficult to understand (read)
- difficult to debug
- difficult to unit test
These are not good attributes for code to have in general. So is multi-threaded code evil? No, not by itself, but given these attributes it is better to avoid it if possible. Are there scenarios where multi-threading cannot be avoided? At first glance it would seem so:
- when interacting with or monitoring a component that does not support events
- when a system must remain responsive and execute long-running tasks at the same time
However, depending on how much control you have over the component, it can be avoided in both cases. (To do: describe how.)
Concurrency vs parallelism
As defined by Hartmut Kaiser:
- Concurrency: more than one thread is operating on the same dataset.
- Parallelism: threads do work independently, on separate datasets.
Unfinished… to be continued.
References
- Michael Wong’s slides: C++ executors to enable heterogeneous computing in tomorrow’s C++ today
- The talk on YouTube: itCppCon17 – C++ executors to enable heterogeneous computing in tomorrow’s C++ today (M. Wong) (skip to 0:55:00)
Leave a Reply