Monday 27 April 2009 - Filed under Code
So I’m reading Bartosz Milewski’s latest on extending the D type system to eliminate common causes of errors in multithreaded code, and I come across this fragment:
There are two major challenges in multithreaded programming:
- Avoiding races
- Preventing deadlocks
While his analysis is correct, from a program-correctness point of view, and he does offer reasonably cogent thoughts on how to solve at least the first of those issues, there’s something still missing that a lot of programmers I meet don’t quite understand. Usually it’s inexperienced programmers who have figured out their threading API of choice and are something like 90% there with getting their juicy nondeterministic crashes ironed out.
Here we go, the point so many seem to miss:
3. It’s all well and good to have a “correct” concurrent program, but unless you actually need all those cycles, GTFO my CPUs.
3. The objective is not to max out all the CPUs available to you.
There’s plenty of less-widely-discussed literature on the topic of Getting The Hell Off The Processor When You Don’t Need It, but to keep things short:
- Every thread should have something to wait on. If you’re waiting for IO, wait on it for god’s sake. If you’re waiting for a signal, wait on it. On POSIX systems, you’ve got select(), poll(), epoll(), and no doubt another half-dozen options. On Win32, you’ve got select() if you’re doing sockets, or WaitForMultipleObjects[Ex] for everything else. And…
- If a thread has nothing worthwhile to do, it SHOULD be waiting on something. Nothing to do – get off my runnable queue. I didn’t really intend that, but it works.
- Mucking with win32 thread priorities, especially with some half-baked last-millennium notion of “make worker threads low-priority” is almost always a waste of time and lead to tuning headaches in maintenance. The low-priority myth comes from an assumption that your worker threads always have stuff to do – that is, unless you decrease their share of your CPU, they’re going to compromise the responsiveness of your UI, or something. Since points (1) and (2) apply to workers and UI threads in those kinds of programs, that’s pretty bogus. In most cases.
- If you call Sleep() under Win32, you’re almost certainly doing it wrong. The scheduler effects are NOT what you probably think they are.
2009-04-27 » admin