> While standardization and support for [threaded] APIs has come a long way, their use is still predominantly restricted to system programmers as opposed to application programmers. One of the reasons for this is that APIs such as Pthreads are considered to be low-level primitives. Conventional wisdom indicates that a large class of applications can be efficiently supported by higher level constructs (or directives)…
Hell is a multi-threaded C++ program (2006)
11–20 of 129 posts
Re: Hell is a multi-threaded C++ program (2006)
#12> While standardization and support for [threaded] APIs has come a long way, their use is still predominantly restricted to system programmers as opposed to application programmers. One of the reasons for this is that APIs such as Pthreads are considered to be low-level primitives. Conventional wisdom indicates that a large class of applications can be efficiently supported by higher level constructs (or directives)…
Usually I will write a program that does the following:
1. Initialize global read-only data structures
2. Parallelize jobs across STDIN lines (or whatever)
3. Output results within a #pragma omp critical block
It works wonders, and is literally 5 additional lines of code to make a single-threaded program multithreaded with OMP. But only for some types of program. The concept is very similar to what GNU parallel does.
In short, threads are not the problem per se, they are just the wrong tool for the job if you have a multiple-readers multiple-writers situation. Message passing, databases, or something else are more appropriate in those cases. But you will pry my read only shared memory space out of my cold, dead hands.
Re: Hell is a multi-threaded C++ program (2006)
#13I've found message passing and thinking in transactions are pretty good architectural patterns for maintaining ones sanity. Message queues with spinlocks for performance critical code (mutexes are slow). The biggest sin generally is to disregard the overhead caused by thread management and thinking more threads makes the sofrware run faster. I've seen people try to parallellize a sequential program by just spawning m…
Re: Hell is a multi-threaded C++ program (2006)
#14I've found message passing and thinking in transactions are pretty good architectural patterns for maintaining ones sanity. Message queues with spinlocks for performance critical code (mutexes are slow). The biggest sin generally is to disregard the overhead caused by thread management and thinking more threads makes the sofrware run faster. I've seen people try to parallellize a sequential program by just spawning m…
The difference is when there's contention. A spinlock will burn CPU cycles but a mutex will yield to another thread or process (with some context switch overhead).
A spinlock should only be used when you know you're going to get it in the next microsecond or so. Or in kernel space when you don't have other options (e.g. interrupt handler). Anything else is just burning CPU cycles for nothing.
Mutex and condition variables (emphasis on the latter) are much more useful than spinlocks and atomics for general multithreaded programming.
Re: Hell is a multi-threaded C++ program (2006)
#15There is no need to use raw pthreads in modern C++, it comes equipped with a much more convenient and capable standard library module. I prefer working with channels, which are still missing from the library; but they are trivial to add: https://github.com/andreas-gone-wild/blog/blob/master/diy_cp...
I'm not actually sure that the C++ library does anything that pthreads doesn't - maybe std::lock, perhaps? - but it's more convenient to use (and it's not like pthreads is bad to start with...), and the pieces work well and fit together quite nicely. Some good use of move semantics. unique_lock is neat and you can do stuff like vector.
The C++ thread library works on Windows, too...
Re: Hell is a multi-threaded C++ program (2006)
#16https://chromium.googlesource.com/chromium/src/+/lkcr/docs/t...
Re: Hell is a multi-threaded C++ program (2006)
#17When designing C++ code for threading, you have to keep a few things in mind, but it's not particularly harder than on other languages with thread support. You generally want to create re-entrant functions which pass all of their state as input, and return all results as output, without modifying ant kind of global state. You can run any number of these in parallel without thread safety issues, or locks. When using multiple threads with shared data, you have to protect it with locks, but I generally use a single thread to access data of this sort which produces work for other threads to do, which can be queued or distributed any other way. Producer/consumer queues show up a lot in good designs, and your single-threaded choke points are usually a producer or a consumer, which allows thread fan-in or fan-out. (As a side note, Go really got this right with channels).
What leads to problems in threaded C++ programs is unprotected, shared state. Some C++ design patterns make life particularly hard, such as singletons, which are just a funny name for global variables. C++ gives you lots of ways to make something global accidentally - static member variables, arguments by reference, for instance.
True C++ hell is taking a single threaded C++ program and making it multi-threaded after the fact, but that's hell in any language which allows you to have globals of any sort and doesn't perform function calls within some kind of closure.
The article in this post is being a little reductionist. You don't need to pick a threading model - some of your threads can pass messages, others can use shared data, all in the same program. The lack of thread local storage is not an issue, because you partition the data so that no two threads are working on the same thing at the same time.
Re: Hell is a multi-threaded C++ program (2006)
#18So to check, I googled C++11 threads memory model, and it[0] looks like his main complaint isn't helped by C++ 11 threads, as they essentially allow shared state too. They are also a thin veneer over the OS threads, for unix types, pthreads I imagine. [0] http://en.cppreference.com/w/cpp/language/memory_model
[1] shameless plug: https://github.com/duneroadrunner/SaferCPlusPlus#asynchronou...
Re: Hell is a multi-threaded C++ program (2006)
#19I've found message passing and thinking in transactions are pretty good architectural patterns for maintaining ones sanity. Message queues with spinlocks for performance critical code (mutexes are slow). The biggest sin generally is to disregard the overhead caused by thread management and thinking more threads makes the sofrware run faster. I've seen people try to parallellize a sequential program by just spawning m…
An uncontended mutex is just as fast as a spinlock (on modern operating systems using a futex). It takes about 25 nanoseconds to lock it. The difference is when there's contention. A spinlock will burn CPU cycles but a mutex will yield to another thread or process (with some context switch overhead). A spinlock should only be used when you know you're going to get it in the next microsecond or so. Or in kernel space…
Outside of hard realtime code, there's zero reason to use spin locks.
Re: Hell is a multi-threaded C++ program (2006)
#20I've found message passing and thinking in transactions are pretty good architectural patterns for maintaining ones sanity. Message queues with spinlocks for performance critical code (mutexes are slow). The biggest sin generally is to disregard the overhead caused by thread management and thinking more threads makes the sofrware run faster. I've seen people try to parallellize a sequential program by just spawning m…
Is there a good message passing library for C++? Sounds like something for the stl to include.